UNPKG

3.69 kBJavaScriptView Raw
1(function (Prism) {
2
3 var expressionDef = /\{[^\r\n\[\]{}]*\}/;
4
5 var params = {
6 'quoted-string': {
7 pattern: /"(?:[^"\\]|\\.)*"/,
8 alias: 'operator'
9 },
10 'command-param-id': {
11 pattern: /(\s)\w+:/,
12 lookbehind: true,
13 alias: 'property'
14 },
15 'command-param-value': [
16 {
17 pattern: expressionDef,
18 alias: 'selector',
19 },
20 {
21 pattern: /([\t ])\S+/,
22 lookbehind: true,
23 greedy: true,
24 alias: 'operator',
25 },
26 {
27 pattern: /\S(?:.*\S)?/,
28 alias: 'operator',
29 }
30 ]
31 };
32
33 Prism.languages.naniscript = {
34 // ; ...
35 'comment': {
36 pattern: /^([\t ]*);.*/m,
37 lookbehind: true,
38 },
39 // > ...
40 // Define is a control line starting with '>' followed by a word, a space and a text.
41 'define': {
42 pattern: /^>.+/m,
43 alias: 'tag',
44 inside: {
45 'value': {
46 pattern: /(^>\w+[\t ]+)(?!\s)[^{}\r\n]+/,
47 lookbehind: true,
48 alias: 'operator'
49 },
50 'key': {
51 pattern: /(^>)\w+/,
52 lookbehind: true,
53 }
54 }
55 },
56 // # ...
57 'label': {
58 pattern: /^([\t ]*)#[\t ]*\w+[\t ]*$/m,
59 lookbehind: true,
60 alias: 'regex'
61 },
62 'command': {
63 pattern: /^([\t ]*)@\w+(?=[\t ]|$).*/m,
64 lookbehind: true,
65 alias: 'function',
66 inside: {
67 'command-name': /^@\w+/,
68 'expression': {
69 pattern: expressionDef,
70 greedy: true,
71 alias: 'selector'
72 },
73 'command-params': {
74 pattern: /\s*\S[\s\S]*/,
75 inside: params
76 },
77 }
78 },
79 // Generic is any line that doesn't start with operators: ;>#@
80 'generic-text': {
81 pattern: /(^[ \t]*)[^#@>;\s].*/m,
82 lookbehind: true,
83 alias: 'punctuation',
84 inside: {
85 // \{ ... \} ... \[ ... \] ... \"
86 'escaped-char': /\\[{}\[\]"]/,
87 'expression': {
88 pattern: expressionDef,
89 greedy: true,
90 alias: 'selector'
91 },
92 'inline-command': {
93 pattern: /\[[\t ]*\w[^\r\n\[\]]*\]/,
94 greedy: true,
95 alias: 'function',
96 inside: {
97 'command-params': {
98 pattern: /(^\[[\t ]*\w+\b)[\s\S]+(?=\]$)/,
99 lookbehind: true,
100 inside: params
101 },
102 'command-param-name': {
103 pattern: /^(\[[\t ]*)\w+/,
104 lookbehind: true,
105 alias: 'name',
106 },
107 'start-stop-char': /[\[\]]/,
108 }
109 },
110 }
111 }
112 };
113 Prism.languages.nani = Prism.languages['naniscript'];
114
115 /** @typedef {InstanceType<import("./prism-core")["Token"]>} Token */
116
117 /**
118 * This hook is used to validate generic-text tokens for balanced brackets.
119 * Mark token as bad-line when contains not balanced brackets: {},[]
120 */
121 Prism.hooks.add('after-tokenize', function (env) {
122 /** @type {(Token | string)[]} */
123 var tokens = env.tokens;
124 tokens.forEach(function (token) {
125 if (typeof token !== "string" && token.type === 'generic-text') {
126 var content = getTextContent(token);
127 if (!isBracketsBalanced(content)) {
128 token.type = 'bad-line';
129 token.content = content;
130 }
131 }
132 });
133 });
134
135 /**
136 * @param {string} input
137 * @returns {boolean}
138 */
139 function isBracketsBalanced(input) {
140 var brackets = "[]{}";
141 var stack = [];
142 for (var i = 0; i < input.length; i++) {
143 var bracket = input[i];
144 var bracketsIndex = brackets.indexOf(bracket);
145 if (bracketsIndex !== -1) {
146 if (bracketsIndex % 2 === 0) {
147 stack.push(bracketsIndex + 1);
148 } else if (stack.pop() !== bracketsIndex) {
149 return false;
150 }
151 }
152 }
153 return stack.length === 0;
154 };
155
156 /**
157 * @param {string | Token | (string | Token)[]} token
158 * @returns {string}
159 */
160 function getTextContent(token) {
161 if (typeof token === 'string') {
162 return token;
163 } else if (Array.isArray(token)) {
164 return token.map(getTextContent).join('');
165 } else {
166 return getTextContent(token.content);
167 }
168 }
169
170})(Prism);