UNPKG

6.18 kBJavaScriptView Raw
1(function (Prism) {
2
3 Prism.languages.xquery = Prism.languages.extend('markup', {
4 'xquery-comment': {
5 pattern: /\(:[\s\S]*?:\)/,
6 greedy: true,
7 alias: 'comment'
8 },
9 'string': {
10 pattern: /(["'])(?:\1\1|(?!\1)[\s\S])*\1/,
11 greedy: true
12 },
13 'extension': {
14 pattern: /\(#.+?#\)/,
15 alias: 'symbol'
16 },
17 'variable': /\$[-\w:]+/,
18 'axis': {
19 pattern: /(^|[^-])(?:ancestor(?:-or-self)?|attribute|child|descendant(?:-or-self)?|following(?:-sibling)?|parent|preceding(?:-sibling)?|self)(?=::)/,
20 lookbehind: true,
21 alias: 'operator'
22 },
23 'keyword-operator': {
24 pattern: /(^|[^:-])\b(?:and|castable as|div|eq|except|ge|gt|idiv|instance of|intersect|is|le|lt|mod|ne|or|union)\b(?=$|[^:-])/,
25 lookbehind: true,
26 alias: 'operator'
27 },
28 'keyword': {
29 pattern: /(^|[^:-])\b(?:as|ascending|at|base-uri|boundary-space|case|cast as|collation|construction|copy-namespaces|declare|default|descending|else|empty (?:greatest|least)|encoding|every|external|for|function|if|import|in|inherit|lax|let|map|module|namespace|no-inherit|no-preserve|option|order(?: by|ed|ing)?|preserve|return|satisfies|schema|some|stable|strict|strip|then|to|treat as|typeswitch|unordered|validate|variable|version|where|xquery)\b(?=$|[^:-])/,
30 lookbehind: true
31 },
32 'function': /[\w-]+(?::[\w-]+)*(?=\s*\()/,
33 'xquery-element': {
34 pattern: /(element\s+)[\w-]+(?::[\w-]+)*/,
35 lookbehind: true,
36 alias: 'tag'
37 },
38 'xquery-attribute': {
39 pattern: /(attribute\s+)[\w-]+(?::[\w-]+)*/,
40 lookbehind: true,
41 alias: 'attr-name'
42 },
43 'builtin': {
44 pattern: /(^|[^:-])\b(?:attribute|comment|document|element|processing-instruction|text|xs:(?:anyAtomicType|anyType|anyURI|base64Binary|boolean|byte|date|dateTime|dayTimeDuration|decimal|double|duration|ENTITIES|ENTITY|float|gDay|gMonth|gMonthDay|gYear|gYearMonth|hexBinary|ID|IDREFS?|int|integer|language|long|Name|NCName|negativeInteger|NMTOKENS?|nonNegativeInteger|nonPositiveInteger|normalizedString|NOTATION|positiveInteger|QName|short|string|time|token|unsigned(?:Byte|Int|Long|Short)|untyped(?:Atomic)?|yearMonthDuration))\b(?=$|[^:-])/,
45 lookbehind: true
46 },
47 'number': /\b\d+(?:\.\d+)?(?:E[+-]?\d+)?/,
48 'operator': [
49 /[+*=?|@]|\.\.?|:=|!=|<[=<]?|>[=>]?/,
50 {
51 pattern: /(\s)-(?=\s)/,
52 lookbehind: true
53 }
54 ],
55 'punctuation': /[[\](){},;:/]/
56 });
57
58 Prism.languages.xquery.tag.pattern = /<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i;
59 Prism.languages.xquery['tag'].inside['attr-value'].pattern = /=(?:("|')(?:\\[\s\S]|\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}|(?!\1)[^\\])*\1|[^\s'">=]+)/i;
60 Prism.languages.xquery['tag'].inside['attr-value'].inside['punctuation'] = /^="|"$/;
61 Prism.languages.xquery['tag'].inside['attr-value'].inside['expression'] = {
62 // Allow for two levels of nesting
63 pattern: /\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}/,
64 inside: Prism.languages.xquery,
65 alias: 'language-xquery'
66 };
67
68 // The following will handle plain text inside tags
69 var stringifyToken = function (token) {
70 if (typeof token === 'string') {
71 return token;
72 }
73 if (typeof token.content === 'string') {
74 return token.content;
75 }
76 return token.content.map(stringifyToken).join('');
77 };
78
79 var walkTokens = function (tokens) {
80 var openedTags = [];
81 for (var i = 0; i < tokens.length; i++) {
82 var token = tokens[i];
83 var notTagNorBrace = false;
84
85 if (typeof token !== 'string') {
86 if (token.type === 'tag' && token.content[0] && token.content[0].type === 'tag') {
87 // We found a tag, now find its kind
88
89 if (token.content[0].content[0].content === '</') {
90 // Closing tag
91 if (openedTags.length > 0 && openedTags[openedTags.length - 1].tagName === stringifyToken(token.content[0].content[1])) {
92 // Pop matching opening tag
93 openedTags.pop();
94 }
95 } else {
96 if (token.content[token.content.length - 1].content === '/>') {
97 // Autoclosed tag, ignore
98 } else {
99 // Opening tag
100 openedTags.push({
101 tagName: stringifyToken(token.content[0].content[1]),
102 openedBraces: 0
103 });
104 }
105 }
106 } else if (
107 openedTags.length > 0 && token.type === 'punctuation' && token.content === '{' &&
108 // Ignore `{{`
109 (!tokens[i + 1] || tokens[i + 1].type !== 'punctuation' || tokens[i + 1].content !== '{') &&
110 (!tokens[i - 1] || tokens[i - 1].type !== 'plain-text' || tokens[i - 1].content !== '{')
111 ) {
112 // Here we might have entered an XQuery expression inside a tag
113 openedTags[openedTags.length - 1].openedBraces++;
114
115 } else if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces > 0 && token.type === 'punctuation' && token.content === '}') {
116
117 // Here we might have left an XQuery expression inside a tag
118 openedTags[openedTags.length - 1].openedBraces--;
119
120 } else if (token.type !== 'comment') {
121 notTagNorBrace = true;
122 }
123 }
124 if (notTagNorBrace || typeof token === 'string') {
125 if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces === 0) {
126 // Here we are inside a tag, and not inside an XQuery expression.
127 // That's plain text: drop any tokens matched.
128 var plainText = stringifyToken(token);
129
130 // And merge text with adjacent text
131 if (i < tokens.length - 1 && (typeof tokens[i + 1] === 'string' || tokens[i + 1].type === 'plain-text')) {
132 plainText += stringifyToken(tokens[i + 1]);
133 tokens.splice(i + 1, 1);
134 }
135 if (i > 0 && (typeof tokens[i - 1] === 'string' || tokens[i - 1].type === 'plain-text')) {
136 plainText = stringifyToken(tokens[i - 1]) + plainText;
137 tokens.splice(i - 1, 1);
138 i--;
139 }
140
141 if (/^\s+$/.test(plainText)) {
142 tokens[i] = plainText;
143 } else {
144 tokens[i] = new Prism.Token('plain-text', plainText, null, plainText);
145 }
146 }
147 }
148
149 if (token.content && typeof token.content !== 'string') {
150 walkTokens(token.content);
151 }
152 }
153 };
154
155 Prism.hooks.add('after-tokenize', function (env) {
156 if (env.language !== 'xquery') {
157 return;
158 }
159 walkTokens(env.tokens);
160 });
161
162}(Prism));