首页 > 语言 > JavaScript > 正文

CodeMirror js代码加亮使用总结

2024-05-06 15:19:24
字体:
来源:转载
供稿:网友

CodeMirror是一个基于JavaScript的代码编辑器,CodeMirror支持大量语言的语法高亮,也包括css,html,js等的高亮显示。此外,CodeMirror还支持代码自动完成、搜索/替换、HTML预览、行号、选择/搜索结果高亮、可视化tab、代码自动格式等。

   CodeMirror源码的github地址:https://github.com/marijnh/CodeMirror/。这几天除了上课之外有空我都是在啃着它的源码,在网上相关资料基本一点都没找到,发觉看起来真是很吃力,这篇总结也只是说个大概原理,具体细节我也很多不明白,虽然很多代码都读得懂,但是串联起来有很大问题,没注释,源码大部分变量都是猜它的意思,大部分函数也真是知道个大概实现什么功能。  

   CodeMirror之所以能够支持这么多语言的高亮,是由于在它的mode包中定义了多种语言的解析方式,然后对外提供统一的接口。源码中也把这部分内容分为一个层次。下面我主要是对CodeMirror库自带的对JS和CSS代码加亮脚本为例进行了研究。

github:https://github.com/marijnh/CodeMirror/blob/master/mode/javascript/javascript.js

这个是它定义的js解析方式,下面我用mode.js代替该js文件
mode.js中主要定义了两个函数:

CodeMirror.defineMode("javascript",function(config,parserConfig){}CodeMirror.defineMIME("text/javascript", "javascript");

这两个define的作用主要是挂靠到CodeMirror这个主体类中

mode.js 对外提供的接口主要是:

return{  startState:function(basecolumn){...}  token:function(stream,state){...}  indent:function(state,textAfter){...}      }

现在解析这三个函数:

(1)startState:主要是定义函数解析执行的上下文环境,起始的状态,如果没有这个方法的话,相当于在解析过程中没有了语义。
startState键虽然不是必选但也十分重要,因为高亮往往涉及语境,即目前高亮的短语处于一个什么样的上下文中,通常影响语义和颜色的选取。所以需要一个startState来初始化一个状态物体,而这个状态物体具体包含什么内容完全由具体应用决定,CodeMirror没有硬性规定。
(2)token:这是最主要的解析语法函数,通过调用state.tokenize(stream,state)执行 function jsTokenBase(stream, state) {...},下面我会解析这个函数的主要内容.
(3)indent:这个是可有可无的

说下jsTokenBase这个函数,通过stream.next()读取下一个字符,并对字符进行判断,主要用到了正则匹配,返回的结果???

function jsTokenBase(stream,state){  var ch = stream.next();  if(ch == '”' || ch=”'”)    return ...;          //判断是否存在下个”或',return [“string”,”string”]  else if(/[/[/]{}/(/),;/:/.]/.test(ch))    return .. ;          //匹配[]{}()...这几个,return ch  else if(ch==”0” && stream.eat(/x/i)){    stream.eatwhile(/[/da-f]/i); //0x**,解析16进制数    return ret(“number”,”number”);//返回一个自己封装好的对象function ret(tp,style,cont)  }  else if(//d/.test(ch) || ch ==“”&&stream.eat(//d/))     return ret(“number”,”number”);//匹配数字  else if (ch == "/") {       //匹配注释    if(stream.eat(“*”)) return [“comment”,”comment”];     //判断“/*”    else if(stream.eat(“/”)) return [“comment”,”comment”];  //判断“//”else if (state.lastType == "operator" || state.lastType == "keyword c" || /^[/[{}/(,;:]$/.test(state.lastType)) {}                     //??    else if(stream.eatWhile(isOperatorChar)) return ret(“operator”); //判断/之后的操作符  }  else if(ch == "#") return [“error”,”error”]; //返回语句是错误的  else if(isOperatorChar.test(ch)) return ret(“operator”); //返回操作符  else { stream.eatWhile(/[/w/$_]/); return ..} //返回匹配字符串 }            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选