You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
6.5 KiB
199 lines
6.5 KiB
// Docs: |
|
// https://docs.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-5.0&tabs=visual-studio |
|
// https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-5.0 |
|
|
|
(function (Prism) { |
|
|
|
var commentLike = /\/(?![/*])|\/\/.*[\r\n]|\/\*[^*]*(?:\*(?!\/)[^*]*)*\*\//.source; |
|
var stringLike = |
|
/@(?!")|"(?:[^\r\n\\"]|\\.)*"|@"(?:[^\\"]|""|\\[\s\S])*"(?!")/.source + |
|
'|' + |
|
/'(?:(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'|(?=[^\\](?!')))/.source; |
|
|
|
/** |
|
* Creates a nested pattern where all occurrences of the string `<<self>>` are replaced with the pattern itself. |
|
* |
|
* @param {string} pattern |
|
* @param {number} depthLog2 |
|
* @returns {string} |
|
*/ |
|
function nested(pattern, depthLog2) { |
|
for (var i = 0; i < depthLog2; i++) { |
|
pattern = pattern.replace(/<self>/g, function () { return '(?:' + pattern + ')'; }); |
|
} |
|
return pattern |
|
.replace(/<self>/g, '[^\\s\\S]') |
|
.replace(/<str>/g, '(?:' + stringLike + ')') |
|
.replace(/<comment>/g, '(?:' + commentLike + ')'); |
|
} |
|
|
|
var round = nested(/\((?:[^()'"@/]|<str>|<comment>|<self>)*\)/.source, 2); |
|
var square = nested(/\[(?:[^\[\]'"@/]|<str>|<comment>|<self>)*\]/.source, 1); |
|
var curly = nested(/\{(?:[^{}'"@/]|<str>|<comment>|<self>)*\}/.source, 2); |
|
var angle = nested(/<(?:[^<>'"@/]|<comment>|<self>)*>/.source, 1); |
|
|
|
var inlineCs = /@/.source + |
|
/(?:await\b\s*)?/.source + |
|
'(?:' + /(?!await\b)\w+\b/.source + '|' + round + ')' + |
|
'(?:' + /[?!]?\.\w+\b/.source + '|' + '(?:' + angle + ')?' + round + '|' + square + ')*' + |
|
/(?![?!\.(\[]|<(?!\/))/.source; |
|
|
|
// Note about the above bracket patterns: |
|
// They all ignore HTML expressions that might be in the C# code. This is a problem because HTML (like strings and |
|
// comments) is parsed differently. This is a huge problem because HTML might contain brackets and quotes which |
|
// messes up the bracket and string counting implemented by the above patterns. |
|
// |
|
// This problem is not fixable because 1) HTML expression are highly context sensitive and very difficult to detect |
|
// and 2) they require one capturing group at every nested level. See the `tagRegion` pattern to admire the |
|
// complexity of an HTML expression. |
|
// |
|
// To somewhat alleviate the problem a bit, the patterns for characters (e.g. 'a') is very permissive, it also |
|
// allows invalid characters to support HTML expressions like this: <p>That's it!</p>. |
|
|
|
var tagAttrInlineCs = /@(?![\w()])/.source + '|' + inlineCs; |
|
var tagAttrValue = '(?:' + |
|
/"[^"@]*"|'[^'@]*'|[^\s'"@>=]+(?=[\s>])/.source + |
|
'|' + |
|
'["\'][^"\'@]*(?:(?:' + tagAttrInlineCs + ')[^"\'@]*)+["\']' + |
|
')'; |
|
|
|
var tagAttrs = /(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*<tagAttrValue>|(?=[\s/>])))+)?/.source.replace(/<tagAttrValue>/, tagAttrValue); |
|
var tagContent = /(?!\d)[^\s>\/=$<%]+/.source + tagAttrs + /\s*\/?>/.source; |
|
var tagRegion = |
|
/\B@?/.source + |
|
'(?:' + |
|
/<([a-zA-Z][\w:]*)/.source + tagAttrs + /\s*>/.source + |
|
'(?:' + |
|
( |
|
/[^<]/.source + |
|
'|' + |
|
// all tags that are not the start tag |
|
// eslint-disable-next-line regexp/strict |
|
/<\/?(?!\1\b)/.source + tagContent + |
|
'|' + |
|
// nested start tag |
|
nested( |
|
// eslint-disable-next-line regexp/strict |
|
/<\1/.source + tagAttrs + /\s*>/.source + |
|
'(?:' + |
|
( |
|
/[^<]/.source + |
|
'|' + |
|
// all tags that are not the start tag |
|
// eslint-disable-next-line regexp/strict |
|
/<\/?(?!\1\b)/.source + tagContent + |
|
'|' + |
|
'<self>' |
|
) + |
|
')*' + |
|
// eslint-disable-next-line regexp/strict |
|
/<\/\1\s*>/.source, |
|
2 |
|
) |
|
) + |
|
')*' + |
|
// eslint-disable-next-line regexp/strict |
|
/<\/\1\s*>/.source + |
|
'|' + |
|
/</.source + tagContent + |
|
')'; |
|
|
|
// Now for the actual language definition(s): |
|
// |
|
// Razor as a language has 2 parts: |
|
// 1) CSHTML: A markup-like language that has been extended with inline C# code expressions and blocks. |
|
// 2) C#+HTML: A variant of C# that can contain CSHTML tags as expressions. |
|
// |
|
// In the below code, both CSHTML and C#+HTML will be create as separate language definitions that reference each |
|
// other. However, only CSHTML will be exported via `Prism.languages`. |
|
|
|
Prism.languages.cshtml = Prism.languages.extend('markup', {}); |
|
|
|
var csharpWithHtml = Prism.languages.insertBefore('csharp', 'string', { |
|
'html': { |
|
pattern: RegExp(tagRegion), |
|
greedy: true, |
|
inside: Prism.languages.cshtml |
|
}, |
|
}, { csharp: Prism.languages.extend('csharp', {}) }); |
|
|
|
var cs = { |
|
pattern: /\S[\s\S]*/, |
|
alias: 'language-csharp', |
|
inside: csharpWithHtml |
|
}; |
|
|
|
var inlineValue = { |
|
pattern: RegExp(/(^|[^@])/.source + inlineCs), |
|
lookbehind: true, |
|
greedy: true, |
|
alias: 'variable', |
|
inside: { |
|
'keyword': /^@/, |
|
'csharp': cs |
|
} |
|
}; |
|
|
|
Prism.languages.cshtml.tag.pattern = RegExp(/<\/?/.source + tagContent); |
|
Prism.languages.cshtml.tag.inside['attr-value'].pattern = RegExp(/=\s*/.source + tagAttrValue); |
|
Prism.languages.insertBefore('inside', 'punctuation', { 'value': inlineValue }, Prism.languages.cshtml.tag.inside['attr-value']); |
|
|
|
Prism.languages.insertBefore('cshtml', 'prolog', { |
|
'razor-comment': { |
|
pattern: /@\*[\s\S]*?\*@/, |
|
greedy: true, |
|
alias: 'comment' |
|
}, |
|
|
|
'block': { |
|
pattern: RegExp( |
|
/(^|[^@])@/.source + |
|
'(?:' + |
|
[ |
|
// @{ ... } |
|
curly, |
|
// @code{ ... } |
|
/(?:code|functions)\s*/.source + curly, |
|
// @for (...) { ... } |
|
/(?:for|foreach|lock|switch|using|while)\s*/.source + round + /\s*/.source + curly, |
|
// @do { ... } while (...); |
|
/do\s*/.source + curly + /\s*while\s*/.source + round + /(?:\s*;)?/.source, |
|
// @try { ... } catch (...) { ... } finally { ... } |
|
/try\s*/.source + curly + /\s*catch\s*/.source + round + /\s*/.source + curly + /\s*finally\s*/.source + curly, |
|
// @if (...) {...} else if (...) {...} else {...} |
|
/if\s*/.source + round + /\s*/.source + curly + '(?:' + /\s*else/.source + '(?:' + /\s+if\s*/.source + round + ')?' + /\s*/.source + curly + ')*', |
|
// @helper Ident(params) { ... } |
|
/helper\s+\w+\s*/.source + round + /\s*/.source + curly, |
|
].join('|') + |
|
')' |
|
), |
|
lookbehind: true, |
|
greedy: true, |
|
inside: { |
|
'keyword': /^@\w*/, |
|
'csharp': cs |
|
} |
|
}, |
|
|
|
'directive': { |
|
pattern: /^([ \t]*)@(?:addTagHelper|attribute|implements|inherits|inject|layout|model|namespace|page|preservewhitespace|removeTagHelper|section|tagHelperPrefix|using)(?=\s).*/m, |
|
lookbehind: true, |
|
greedy: true, |
|
inside: { |
|
'keyword': /^@\w+/, |
|
'csharp': cs |
|
} |
|
}, |
|
|
|
'value': inlineValue, |
|
|
|
'delegate-operator': { |
|
pattern: /(^|[^@])@(?=<)/, |
|
lookbehind: true, |
|
alias: 'operator' |
|
} |
|
}); |
|
|
|
Prism.languages.razor = Prism.languages.cshtml; |
|
|
|
}(Prism));
|
|
|