前端代码编辑器ace 语法验证

时间:2023-03-09 22:12:15
前端代码编辑器ace 语法验证

本文主要是介绍实际项目中如何加入语法检测功能。官方文档链接https://github.com/ajaxorg/ace/wiki/Syntax-validation

代码编辑器ace,使用webworker进行实时语法检查。目前支持JavaScript,json,php,coffeescript,css,xquery模式。
      根据官方https://ace.c9.io/#nav=higlighter的例子,在项目开发中,新增了Formula的语法高亮,下面是定义Mode并增加语法高亮的部分代码
      //parserNet是parser模块,在发生错误的时候会主动调用parseError方法

至于怎么实现语法检测的功能,比较复杂,涉及到编译原理,语法词法分析的知识。这个我了解的也只是入门,有时间的时候再介绍吧

ace.define("ace/mode/formula", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text", "ace/mode/formula_highlight_rules"], function (acequire, exports, module) {

    var oop = acequire("../lib/oop");
var TextMode = acequire("./text").Mode;
var FormulaHighlightRules = acequire("./formula_highlight_rules").FormulaHighlightRules; var Mode = function () {
this.HighlightRules = FormulaHighlightRules;
this.$behaviour = this.$defaultBehaviour;
};
oop.inherits(Mode, TextMode); (function () {
this.lineCommentStart = "//";
this.$id = "ace/mode/formula"; this.createWorker = function (session) {
var worker = {
//编辑器销毁或修改模式的时候
terminate: function () {
session.clearAnnotations(); //清除错误信息
this.$worker = null;
if (this.$doc)
this.$doc.off("change", this.changeListener);
this.changeListener = null;
this.$doc = null;
},
//文档变化的回调
_changeListener: function () {
if (!this.$doc) return;
var val = this.$doc.getValue();
if (val.trim() === "") {
session.clearAnnotations(); //清除错误信息
return;
}
var res = [];
//重写parserNet.parseError方法,收集错误信息
parserNet.parseError = function (str, obj) {
var column = obj.loc ? obj.loc.first_column : 0;
res.push({
column: column,
raw: str,
row: obj.line,
text: str,
type: "error"
})
}
try {
//parserNet.parse实时检测代码功能
parserNet.parse(val);
} catch (e) {
}
session.setAnnotations(res)//显示错误信息
},
//绑定文档对象的时候
attachToDocument(doc) {
if (this.$doc)
this.terminate();
this.$doc = doc;
this.changeListener = _.debounce(this._changeListener.bind(this), 500);
this.changeListener();
//绑定change文档事件
doc.on("change", this.changeListener);
},
//响应weoker中发出的消息,this.sender.emit("annotate",[])消息,也可以定义其他的消息名称
annotate(results) {
session.setAnnotations(results);
}
};
//绑定文档
worker.attachToDocument(session.getDocument());
return worker;
};
}).call(Mode.prototype);

在实际项目中,有可能是给ace已存在的高亮增加语法检测,下面是webpack打包项目中的写法,主要参考怎么引用已存在的ace模式

import 'brace/mode/mysql.js'
import {parserMySql} from '../mysql/mysqlParser.js';
var MysqlMode = ace.acequire("ace/mode/mysql").Mode;
(function () {
this.createWorker = function (session) {
var worker = {
terminate: function () {
session.clearAnnotations();
this.$worker = null;
if (this.$doc)
this.$doc.off("change", this.changeListener);
this.changeListener = null;
this.$doc = null;
},
_changeListener: function () {
if (!this.$doc) return;
var val = this.$doc.getValue();
var res = [];
parserMySql.parseError = function (str, obj) {
var column = obj.loc ? obj.loc.first_column : 0;
res.push({
column: column,
raw: str,
row: obj.line,
text: str,
type: "error"
})
}
if (val.trim().length === 0) {
res.push({
column: 0,
raw: "该字段不能为空",
row: 0,
text: "该字段不能为空",
type: "error"
})
} else {
try {
parserMySql.parse(val);
} catch (e) {
}
}
session.setAnnotations(res)
},
attachToDocument(doc) {
if (this.$doc)
this.terminate();
this.$doc = doc;
this.changeListener = _.debounce(this._changeListener.bind(this), 500);
this.changeListener();
doc.on("change", this.changeListener);
},
annotate(results) {
session.setAnnotations(results);
}
};
worker.attachToDocument(session.getDocument());
return worker;
};
}).call(MysqlMode.prototype);