textarea里面实现语法高亮

背景

工作中遇到了一个需求, 需要在前端页面弹出框里面, 一个textarea编辑器里面, 实现自定义规则的语法高亮

使用到的工具

开源项目 https://github.com/lonekorean/highlight-within-textarea 参考文档 https://lonekorean.github.io/highlight-within-textarea/

具体使用步骤

  1. 克隆项目代码
     git clone git@github.com:lonekorean/highlight-within-textarea.git
    
  2. 将代码拷贝进自己项目的静态目录文件夹内. 我放到了 static/lib/highlight-within-textarea 这里.
  3. 用本地文件的方式打开index.html可以看到实现的而效果. 我们可以参照着项目里index.html来写自己的.
  4. 在html中引入依赖, 设置一些样式

     <link href="/static/lib/highlight-within-textarea/jquery.highlight-within-textarea.css" rel="stylesheet">
     <script src="/static/lib/highlight-within-textarea/jquery.highlight-within-textarea.js"></script>
     <style>
       .hwt-container {
         background-color: #f8f9fa;
       }
    
       .hwt-content {
         width: 833px;
         height: 500px;
         border: 1px solid #adb5bd;
         color: transparent;
         caret-color: black; /* Edge ignores this, but luckily doesn't need it */
    
       }
    
       .hwt-highlights {
         color: black !important;
       }
    
       .hwt-input:focus {
         outline-color: #495057;
       }
    
       .hwt-content mark {
         color: #8B008B;
         background-color: transparent;
       }
    
       .hwt-content mark.red {
         color: #DC143C;
       }
    
       .hwt-content mark.blue {
         color: #00BFFF;
       }
    
       .hwt-content mark.yellow {
         color: #F4A460;
       }
    
       .hwt-content mark.green {
         color: #008080;
       }
     </style>
    
  5. 在js当中, 设置语法高亮

    $(document).ready(function () {
      function match_keyword(input) {
        let keywords = [/rule\s/gi, /meta:\s/gi, /strings:\s/gi, /condition:\s/gi, /\sat\s/gi, /\sand\s/gi, /\sof\s/gi, /\scontains\s/gi,]
        var l = [];
        for (r of keywords) {
          var match = r.exec(input);
          while (match != null) {
            let s = match[0];
            l.push(s);
            match = r.exec(input);
          }
        }
        return l || false;
      }
    	
      function match_double_qoute_string(input) {
        var l = [];
        r = /"(?:\\.|[^\\"])*"/gi;
        var match = r.exec(input);
        while (match != null) {
          let s = match[0];
          l.push(s);
          match = r.exec((input))
        }
        return l || false;
      }
    	
      let hightlightOptions = {
        highlight: [
      // 关键字
          {
            highlight: match_keyword,
          },
          // 不在字符串里的数字
          {
            highlight: /[^"^\w]\d+[^"^\w]/gi,
            className: "green",
          },
    	
      // 双引号
          {
            highlight: match_double_qoute_string,
            className: 'red',
          },
          // 注释
          {
            highlight: /\/\/[^\n]*/gi,
            className: 'yellow',
          },
        ]
      };
            $("#yararule_textarea_many").highlightWithinTextarea(hightlightOptions);
            $('#yararule_textarea_many_edit').highlightWithinTextarea(hightlightOptions);
    	
    

} ```

  1. 这里要注意, 如果是点击按钮, 获取数据显示到在弹出的窗口中, 光使用 $("#xxx").val(message) 的话,高亮不会自动完成. 还需要调用 $('#xxx').highlightWithinTextarea('update'); 才行

      $("#yararule_list_tbody").on('click', '.yararule_edit_many', function () {
                     // 清除数据
                     clear_add_yara_div();
                   // 组装form数据
                     $("#action_type").val('edit_many');
                     var ruleset_name = $("#ruleset_name_origin").val();
     
                     var data = "ruleset_name=" + ruleset_name + "&query_items=query_ruleset";
                     // 发起请求
                     result = ajax_get_info(data, '/yararule_modify');
                     // 设置回显
                     $("#yararule_textarea_many_edit").val(result.ruleset_s);
                     $("#yararule_div").modal('show');
                     $("#edit_many_li").click();
                     // 必须调用这个update, 要不然只用val更改了的值无法自动高亮
                                           $('#yararule_textarea_many_edit').highlightWithinTextarea('update');
             });
    

    效果如图, 点击之前 点击之后