前端代碼編輯器ace 語法驗證

本文主要是介紹實際項目中如何加入語法檢測功能。官方文檔連接https://github.com/ajaxorg/ace/wiki/Syntax-validationphp


      代碼編輯器ace,使用webworker進行實時語法檢查。目前支持JavaScript,json,php,coffeescript,css,xquery模式。
      根據官方https://ace.c9.io/#nav=higlighter的例子,在項目開發中,新增了Formula的語法高亮,下面是定義Mode並增長語法高亮的部分代碼
      //parserNet是parser模塊,在發生錯誤的時候會主動調用parseError方法css

      至於怎麼實現語法檢測的功能,比較複雜,涉及到編譯原理,語法詞法分析的知識。這個我瞭解的也只是入門,有時間的時候再介紹吧mysql

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模式webpack

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);
相關文章
相關標籤/搜索