aboutsummaryrefslogtreecommitdiffstats
path: root/public/prism/prism-cshtml.js
blob: df73bacc8bcdbd389ee81dc0b9ef6ae3c7824668 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color
// 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, 2);
  var curly = nested(/\{(?:[^{}'"@/]|<str>|<comment>|<self>)*\}/.source, 2);
  var angle = nested(/<(?:[^<>'"@/]|<str>|<comment>|<self>)*>/.source, 2);

  // 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 tagAttrs =
    /(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?/
      .source;
  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,
  };

  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 +
              ')*',
          ].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: {
      pattern: RegExp(
        /(^|[^@])@/.source +
          /(?:await\b\s*)?/.source +
          '(?:' +
          /\w+\b/.source +
          '|' +
          round +
          ')' +
          '(?:' +
          /[?!]?\.\w+\b/.source +
          '|' +
          round +
          '|' +
          square +
          '|' +
          angle +
          round +
          ')*'
      ),
      lookbehind: true,
      greedy: true,
      alias: 'variable',
      inside: {
        keyword: /^@/,
        csharp: cs,
      },
    },

    'delegate-operator': {
      pattern: /(^|[^@])@(?=<)/,
      lookbehind: true,
      alias: 'operator',
    },
  });

  Prism.languages.razor = Prism.languages.cshtml;
})(Prism);