UNPKG

5.92 kBJavaScriptView Raw
1// Docs:
2// https://docs.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-5.0&tabs=visual-studio
3// https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-5.0
4
5(function (Prism) {
6
7 var commentLike = /\/(?![/*])|\/\/.*[\r\n]|\/\*[^*]*(?:\*(?!\/)[^*]*)*\*\//.source;
8 var stringLike =
9 /@(?!")|"(?:[^\r\n\\"]|\\.)*"|@"(?:[^\\"]|""|\\[\s\S])*"(?!")/.source +
10 '|' +
11 /'(?:(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'|(?=[^\\](?!')))/.source;
12
13 /**
14 * Creates a nested pattern where all occurrences of the string `<<self>>` are replaced with the pattern itself.
15 *
16 * @param {string} pattern
17 * @param {number} depthLog2
18 * @returns {string}
19 */
20 function nested(pattern, depthLog2) {
21 for (var i = 0; i < depthLog2; i++) {
22 pattern = pattern.replace(/<self>/g, function () { return '(?:' + pattern + ')'; });
23 }
24 return pattern
25 .replace(/<self>/g, '[^\\s\\S]')
26 .replace(/<str>/g, '(?:' + stringLike + ')')
27 .replace(/<comment>/g, '(?:' + commentLike + ')');
28 }
29
30 var round = nested(/\((?:[^()'"@/]|<str>|<comment>|<self>)*\)/.source, 2);
31 var square = nested(/\[(?:[^\[\]'"@/]|<str>|<comment>|<self>)*\]/.source, 2);
32 var curly = nested(/\{(?:[^{}'"@/]|<str>|<comment>|<self>)*\}/.source, 2);
33 var angle = nested(/<(?:[^<>'"@/]|<str>|<comment>|<self>)*>/.source, 2);
34
35 // Note about the above bracket patterns:
36 // They all ignore HTML expressions that might be in the C# code. This is a problem because HTML (like strings and
37 // comments) is parsed differently. This is a huge problem because HTML might contain brackets and quotes which
38 // messes up the bracket and string counting implemented by the above patterns.
39 //
40 // This problem is not fixable because 1) HTML expression are highly context sensitive and very difficult to detect
41 // and 2) they require one capturing group at every nested level. See the `tagRegion` pattern to admire the
42 // complexity of an HTML expression.
43 //
44 // To somewhat alleviate the problem a bit, the patterns for characters (e.g. 'a') is very permissive, it also
45 // allows invalid characters to support HTML expressions like this: <p>That's it!</p>.
46
47 var tagAttrs = /(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?/.source;
48 var tagContent = /(?!\d)[^\s>\/=$<%]+/.source + tagAttrs + /\s*\/?>/.source;
49 var tagRegion =
50 /\B@?/.source +
51 '(?:' +
52 /<([a-zA-Z][\w:]*)/.source + tagAttrs + /\s*>/.source +
53 '(?:' +
54 (
55 /[^<]/.source +
56 '|' +
57 // all tags that are not the start tag
58 // eslint-disable-next-line regexp/strict
59 /<\/?(?!\1\b)/.source + tagContent +
60 '|' +
61 // nested start tag
62 nested(
63 // eslint-disable-next-line regexp/strict
64 /<\1/.source + tagAttrs + /\s*>/.source +
65 '(?:' +
66 (
67 /[^<]/.source +
68 '|' +
69 // all tags that are not the start tag
70 // eslint-disable-next-line regexp/strict
71 /<\/?(?!\1\b)/.source + tagContent +
72 '|' +
73 '<self>'
74 ) +
75 ')*' +
76 // eslint-disable-next-line regexp/strict
77 /<\/\1\s*>/.source,
78 2
79 )
80 ) +
81 ')*' +
82 // eslint-disable-next-line regexp/strict
83 /<\/\1\s*>/.source +
84 '|' +
85 /</.source + tagContent +
86 ')';
87
88 // Now for the actual language definition(s):
89 //
90 // Razor as a language has 2 parts:
91 // 1) CSHTML: A markup-like language that has been extended with inline C# code expressions and blocks.
92 // 2) C#+HTML: A variant of C# that can contain CSHTML tags as expressions.
93 //
94 // In the below code, both CSHTML and C#+HTML will be create as separate language definitions that reference each
95 // other. However, only CSHTML will be exported via `Prism.languages`.
96
97 Prism.languages.cshtml = Prism.languages.extend('markup', {});
98
99 var csharpWithHtml = Prism.languages.insertBefore('csharp', 'string', {
100 'html': {
101 pattern: RegExp(tagRegion),
102 greedy: true,
103 inside: Prism.languages.cshtml
104 },
105 }, { csharp: Prism.languages.extend('csharp', {}) });
106
107 var cs = {
108 pattern: /\S[\s\S]*/,
109 alias: 'language-csharp',
110 inside: csharpWithHtml
111 };
112
113 Prism.languages.insertBefore('cshtml', 'prolog', {
114 'razor-comment': {
115 pattern: /@\*[\s\S]*?\*@/,
116 greedy: true,
117 alias: 'comment'
118 },
119
120 'block': {
121 pattern: RegExp(
122 /(^|[^@])@/.source +
123 '(?:' +
124 [
125 // @{ ... }
126 curly,
127 // @code{ ... }
128 /(?:code|functions)\s*/.source + curly,
129 // @for (...) { ... }
130 /(?:for|foreach|lock|switch|using|while)\s*/.source + round + /\s*/.source + curly,
131 // @do { ... } while (...);
132 /do\s*/.source + curly + /\s*while\s*/.source + round + /(?:\s*;)?/.source,
133 // @try { ... } catch (...) { ... } finally { ... }
134 /try\s*/.source + curly + /\s*catch\s*/.source + round + /\s*/.source + curly + /\s*finally\s*/.source + curly,
135 // @if (...) {...} else if (...) {...} else {...}
136 /if\s*/.source + round + /\s*/.source + curly + '(?:' + /\s*else/.source + '(?:' + /\s+if\s*/.source + round + ')?' + /\s*/.source + curly + ')*',
137 ].join('|') +
138 ')'
139 ),
140 lookbehind: true,
141 greedy: true,
142 inside: {
143 'keyword': /^@\w*/,
144 'csharp': cs
145 }
146 },
147
148 'directive': {
149 pattern: /^([ \t]*)@(?:addTagHelper|attribute|implements|inherits|inject|layout|model|namespace|page|preservewhitespace|removeTagHelper|section|tagHelperPrefix|using)(?=\s).*/m,
150 lookbehind: true,
151 greedy: true,
152 inside: {
153 'keyword': /^@\w+/,
154 'csharp': cs
155 }
156 },
157
158 'value': {
159 pattern: RegExp(
160 /(^|[^@])@/.source +
161 /(?:await\b\s*)?/.source +
162 '(?:' + /\w+\b/.source + '|' + round + ')' +
163 '(?:' + /[?!]?\.\w+\b/.source + '|' + round + '|' + square + '|' + angle + round + ')*'
164 ),
165 lookbehind: true,
166 greedy: true,
167 alias: 'variable',
168 inside: {
169 'keyword': /^@/,
170 'csharp': cs
171 }
172 },
173
174 'delegate-operator': {
175 pattern: /(^|[^@])@(?=<)/,
176 lookbehind: true,
177 alias: 'operator'
178 }
179 });
180
181 Prism.languages.razor = Prism.languages.cshtml;
182
183}(Prism));