'use strict' module.exports = icuMessageFormat icuMessageFormat.displayName = 'icuMessageFormat' icuMessageFormat.aliases = [] function icuMessageFormat(Prism) { // 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(//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( /\{(?:[^{}']|'(?![{},'])|''||)*\}/.source.replace( //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(/(?:[^{}']|'[^']*'|\{(?:)?\})+/.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) }