Skip to content

Commit 4e8926e

Browse files
authored
feat: add highlight mode for Apache JEXL (#4979)
1 parent 0c49167 commit 4e8926e

File tree

5 files changed

+338
-0
lines changed

5 files changed

+338
-0
lines changed

demo/kitchen-sink/docs/jexl.jexl

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pragma execution.option 42
2+
3+
##
4+
## This is a test script
5+
##
6+
7+
/* This is
8+
a multi-line
9+
comment
10+
*/
11+
if (out != null and result == null) out.println("The result is " + result);
12+
x = ~/\w+\/test/;
13+
y = 2;
14+
result = x * y + 5;
15+
if (out != null) out.println("The result is " + result);
16+
17+
@lenient @silent x.someMethod();
18+
19+
`multi-line string
20+
with ${var interpolation = "Hey!"} and \escap\u00E9 chars`

src/ext/modelist.js

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ var supportedModes = {
111111
Jade: ["jade|pug"],
112112
Java: ["java"],
113113
JavaScript: ["js|jsm|jsx|cjs|mjs"],
114+
JEXL: ["jexl"],
114115
JSON: ["json"],
115116
JSON5: ["json5"],
116117
JSONiq: ["jq"],

src/mode/_test/tokens_jexl.json

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
[[
2+
"start",
3+
["comment","#pragma"],
4+
["text"," execution.option 42"]
5+
],[
6+
"start"
7+
],[
8+
"start",
9+
["comment","##"]
10+
],[
11+
"start",
12+
["comment","## This is a test script"]
13+
],[
14+
"start",
15+
["comment","##"]
16+
],[
17+
"start"
18+
],[
19+
"comment",
20+
["comment","/* This is"]
21+
],[
22+
"comment",
23+
["comment","a multi-line"]
24+
],[
25+
"comment",
26+
["comment","comment"]
27+
],[
28+
"start",
29+
["comment","*/"]
30+
],[
31+
"start",
32+
["keyword","if"],
33+
["text"," "],
34+
["lparen","("],
35+
["identifier","out"],
36+
["text"," "],
37+
["keyword.operator","!="],
38+
["text"," "],
39+
["constant.language","null"],
40+
["text"," "],
41+
["keyword","and"],
42+
["text"," "],
43+
["identifier","result"],
44+
["text"," "],
45+
["keyword.operator","=="],
46+
["text"," "],
47+
["constant.language","null"],
48+
["rparen",")"],
49+
["text"," "],
50+
["identifier","out"],
51+
["punctuation","."],
52+
["identifier","println"],
53+
["lparen","("],
54+
["string","\"The result is \""],
55+
["text"," "],
56+
["keyword.operator","+"],
57+
["text"," "],
58+
["identifier","result"],
59+
["rparen",")"],
60+
["text",";"]
61+
],[
62+
"start",
63+
["identifier","x"],
64+
["text"," "],
65+
["keyword.operator","="],
66+
["text"," "],
67+
["string.regexp","~/\\w+"],
68+
["constant.language.escape","\\/"],
69+
["string.regexp","test/"],
70+
["text",";"]
71+
],[
72+
"start",
73+
["identifier","y"],
74+
["text"," "],
75+
["keyword.operator","="],
76+
["text"," "],
77+
["constant.numeric","2"],
78+
["text",";"]
79+
],[
80+
"start",
81+
["identifier","result"],
82+
["text"," "],
83+
["keyword.operator","="],
84+
["text"," "],
85+
["identifier","x"],
86+
["text"," "],
87+
["keyword.operator","*"],
88+
["text"," "],
89+
["identifier","y"],
90+
["text"," "],
91+
["keyword.operator","+"],
92+
["text"," "],
93+
["constant.numeric","5"],
94+
["text",";"]
95+
],[
96+
"start",
97+
["keyword","if"],
98+
["text"," "],
99+
["lparen","("],
100+
["identifier","out"],
101+
["text"," "],
102+
["keyword.operator","!="],
103+
["text"," "],
104+
["constant.language","null"],
105+
["rparen",")"],
106+
["text"," "],
107+
["identifier","out"],
108+
["punctuation","."],
109+
["identifier","println"],
110+
["lparen","("],
111+
["string","\"The result is \""],
112+
["text"," "],
113+
["keyword.operator","+"],
114+
["text"," "],
115+
["identifier","result"],
116+
["rparen",")"],
117+
["text",";"]
118+
],[
119+
"start"
120+
],[
121+
"start",
122+
["storage.type.annotation","@lenient"],
123+
["text"," "],
124+
["storage.type.annotation","@silent"],
125+
["text"," "],
126+
["identifier","x"],
127+
["punctuation","."],
128+
["identifier","someMethod"],
129+
["lparen","("],
130+
["rparen",")"],
131+
["text",";"]
132+
],[
133+
"start"
134+
],[
135+
"string",
136+
["string","`multi-line string"]
137+
],[
138+
"start",
139+
["string","with "],
140+
["lparen","${"],
141+
["keyword","var"],
142+
["text"," "],
143+
["identifier","interpolation"],
144+
["text"," "],
145+
["keyword.operator","="],
146+
["text"," "],
147+
["string","\"Hey!\""],
148+
["rparen","}"],
149+
["string"," and "],
150+
["constant.language.escape","\\"],
151+
["string","escap"],
152+
["constant.language.escape","\\u00E9"],
153+
["string"," chars`"]
154+
],[
155+
"start"
156+
]]

src/mode/jexl.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"use strict";
2+
3+
var oop = require("../lib/oop");
4+
var JexlHighlightRules = require("./jexl_highlight_rules").JexlHighlightRules;
5+
var TextMode = require("./text").Mode;
6+
var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
7+
var CStyleFoldMode = require("./folding/cstyle").FoldMode;
8+
9+
var Mode = function () {
10+
this.HighlightRules = JexlHighlightRules;
11+
this.$behaviour = new CstyleBehaviour();
12+
this.foldingRules = new CStyleFoldMode();
13+
};
14+
oop.inherits(Mode, TextMode);
15+
16+
(function () {
17+
this.lineCommentStart = ["//", "##"];
18+
this.blockComment = {start: "/*", end: "*/"};
19+
20+
this.$id = "ace/mode/jexl";
21+
}).call(Mode.prototype);
22+
23+
exports.Mode = Mode;

src/mode/jexl_highlight_rules.js

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
"use strict";
2+
3+
var oop = require("../lib/oop");
4+
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
5+
6+
var JexlHighlightRules = function () {
7+
8+
var keywords = "return|var|function|and|or|not|if|for|while|do|continue|break";
9+
var buildinConstants = "null";
10+
var supportFunc = "empty|size|new";
11+
12+
var keywordMapper = this.createKeywordMapper({
13+
"keyword": keywords,
14+
"constant.language": buildinConstants,
15+
"support.function": supportFunc
16+
}, "identifier");
17+
18+
var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
19+
"u[0-9a-fA-F]{4}|" + // unicode
20+
"u{[0-9a-fA-F]{1,6}}|" + // es6 unicode
21+
"|.)";
22+
23+
// regexp must not have capturing parentheses. Use (?:) instead.
24+
// regexps are ordered -> the first match is used
25+
26+
this.$rules = {
27+
"start": [
28+
{
29+
token: "comment",
30+
regex: "\\/\\/.*$"
31+
}, {
32+
token: "comment",
33+
regex: "##.*$"
34+
}, {
35+
token: "comment", // multi line comment
36+
regex: "\\/\\*",
37+
next: "comment"
38+
}, {
39+
token: ["comment", "text"],
40+
regex: "(#pragma)(\\s.*$)"
41+
}, {
42+
token: "string", // single line
43+
regex: '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
44+
}, {
45+
token: "string", // single line
46+
regex: "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
47+
}, {
48+
token: "string", // multi line string
49+
regex: "`",
50+
push: [
51+
{
52+
token: "constant.language.escape",
53+
regex: escapedRe
54+
}, {
55+
token: "string",
56+
regex: "`",
57+
next: "pop"
58+
}, {
59+
token: "lparen", //interpolation
60+
regex: "\\${",
61+
push: [
62+
{
63+
token: "rparen",
64+
regex: "}",
65+
next: "pop"
66+
}, {
67+
include: "start"
68+
}
69+
]
70+
}, {
71+
defaultToken: "string"
72+
}
73+
]
74+
}, {
75+
token: "constant.numeric", // hex
76+
regex: /0(?:[xX][0-9a-fA-F][0-9a-fA-F_]*|[bB][01][01_]*)[LlSsDdFfYy]?\b/
77+
}, {
78+
token: "constant.numeric", // float
79+
regex: /[+-]?\d[\d_]*(?:(?:\.[\d_]*)?(?:[eE][+-]?[\d_]+)?)?[LlSsDdFfYy]?\b/
80+
}, {
81+
token: "constant.language.boolean",
82+
regex: "(?:true|false)\\b"
83+
}, {
84+
token: "string.regexp",
85+
regex: "~/",
86+
push: [
87+
{
88+
token: "constant.language.escape",
89+
regex: "\\\\/"
90+
}, {
91+
token: "string.regexp",
92+
regex: "$|/",
93+
next: "pop"
94+
}, {
95+
defaultToken: "string.regexp"
96+
}
97+
]
98+
}, {
99+
token: keywordMapper,
100+
regex: "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
101+
}, {
102+
token: "keyword.operator",
103+
regex: "&&|\\|\\||!|&|\\||\\^|~|\\?|:|\\?\\?|==|!=|<|<=|>|>=|=~|!~|=\\^|=\\$|!\\$|\\+|\\-|\\*|%|\\/|="
104+
}, {
105+
token: "lparen",
106+
regex: "[[({]"
107+
}, {
108+
token: "rparen",
109+
regex: "[\\])}]"
110+
}, {
111+
token: "text",
112+
regex: "\\s+"
113+
}, {
114+
token: "punctuation",
115+
regex: "[,.]"
116+
}, {
117+
token: "storage.type.annotation",
118+
regex: "@[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
119+
}
120+
],
121+
"comment": [
122+
{
123+
token: "comment",
124+
regex: "\\*\\/",
125+
next: "start"
126+
}, {
127+
defaultToken: "comment"
128+
}
129+
]
130+
};
131+
132+
133+
this.normalizeRules();
134+
};
135+
136+
oop.inherits(JexlHighlightRules, TextHighlightRules);
137+
138+
exports.JexlHighlightRules = JexlHighlightRules;

0 commit comments

Comments
 (0)