| 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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
 | // https://unicode-org.github.io/icu/userguide/format_parse/messages/
// https://unicode-org.github.io/icu-docs/apidoc/released/icu4j/com/ibm/icu/text/MessageFormat.html
(function (Prism) {
  /**
   * @param {string} source
   * @param {number} level
   * @returns {string}
   */
  function nested(source, level) {
    if (level <= 0) {
      return /[]/.source;
    } else {
      return source.replace(/<SELF>/g, function () {
        return nested(source, level - 1);
      });
    }
  }
  var stringPattern = /'[{}:=,](?:[^']|'')*'(?!')/;
  var escape = {
    pattern: /''/,
    greedy: true,
    alias: 'operator',
  };
  var string = {
    pattern: stringPattern,
    greedy: true,
    inside: {
      escape: escape,
    },
  };
  var argumentSource = nested(
    /\{(?:[^{}']|'(?![{},'])|''|<STR>|<SELF>)*\}/.source.replace(
      /<STR>/g,
      function () {
        return stringPattern.source;
      }
    ),
    8
  );
  var nestedMessage = {
    pattern: RegExp(argumentSource),
    inside: {
      message: {
        pattern: /^(\{)[\s\S]+(?=\}$)/,
        lookbehind: true,
        inside: null, // see below
      },
      'message-delimiter': {
        pattern: /./,
        alias: 'punctuation',
      },
    },
  };
  Prism.languages['icu-message-format'] = {
    argument: {
      pattern: RegExp(argumentSource),
      greedy: true,
      inside: {
        content: {
          pattern: /^(\{)[\s\S]+(?=\}$)/,
          lookbehind: true,
          inside: {
            'argument-name': {
              pattern: /^(\s*)[^{}:=,\s]+/,
              lookbehind: true,
            },
            'choice-style': {
              // https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1ChoiceFormat.html#details
              pattern: /^(\s*,\s*choice\s*,\s*)\S(?:[\s\S]*\S)?/,
              lookbehind: true,
              inside: {
                punctuation: /\|/,
                range: {
                  pattern: /^(\s*)[+-]?(?:\d+(?:\.\d*)?|\u221e)\s*[<#\u2264]/,
                  lookbehind: true,
                  inside: {
                    operator: /[<#\u2264]/,
                    number: /\S+/,
                  },
                },
                rest: null, // see below
              },
            },
            'plural-style': {
              // https://unicode-org.github.io/icu-docs/apidoc/released/icu4j/com/ibm/icu/text/PluralFormat.html#:~:text=Patterns%20and%20Their%20Interpretation
              pattern:
                /^(\s*,\s*(?:plural|selectordinal)\s*,\s*)\S(?:[\s\S]*\S)?/,
              lookbehind: true,
              inside: {
                offset: /^offset:\s*\d+/,
                'nested-message': nestedMessage,
                selector: {
                  pattern: /=\d+|[^{}:=,\s]+/,
                  inside: {
                    keyword: /^(?:few|many|one|other|two|zero)$/,
                  },
                },
              },
            },
            'select-style': {
              // https://unicode-org.github.io/icu-docs/apidoc/released/icu4j/com/ibm/icu/text/SelectFormat.html#:~:text=Patterns%20and%20Their%20Interpretation
              pattern: /^(\s*,\s*select\s*,\s*)\S(?:[\s\S]*\S)?/,
              lookbehind: true,
              inside: {
                'nested-message': nestedMessage,
                selector: {
                  pattern: /[^{}:=,\s]+/,
                  inside: {
                    keyword: /^other$/,
                  },
                },
              },
            },
            keyword: /\b(?:choice|plural|select|selectordinal)\b/,
            'arg-type': {
              pattern: /\b(?:date|duration|number|ordinal|spellout|time)\b/,
              alias: 'keyword',
            },
            'arg-skeleton': {
              pattern: /(,\s*)::[^{}:=,\s]+/,
              lookbehind: true,
            },
            'arg-style': {
              pattern:
                /(,\s*)(?:currency|full|integer|long|medium|percent|short)(?=\s*$)/,
              lookbehind: true,
            },
            'arg-style-text': {
              pattern: RegExp(
                /(^\s*,\s*(?=\S))/.source +
                  nested(/(?:[^{}']|'[^']*'|\{(?:<SELF>)?\})+/.source, 8) +
                  '$'
              ),
              lookbehind: true,
              alias: 'string',
            },
            punctuation: /,/,
          },
        },
        'argument-delimiter': {
          pattern: /./,
          alias: 'operator',
        },
      },
    },
    escape: escape,
    string: string,
  };
  nestedMessage.inside.message.inside = Prism.languages['icu-message-format'];
  Prism.languages['icu-message-format'].argument.inside.content.inside[
    'choice-style'
  ].inside.rest = Prism.languages['icu-message-format'];
})(Prism);
 |