Search code examples
javascripthtmlace-editor

How to correctly load ACE editor script and add self-defined highlighting rule script?


I am making an editor for LPMLN language which currently has no highlighting support in ACE editor. I tried to embed the script as guide in my index.html site but I can't add it locally with local relative path. So I can only try the CDN way by adding the URL of the script, which works. However, then I defined the highlighting rules in highlighting javascript files. So the URL way won't work since the existing library has no such files. Then I tried to post the code on github and copy the CDN link to load my script, but it can't seem to work. I have tested my highlighting file in mode creator link: https://ace.c9.io/tool/mode_creator.html and it gives the right highlighting display.

This is my html code(from body):

<body>

<div id="editor">%example:
1:go_out(today,a):-not rain(today),free(a,today).
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.2/ace.js" type="text/javascript"></script>
<script src="https://raw.githack.com/BobHuNanjing/myeditor/master/ace/mode/mode-lpmln" type="text/javascript" charset="utf-8"></script>


<script>
    var editor = ace.edit("editor");
    editor.setTheme("ace/theme/monokai");
    editor.session.setMode("ace/mode/lpmln");
</script>
<app-root></app-root>
</body>
</html>

And here is my highlighting js file:

define('ace/mode/lpmln',function(require, exports, module) {
    "use strict";
    var oop = require("../lib/oop");
    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
    /* --------------------- START ----------------------------- */
    var LpmlnHighlightRules = function() {
    this.$rules = {
    "start" : [
    {
        "token" : "keyword.other.define",
        "regex" : "(\\:-)"
    },
    {
        "token" : "keyword.operator.naf",
        "regex" : "((not))"
    },
    {
        "token" : "keyword.operator.neg",
        "regex" : "([\\-])"
    },
    {
        "token" : "markup.underline.weight",
        "regex" : "(\\d+:)"
    },
    {
        "token" : "string.regexp",
        "regex" : "(^\\w+(\\.*\\d{0,2})([+*/-]\\w+(\\.*\\d{0,2}))+)"
    },
    {
        "token" : "comment.line.percentage",
        "regex" : "(\\%.*)"
    },
    {
        "token" : "support.varaiable",
        "regex" : "([\\(\\)])"
    },
    {
        "token" : "variable.parameter",
        "regex" : "(?<=\\().*?(?=\\,)|(?<=\\,).*?(?=\\))"
    },
    {
        defaultToken : "text",
    }
    ]
    };
    this.normalizeRules();
    };
    /* ------------------------ END ------------------------------ */
    oop.inherits(LpmlnHighlightRules, TextHighlightRules);
    exports.LpmlnHighlightRules = LpmlnHighlightRules;
    });

As I can see, the theme is correctly loaded, which must be existing under the path of the cloudflare CDN. But my script was not loaded. I have also tried ace.config.setModuleUrl('ace/mode/lpmln',"https://raw.githack.com/BobHuNanjing/myeditor/master/ace/mode/mode-lpmln.js"), the console shows no error but nothing highlighting displays.

So how should I correctly import the ace.js and how to correctly add a new highlighting js file and make it work?


Solution

  • To define syntax for Ace you need both highlight rules and a mode that controls folding autoindent, etc., see https://github.com/ajaxorg/ace-builds/blob/0d62c26de7b2e1922d8dd95ba587c9845c018c51/src/mode-json.js#L257 and https://ace.c9.io/#nav=higlighter

    Here is a snippet that modifies your example to work by adding mode definition

    define('ace/mode/lpmln',function(require, exports, module) {
    "use strict";
    var oop = require("../lib/oop");
    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
    
    
    // to define highlighting we need mode and highlight rules
    // normally highlight rules are defined in a separate file, 
    // but since this is used only in one place, this function is directly in the mode
    var LpmlnHighlightRules = function() {
        this.$rules = {
        "start" : [
        {
            "token" : "keyword.other.define",
            "regex" : "(\\:-)"
        },
        {
            "token" : "keyword.operator.naf",
            "regex" : "((not))"
        },
        {
            "token" : "keyword.operator.neg",
            "regex" : "([\\-])"
        },
        {
            "token" : "markup.underline.weight",
            "regex" : "(\\d+:)"
        },
        {
            "token" : "string.regexp",
            "regex" : "(^\\w+(\\.*\\d{0,2})([+*/-]\\w+(\\.*\\d{0,2}))+)"
        },
        {
            "token" : "comment.line.percentage",
            "regex" : "(\\%.*)"
        },
        {
            "token" : "support.varaiable",
            "regex" : "([\\(\\)])"
        },
        {
            "token" : "variable.parameter",
            "regex" : "(?<=\\().*?(?=\\,)|(?<=\\,).*?(?=\\))"
        },
        {
            defaultToken : "text",
        }
        ]
        };
        this.normalizeRules();
        };
    /* ------------------------ END ------------------------------ */
    oop.inherits(LpmlnHighlightRules, TextHighlightRules);
    exports.LpmlnHighlightRules = LpmlnHighlightRules;
    
    var oop = require("../lib/oop");
    var TextMode = require("./text").Mode;
    var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
    var CStyleFoldMode = require("./folding/cstyle").FoldMode;
    
    var Mode = function() {
        this.HighlightRules = LpmlnHighlightRules;
        this.$behaviour = new CstyleBehaviour();
        this.foldingRules = new CStyleFoldMode();
    };
    oop.inherits(Mode, TextMode);
    
    (function() {
        this.$id = "ace/mode/lpmln";
    }).call(Mode.prototype);
    
    exports.Mode = Mode
    });
    
    // after the mode is defined initialize the editor
    // this can be in another file, but this playground doesn't allow to create multiple files
    var editor = ace.edit("editor");
    editor.setTheme("ace/theme/monokai");
    editor.session.setMode("ace/mode/lpmln");
    #editor{ height: 100px }
    <!--include ace-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.2/ace.js" type="text/javascript"></script>
    <!--include one of modes if you use behavior or folding rules-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.2/mode-json.js" type="text/javascript"></script>
    
    <div id="editor" >%example:
    1:go_out(today,a):-not rain(today),free(a,today).
    </div>