简单的 JSON 语法高亮

原创
2022/02/24 15:27
阅读数 533

HTML显示

<!-- html template -->
<pre id="jsonResult" class="json-result"></pre>
/* less/scss */

.json-result {
  border: 0;
  padding: 5px;
  background-color: #fff;
  font-size: 12px;

  .string {
    color: green;
  }

  .number {
    color: darkorange;
  }

  .boolean {
    color: blue;
  }

  .null {
    color: magenta;
  }

  .key {
    color: red;
  }
}

格式化

/**
 * JSON 格式化
 * @param {string} json 对象或字符串
 */
export function syntaxHighlight(json) {
  if (!json || json.length === 0) {
    return '';
  }
  if (typeof json !== 'string') {
    json = JSON.stringify(json, undefined, 2)
  }
  return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, function (match) {
    let cls;
    if (/^"/.test(match)) {
      cls = /:$/.test(match) ? 'key' : 'string'
    } else if (/true|false/.test(match)) {
      cls = 'boolean'
    } else if (/null/.test(match)) {
      cls = 'null'
    } else {
      cls = 'number'
    }
    return '<span class="' + cls + '">' + match + '</span>'
  })
}

// call
document.getElementById('jsonResult').innerHTML = syntaxHighlight(THE_JSON_OBJECT);

核心点

核心点就在这个正则表达式:

("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)


(
    "
    (    \\u[a-zA-Z0-9]{4}      |     \\[^u]     |     [^\\"]   )*
    "
    (\s*:)?       |       \b
    (true|false|null)
    \b      |     -?
    \d+
    (?:\.\d*)?
    (?:[eE][+-]?\d+)?
)

模式匹配

用到了不常见的JS正则表达式模式匹配(来自博客园

  • (?:pattern) 非获取匹配,匹配 pattern 但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry | industries”更简略的表达式。
  • (?=pattern) 非获取匹配,正向肯定预查,在任何匹配 pattern 的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3 .1 ”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
  • (?!pattern) 非获取匹配,正向否定预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000 )”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
  • (?<=pattern) 非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“ 2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
  • (?<!pattern) 非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“ 3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。

边界匹配

边界匹配(来自OSCHINA),更多(见博客园

  • \b只能匹配字母、数字、汉字、下划线
  • \b就近匹配,比如\bAB 匹配A,而AB\b 匹配B;但如果只写一个\b或者在两个字母、数字、汉字、下划线之间有\b时就在所有字符或者两个字母、数字、汉字、下划线之间所有字符去逐个匹配

举例:

/\bnice\b/.test("It's a nice day today.")   //    true
/\bnice\b/.test("It' nicely.")              //    false
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部