From a2423c12241b4226902560a213b694f79b270163 Mon Sep 17 00:00:00 2001 From: Jonathan Gillespie Date: Mon, 11 May 2026 23:39:22 -0400 Subject: [PATCH 1/9] Created a new node script to auto-retrieve & auto-minify PrismJS files (including plugins & languages) to streamline the update process & to switch to minified versions --- .forceignore | 7 + .gitignore | 1 + .prettierignore | 11 +- .../staticresources/LoggerResources/README.md | 38 + .../staticresources/LoggerResources/prism.css | 324 +- .../staticresources/LoggerResources/prism.js | 1312 +- .../LoggerResources/prism.min.css | 1 + .../LoggerResources/prism.min.js | 3 + .../LoggerResources/prism.nebula-logger.css | 4 + package-lock.json | 32715 ++++++++++++---- package.json | 8 +- scripts/build/build-prism-static-resources.js | 85 + 12 files changed, 26316 insertions(+), 8193 deletions(-) create mode 100644 nebula-logger/core/main/log-management/staticresources/LoggerResources/README.md create mode 100644 nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.min.css create mode 100644 nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.min.js create mode 100644 nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.nebula-logger.css create mode 100644 scripts/build/build-prism-static-resources.js diff --git a/.forceignore b/.forceignore index 67d92b535..3424dc4ae 100644 --- a/.forceignore +++ b/.forceignore @@ -21,3 +21,10 @@ nebula-logger/managed-package/**/*.testSuite-meta.xml **/tsconfig.json **/*.ts + + +# PrismJS - only the minified files are deployed, the unminified versions are +# only kept in source control to make it easier to see what's changed when upgrading PrismJS. +nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.css +nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.js +nebula-logger/core/main/log-management/staticresources/LoggerResources/README.md diff --git a/.gitignore b/.gitignore index 26efa8d77..1119bd874 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .sf/ .sfdx/ .vscode/ +.claude/ docs/apex/Miscellaneous/ temp/ test-coverage/ diff --git a/.prettierignore b/.prettierignore index 6fb5cca87..cf858583b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -20,8 +20,9 @@ yarn.lock *.log *.xml -# Prism JS -# The CSS for Prism has specifically been modified for Nebula Logger (a bit), so it's NOT ignored. -# nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.css -# The minified JS is taken as-is, so no need for prettier to format it. -nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.js \ No newline at end of file +# PrismJS - these files are automatically updated & minified, +# so no need for prettier to format them. +nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.css +nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.min.css +nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.js +nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.min.js \ No newline at end of file diff --git a/nebula-logger/core/main/log-management/staticresources/LoggerResources/README.md b/nebula-logger/core/main/log-management/staticresources/LoggerResources/README.md new file mode 100644 index 000000000..45f8bd6f2 --- /dev/null +++ b/nebula-logger/core/main/log-management/staticresources/LoggerResources/README.md @@ -0,0 +1,38 @@ +# Prism Static Resource Files + +This directory contains four files for the [Prism.js](https://prismjs.com/) syntax highlighting library: + +| File | Purpose | +| ------------------------- | --------------------------------------------------------- | +| `prism.js` | Unminified source - readable, used for debugging | +| `prism.css` | Unminified source - readable, used for debugging | +| `prism.min.js` | Minified - this is what Salesforce deploys | +| `prism.min.css` | Minified - this is what Salesforce deploys | +| `prism.nebula-logger.css` | Unminified - project-specific overrides for Nebula Logger | + +The unminified files are the source of truth. The `.min` files are generated automatically and should never be edited by hand. Previously, these files were manually downloaded from https://prismjs.com/download#themes=prism-tomorrow&languages=markup+css+clike+javascript+apex+http+javadoclike+json+json5+jsonp+jsstacktrace+sql+typescript&plugins=line-highlight+line-numbers+show-language+toolbar+copy-to-clipboard+download-button. + +The file `prism.nebula-logger.css` contains project-specific overrides and is maintained separately from the Prism project files. It is always deployed to Salesforce and should be edited directly - it is not generated by any script, and there's currently not a minified version (since the file is already so small). + +## Why both versions? + +The unminified files are kept in the repo so that the bundle is readable and diffable in pull requests - useful when upgrading Prism to see exactly what changed. The minified versions are what actually gets deployed to Salesforce to keep the static resource size down. + +The unminified files are excluded from Salesforce deployments via `.forceignore`. + +## Upgrading Prism or changing the build config + +There are 2 files within this repo that control upgrading Prism + +- The version of Prism used is specified in `dependencies` within `package.json`. +- Languages, plugins, and the theme are configured at the top of `scripts/build/build-prism-static-resources.js` in this repo. + +To upgrade Prism or rebuild the files after changing the config, run: + +```bash +npm run prism:build +``` + +This updates the `prismjs` npm package to its latest version and regenerates all four files. Commit all four files after running it. + +The build script also runs automatically via `postinstall`, so the files will be regenerated whenever anyone runs `npm install` (such as when setting up the project for the first time after cloning the repo). diff --git a/nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.css b/nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.css index 33b91b6f8..19d9f9743 100644 --- a/nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.css +++ b/nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.css @@ -1,55 +1,50 @@ -/* -This file is originally from prismjs.com - all credits to that project for Prism. Some customizations have been made below specifically for Nebula Logger - search for 'Nebula Logger' to find them 😉 -*/ - -/* PrismJS 1.30.0 -https://prismjs.com/download#themes=prism-tomorrow&languages=markup+css+clike+javascript+apex+http+javadoclike+json+json5+jsonp+jsstacktrace+sql+typescript&plugins=line-highlight+line-numbers+show-language+toolbar+copy-to-clipboard+download-button */ /** * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML * Based on https://github.com/chriskempson/tomorrow-theme * @author Rose Pritchard */ -code[class*='language-'], -pre[class*='language-'] { - color: #ccc; - background: none; - font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; - font-size: 1em; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - word-wrap: normal; - line-height: 1.5; - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; +code[class*="language-"], +pre[class*="language-"] { + color: #ccc; + background: none; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1em; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; + } /* Code blocks */ -pre[class*='language-'] { - padding: 1em; - margin: 0.5em 0; - overflow: auto; +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; } -:not(pre) > code[class*='language-'], -pre[class*='language-'] { - background: #2d2d2d; +:not(pre) > code[class*="language-"], +pre[class*="language-"] { + background: #2d2d2d; } /* Inline code */ -:not(pre) > code[class*='language-'] { - padding: 0.1em; - border-radius: 0.3em; - white-space: normal; +:not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; + white-space: normal; } .token.comment, @@ -57,35 +52,35 @@ pre[class*='language-'] { .token.prolog, .token.doctype, .token.cdata { - color: #999; + color: #999; } .token.punctuation { - color: #ccc; + color: #ccc; } .token.tag, .token.attr-name, .token.namespace, .token.deleted { - color: #e2777a; + color: #e2777a; } .token.function-name { - color: #6196cc; + color: #6196cc; } .token.boolean, .token.number, .token.function { - color: #f08d49; + color: #f08d49; } .token.property, .token.class-name, .token.constant, .token.symbol { - color: #f8c555; + color: #f8c555; } .token.selector, @@ -93,7 +88,7 @@ pre[class*='language-'] { .token.atrule, .token.keyword, .token.builtin { - color: #cc99cd; + color: #cc99cd; } .token.string, @@ -101,199 +96,197 @@ pre[class*='language-'] { .token.attr-value, .token.regex, .token.variable { - color: #7ec699; + color: #7ec699; } .token.operator, .token.entity, .token.url { - color: #67cdcc; + color: #67cdcc; } .token.important, .token.bold { - font-weight: bold; + font-weight: bold; } .token.italic { - font-style: italic; + font-style: italic; } .token.entity { - cursor: help; + cursor: help; } .token.inserted { - color: green; + color: green; } pre[data-line] { - position: relative; - padding: 1em 0 1em 3em; + position: relative; + padding: 1em 0 1em 3em; } .line-highlight { - position: absolute; - left: 0; - right: 0; - padding: inherit 0; - margin-top: 1em; /* Same as .prism’s padding-top */ + position: absolute; + left: 0; + right: 0; + padding: inherit 0; + margin-top: 1em; /* Same as .prism’s padding-top */ - /* Background color customized for Nebula Logger */ - background: hsla(24, 20%, 80%, 0.4); - /* Original background colors */ - /* background: hsla(24, 20%, 50%,.08); - background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); */ + background: hsla(24, 20%, 50%,.08); + background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); - pointer-events: none; + pointer-events: none; - line-height: inherit; - white-space: pre; + line-height: inherit; + white-space: pre; } @media print { - .line-highlight { - /* + .line-highlight { + /* * This will prevent browsers from replacing the background color with white. * It's necessary because the element is layered on top of the displayed code. */ - -webkit-print-color-adjust: exact; - color-adjust: exact; - } -} - -.line-highlight:before, -.line-highlight[data-end]:after { - content: attr(data-start); - position: absolute; - top: 0.4em; - left: 0.6em; - min-width: 1em; - padding: 0 0.5em; - background-color: hsla(24, 20%, 50%, 0.4); - color: hsl(24, 20%, 95%); - font: bold 65%/1.5 sans-serif; - text-align: center; - vertical-align: 0.3em; - border-radius: 999px; - text-shadow: none; - box-shadow: 0 1px white; -} - -.line-highlight[data-end]:after { - content: attr(data-end); - top: auto; - bottom: 0.4em; -} + -webkit-print-color-adjust: exact; + color-adjust: exact; + } +} + + .line-highlight:before, + .line-highlight[data-end]:after { + content: attr(data-start); + position: absolute; + top: .4em; + left: .6em; + min-width: 1em; + padding: 0 .5em; + background-color: hsla(24, 20%, 50%,.4); + color: hsl(24, 20%, 95%); + font: bold 65%/1.5 sans-serif; + text-align: center; + vertical-align: .3em; + border-radius: 999px; + text-shadow: none; + box-shadow: 0 1px white; + } + + .line-highlight[data-end]:after { + content: attr(data-end); + top: auto; + bottom: .4em; + } .line-numbers .line-highlight:before, .line-numbers .line-highlight:after { - content: none; + content: none; } pre[id].linkable-line-numbers span.line-numbers-rows { - pointer-events: all; + pointer-events: all; } pre[id].linkable-line-numbers span.line-numbers-rows > span:before { - cursor: pointer; + cursor: pointer; } pre[id].linkable-line-numbers span.line-numbers-rows > span:hover:before { - background-color: rgba(128, 128, 128, 0.2); + background-color: rgba(128, 128, 128, .2); } -pre[class*='language-'].line-numbers { - position: relative; - padding-left: 3.8em; - counter-reset: linenumber; +pre[class*="language-"].line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; } -pre[class*='language-'].line-numbers > code { - position: relative; - white-space: inherit; +pre[class*="language-"].line-numbers > code { + position: relative; + white-space: inherit; } .line-numbers .line-numbers-rows { - position: absolute; - pointer-events: none; - top: 0; - font-size: 100%; - left: -3.8em; - width: 3em; /* works for line-numbers below 1000 lines */ - letter-spacing: -1px; - border-right: 1px solid #999; - - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.line-numbers-rows > span { - display: block; - counter-increment: linenumber; -} - -.line-numbers-rows > span:before { - content: counter(linenumber); - color: #999; - display: block; - padding-right: 0.8em; - text-align: right; -} + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid #999; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + +} + + .line-numbers-rows > span { + display: block; + counter-increment: linenumber; + } + + .line-numbers-rows > span:before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: 0.8em; + text-align: right; + } div.code-toolbar { - position: relative; + position: relative; } div.code-toolbar > .toolbar { - position: absolute; - z-index: 10; - top: 0.3em; - right: 0.2em; - transition: opacity 0.3s ease-in-out; - opacity: 0; + position: absolute; + z-index: 10; + top: .3em; + right: .2em; + transition: opacity 0.3s ease-in-out; + opacity: 0; } div.code-toolbar:hover > .toolbar { - opacity: 1; + opacity: 1; } /* Separate line b/c rules are thrown out if selector is invalid. IE11 and old Edge versions don't support :focus-within. */ div.code-toolbar:focus-within > .toolbar { - opacity: 1; + opacity: 1; } div.code-toolbar > .toolbar > .toolbar-item { - display: inline-block; + display: inline-block; } div.code-toolbar > .toolbar > .toolbar-item > a { - cursor: pointer; + cursor: pointer; } div.code-toolbar > .toolbar > .toolbar-item > button { - background: none; - border: 0; - color: inherit; - font: inherit; - line-height: normal; - overflow: visible; - padding: 0; - -webkit-user-select: none; /* for button */ - -moz-user-select: none; - -ms-user-select: none; + background: none; + border: 0; + color: inherit; + font: inherit; + line-height: normal; + overflow: visible; + padding: 0; + -webkit-user-select: none; /* for button */ + -moz-user-select: none; + -ms-user-select: none; } div.code-toolbar > .toolbar > .toolbar-item > a, div.code-toolbar > .toolbar > .toolbar-item > button, div.code-toolbar > .toolbar > .toolbar-item > span { - color: #bbb; - font-size: 0.8em; - padding: 0 0.5em; - background: #f5f2f0; - background: rgba(224, 224, 224, 0.2); - box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2); - border-radius: 0.5em; + color: #bbb; + font-size: .8em; + padding: 0 .5em; + background: #f5f2f0; + background: rgba(224, 224, 224, 0.2); + box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); + border-radius: .5em; } div.code-toolbar > .toolbar > .toolbar-item > a:hover, @@ -302,6 +295,9 @@ div.code-toolbar > .toolbar > .toolbar-item > button:hover, div.code-toolbar > .toolbar > .toolbar-item > button:focus, div.code-toolbar > .toolbar > .toolbar-item > span:hover, div.code-toolbar > .toolbar > .toolbar-item > span:focus { - color: inherit; - text-decoration: none; + color: inherit; + text-decoration: none; } + + + diff --git a/nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.js b/nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.js index b285678e9..b66fa57aa 100644 --- a/nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.js +++ b/nebula-logger/core/main/log-management/staticresources/LoggerResources/prism.js @@ -1,5 +1,8 @@ -/* PrismJS 1.30.0 -https://prismjs.com/download#themes=prism-tomorrow&languages=markup+css+clike+javascript+apex+http+javadoclike+json+json5+jsonp+jsstacktrace+sql+typescript&plugins=line-highlight+line-numbers+show-language+toolbar+copy-to-clipboard+download-button */ + +/* ********************************************** + Begin prism-core.js +********************************************** */ + /// var _self = (typeof window !== 'undefined') @@ -1263,7 +1266,12 @@ if (typeof global !== 'undefined') { * @global * @public */ -; + + +/* ********************************************** + Begin prism-markup.js +********************************************** */ + Prism.languages.markup = { 'comment': { pattern: //, @@ -1451,6 +1459,11 @@ Prism.languages.ssml = Prism.languages.xml; Prism.languages.atom = Prism.languages.xml; Prism.languages.rss = Prism.languages.xml; + +/* ********************************************** + Begin prism-css.js +********************************************** */ + (function (Prism) { var string = /(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/; @@ -1516,6 +1529,11 @@ Prism.languages.rss = Prism.languages.xml; }(Prism)); + +/* ********************************************** + Begin prism-clike.js +********************************************** */ + Prism.languages.clike = { 'comment': [ { @@ -1548,6 +1566,11 @@ Prism.languages.clike = { 'punctuation': /[{}[\];(),.:]/ }; + +/* ********************************************** + Begin prism-javascript.js +********************************************** */ + Prism.languages.javascript = Prism.languages.extend('clike', { 'class-name': [ Prism.languages.clike['class-name'], @@ -1721,38 +1744,206 @@ if (Prism.languages.markup) { Prism.languages.js = Prism.languages.javascript; -Prism.languages.sql = { - 'comment': { - pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/, - lookbehind: true - }, - 'variable': [ - { - pattern: /@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/, - greedy: true - }, - /@[\w.$]+/ - ], - 'string': { - pattern: /(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/, - greedy: true, - lookbehind: true - }, - 'identifier': { - pattern: /(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/, - greedy: true, - lookbehind: true, - inside: { - 'punctuation': /^`|`$/ + +/* ********************************************** + Begin prism-file-highlight.js +********************************************** */ + +(function () { + + if (typeof Prism === 'undefined' || typeof document === 'undefined') { + return; + } + + // https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill + if (!Element.prototype.matches) { + Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; + } + + var LOADING_MESSAGE = 'Loading…'; + var FAILURE_MESSAGE = function (status, message) { + return '✖ Error ' + status + ' while fetching file: ' + message; + }; + var FAILURE_EMPTY_MESSAGE = '✖ Error: File does not exist or is empty'; + + var EXTENSIONS = { + 'js': 'javascript', + 'py': 'python', + 'rb': 'ruby', + 'ps1': 'powershell', + 'psm1': 'powershell', + 'sh': 'bash', + 'bat': 'batch', + 'h': 'c', + 'tex': 'latex' + }; + + var STATUS_ATTR = 'data-src-status'; + var STATUS_LOADING = 'loading'; + var STATUS_LOADED = 'loaded'; + var STATUS_FAILED = 'failed'; + + var SELECTOR = 'pre[data-src]:not([' + STATUS_ATTR + '="' + STATUS_LOADED + '"])' + + ':not([' + STATUS_ATTR + '="' + STATUS_LOADING + '"])'; + + /** + * Loads the given file. + * + * @param {string} src The URL or path of the source file to load. + * @param {(result: string) => void} success + * @param {(reason: string) => void} error + */ + function loadFile(src, success, error) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', src, true); + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + if (xhr.status < 400 && xhr.responseText) { + success(xhr.responseText); + } else { + if (xhr.status >= 400) { + error(FAILURE_MESSAGE(xhr.status, xhr.statusText)); + } else { + error(FAILURE_EMPTY_MESSAGE); + } + } + } + }; + xhr.send(null); + } + + /** + * Parses the given range. + * + * This returns a range with inclusive ends. + * + * @param {string | null | undefined} range + * @returns {[number, number | undefined] | undefined} + */ + function parseRange(range) { + var m = /^\s*(\d+)\s*(?:(,)\s*(?:(\d+)\s*)?)?$/.exec(range || ''); + if (m) { + var start = Number(m[1]); + var comma = m[2]; + var end = m[3]; + + if (!comma) { + return [start, start]; + } + if (!end) { + return [start, undefined]; + } + return [start, Number(end)]; } - }, - 'function': /\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i, // Should we highlight user defined functions too? - 'keyword': /\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i, - 'boolean': /\b(?:FALSE|NULL|TRUE)\b/i, - 'number': /\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i, - 'operator': /[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i, - 'punctuation': /[;[\]()`,.]/ -}; + return undefined; + } + + Prism.hooks.add('before-highlightall', function (env) { + env.selector += ', ' + SELECTOR; + }); + + Prism.hooks.add('before-sanity-check', function (env) { + var pre = /** @type {HTMLPreElement} */ (env.element); + if (pre.matches(SELECTOR)) { + env.code = ''; // fast-path the whole thing and go to complete + + pre.setAttribute(STATUS_ATTR, STATUS_LOADING); // mark as loading + + // add code element with loading message + var code = pre.appendChild(document.createElement('CODE')); + code.textContent = LOADING_MESSAGE; + + var src = pre.getAttribute('data-src'); + + var language = env.language; + if (language === 'none') { + // the language might be 'none' because there is no language set; + // in this case, we want to use the extension as the language + var extension = (/\.(\w+)$/.exec(src) || [, 'none'])[1]; + language = EXTENSIONS[extension] || extension; + } + + // set language classes + Prism.util.setLanguage(code, language); + Prism.util.setLanguage(pre, language); + + // preload the language + var autoloader = Prism.plugins.autoloader; + if (autoloader) { + autoloader.loadLanguages(language); + } + + // load file + loadFile( + src, + function (text) { + // mark as loaded + pre.setAttribute(STATUS_ATTR, STATUS_LOADED); + + // handle data-range + var range = parseRange(pre.getAttribute('data-range')); + if (range) { + var lines = text.split(/\r\n?|\n/g); + + // the range is one-based and inclusive on both ends + var start = range[0]; + var end = range[1] == null ? lines.length : range[1]; + + if (start < 0) { start += lines.length; } + start = Math.max(0, Math.min(start - 1, lines.length)); + if (end < 0) { end += lines.length; } + end = Math.max(0, Math.min(end, lines.length)); + + text = lines.slice(start, end).join('\n'); + + // add data-start for line numbers + if (!pre.hasAttribute('data-start')) { + pre.setAttribute('data-start', String(start + 1)); + } + } + + // highlight code + code.textContent = text; + Prism.highlightElement(code); + }, + function (error) { + // mark as failed + pre.setAttribute(STATUS_ATTR, STATUS_FAILED); + + code.textContent = error; + } + ); + } + }); + + Prism.plugins.fileHighlight = { + /** + * Executes the File Highlight plugin for all matching `pre` elements under the given container. + * + * Note: Elements which are already loaded or currently loading will not be touched by this method. + * + * @param {ParentNode} [container=document] + */ + highlight: function highlight(container) { + var elements = (container || document).querySelectorAll(SELECTOR); + + for (var i = 0, element; (element = elements[i++]);) { + Prism.highlightElement(element); + } + } + }; + + var logged = false; + /** @deprecated Use `Prism.plugins.fileHighlight.highlight` instead. */ + Prism.fileHighlight = function () { + if (!logged) { + console.warn('Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead.'); + logged = true; + } + Prism.plugins.fileHighlight.highlight.apply(this, arguments); + }; + +}()); (function (Prism) { @@ -1820,6 +2011,103 @@ Prism.languages.sql = { }(Prism)); +Prism.languages.clike = { + 'comment': [ + { + pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/, + lookbehind: true, + greedy: true + }, + { + pattern: /(^|[^\\:])\/\/.*/, + lookbehind: true, + greedy: true + } + ], + 'string': { + pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, + greedy: true + }, + 'class-name': { + pattern: /(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i, + lookbehind: true, + inside: { + 'punctuation': /[.\\]/ + } + }, + 'keyword': /\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/, + 'boolean': /\b(?:false|true)\b/, + 'function': /\b\w+(?=\()/, + 'number': /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i, + 'operator': /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/, + 'punctuation': /[{}[\];(),.:]/ +}; + +(function (Prism) { + + var string = /(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/; + + Prism.languages.css = { + 'comment': /\/\*[\s\S]*?\*\//, + 'atrule': { + pattern: RegExp('@[\\w-](?:' + /[^;{\s"']|\s+(?!\s)/.source + '|' + string.source + ')*?' + /(?:;|(?=\s*\{))/.source), + inside: { + 'rule': /^@[\w-]+/, + 'selector-function-argument': { + pattern: /(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/, + lookbehind: true, + alias: 'selector' + }, + 'keyword': { + pattern: /(^|[^\w-])(?:and|not|only|or)(?![\w-])/, + lookbehind: true + } + // See rest below + } + }, + 'url': { + // https://drafts.csswg.org/css-values-3/#urls + pattern: RegExp('\\burl\\((?:' + string.source + '|' + /(?:[^\\\r\n()"']|\\[\s\S])*/.source + ')\\)', 'i'), + greedy: true, + inside: { + 'function': /^url/i, + 'punctuation': /^\(|\)$/, + 'string': { + pattern: RegExp('^' + string.source + '$'), + alias: 'url' + } + } + }, + 'selector': { + pattern: RegExp('(^|[{}\\s])[^{}\\s](?:[^{};"\'\\s]|\\s+(?![\\s{])|' + string.source + ')*(?=\\s*\\{)'), + lookbehind: true + }, + 'string': { + pattern: string, + greedy: true + }, + 'property': { + pattern: /(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i, + lookbehind: true + }, + 'important': /!important\b/i, + 'function': { + pattern: /(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i, + lookbehind: true + }, + 'punctuation': /[(){};:,]/ + }; + + Prism.languages.css['atrule'].inside.rest = Prism.languages.css; + + var markup = Prism.languages.markup; + if (markup) { + markup.tag.addInlined('style', 'css'); + markup.tag.addAttribute('style', 'css'); + } + +}(Prism)); + (function (Prism) { /** @@ -2060,50 +2348,223 @@ Prism.languages.sql = { }(Prism)); -// https://www.json.org/json-en.html -Prism.languages.json = { - 'property': { - pattern: /(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/, - lookbehind: true, - greedy: true - }, - 'string': { - pattern: /(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/, - lookbehind: true, - greedy: true - }, - 'comment': { - pattern: /\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/, - greedy: true - }, - 'number': /-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i, - 'punctuation': /[{}[\],]/, - 'operator': /:/, - 'boolean': /\b(?:false|true)\b/, - 'null': { - pattern: /\bnull\b/, - alias: 'keyword' - } -}; - -Prism.languages.webmanifest = Prism.languages.json; - -(function (Prism) { - - var string = /("|')(?:\\(?:\r\n?|\n|.)|(?!\1)[^\\\r\n])*\1/; - - Prism.languages.json5 = Prism.languages.extend('json', { - 'property': [ - { - pattern: RegExp(string.source + '(?=\\s*:)'), - greedy: true - }, - { - pattern: /(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/, - alias: 'unquoted' - } - ], - 'string': { +Prism.languages.javascript = Prism.languages.extend('clike', { + 'class-name': [ + Prism.languages.clike['class-name'], + { + pattern: /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/, + lookbehind: true + } + ], + 'keyword': [ + { + pattern: /((?:^|\})\s*)catch\b/, + lookbehind: true + }, + { + pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/, + lookbehind: true + }, + ], + // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444) + 'function': /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/, + 'number': { + pattern: RegExp( + /(^|[^\w$])/.source + + '(?:' + + ( + // constant + /NaN|Infinity/.source + + '|' + + // binary integer + /0[bB][01]+(?:_[01]+)*n?/.source + + '|' + + // octal integer + /0[oO][0-7]+(?:_[0-7]+)*n?/.source + + '|' + + // hexadecimal integer + /0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source + + '|' + + // decimal bigint + /\d+(?:_\d+)*n/.source + + '|' + + // decimal number (integer or float) but no bigint + /(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source + ) + + ')' + + /(?![\w$])/.source + ), + lookbehind: true + }, + 'operator': /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/ +}); + +Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/; + +Prism.languages.insertBefore('javascript', 'keyword', { + 'regex': { + pattern: RegExp( + // lookbehind + // eslint-disable-next-line regexp/no-dupe-characters-character-class + /((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source + + // Regex pattern: + // There are 2 regex patterns here. The RegExp set notation proposal added support for nested character + // classes if the `v` flag is present. Unfortunately, nested CCs are both context-free and incompatible + // with the only syntax, so we have to define 2 different regex patterns. + /\//.source + + '(?:' + + /(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source + + '|' + + // `v` flag syntax. This supports 3 levels of nested character classes. + /(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source + + ')' + + // lookahead + /(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source + ), + lookbehind: true, + greedy: true, + inside: { + 'regex-source': { + pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/, + lookbehind: true, + alias: 'language-regex', + inside: Prism.languages.regex + }, + 'regex-delimiter': /^\/|\/$/, + 'regex-flags': /^[a-z]+$/, + } + }, + // This must be declared before keyword because we use "function" inside the look-forward + 'function-variable': { + pattern: /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/, + alias: 'function' + }, + 'parameter': [ + { + pattern: /(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/, + lookbehind: true, + inside: Prism.languages.javascript + }, + { + pattern: /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i, + lookbehind: true, + inside: Prism.languages.javascript + }, + { + pattern: /(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/, + lookbehind: true, + inside: Prism.languages.javascript + }, + { + pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/, + lookbehind: true, + inside: Prism.languages.javascript + } + ], + 'constant': /\b[A-Z](?:[A-Z_]|\dx?)*\b/ +}); + +Prism.languages.insertBefore('javascript', 'string', { + 'hashbang': { + pattern: /^#!.*/, + greedy: true, + alias: 'comment' + }, + 'template-string': { + pattern: /`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/, + greedy: true, + inside: { + 'template-punctuation': { + pattern: /^`|`$/, + alias: 'string' + }, + 'interpolation': { + pattern: /((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/, + lookbehind: true, + inside: { + 'interpolation-punctuation': { + pattern: /^\$\{|\}$/, + alias: 'punctuation' + }, + rest: Prism.languages.javascript + } + }, + 'string': /[\s\S]+/ + } + }, + 'string-property': { + pattern: /((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m, + lookbehind: true, + greedy: true, + alias: 'property' + } +}); + +Prism.languages.insertBefore('javascript', 'operator', { + 'literal-property': { + pattern: /((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m, + lookbehind: true, + alias: 'property' + }, +}); + +if (Prism.languages.markup) { + Prism.languages.markup.tag.addInlined('script', 'javascript'); + + // add attribute support for all DOM events. + // https://developer.mozilla.org/en-US/docs/Web/Events#Standard_events + Prism.languages.markup.tag.addAttribute( + /on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source, + 'javascript' + ); +} + +Prism.languages.js = Prism.languages.javascript; + +// https://www.json.org/json-en.html +Prism.languages.json = { + 'property': { + pattern: /(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/, + lookbehind: true, + greedy: true + }, + 'string': { + pattern: /(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/, + lookbehind: true, + greedy: true + }, + 'comment': { + pattern: /\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/, + greedy: true + }, + 'number': /-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i, + 'punctuation': /[{}[\],]/, + 'operator': /:/, + 'boolean': /\b(?:false|true)\b/, + 'null': { + pattern: /\bnull\b/, + alias: 'keyword' + } +}; + +Prism.languages.webmanifest = Prism.languages.json; + +(function (Prism) { + + var string = /("|')(?:\\(?:\r\n?|\n|.)|(?!\1)[^\\\r\n])*\1/; + + Prism.languages.json5 = Prism.languages.extend('json', { + 'property': [ + { + pattern: RegExp(string.source + '(?=\\s*:)'), + greedy: true + }, + { + pattern: /(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/, + alias: 'unquoted' + } + ], + 'string': { pattern: string, greedy: true }, @@ -2147,27 +2608,247 @@ Prism.languages.jsstacktrace = { inside: { 'punctuation': /\./ } - }, - - 'punctuation': /[()]/, - - 'keyword': /\b(?:at|new)\b/, + }, + + 'punctuation': /[()]/, + + 'keyword': /\b(?:at|new)\b/, + + 'alias': { + pattern: /\[(?:as\s+)?(?!\s)[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\]/, + alias: 'variable' + }, + + 'line-number': { + pattern: /:\d+(?::\d+)?\b/, + alias: 'number', + inside: { + 'punctuation': /:/ + } + }, + + } + } +}; + +Prism.languages.markup = { + 'comment': { + pattern: //, + greedy: true + }, + 'prolog': { + pattern: /<\?[\s\S]+?\?>/, + greedy: true + }, + 'doctype': { + // https://www.w3.org/TR/xml/#NT-doctypedecl + pattern: /"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i, + greedy: true, + inside: { + 'internal-subset': { + pattern: /(^[^\[]*\[)[\s\S]+(?=\]>$)/, + lookbehind: true, + greedy: true, + inside: null // see below + }, + 'string': { + pattern: /"[^"]*"|'[^']*'/, + greedy: true + }, + 'punctuation': /^$|[[\]]/, + 'doctype-tag': /^DOCTYPE/i, + 'name': /[^\s<>'"]+/ + } + }, + 'cdata': { + pattern: //i, + greedy: true + }, + 'tag': { + pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/, + greedy: true, + inside: { + 'tag': { + pattern: /^<\/?[^\s>\/]+/, + inside: { + 'punctuation': /^<\/?/, + 'namespace': /^[^\s>\/:]+:/ + } + }, + 'special-attr': [], + 'attr-value': { + pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/, + inside: { + 'punctuation': [ + { + pattern: /^=/, + alias: 'attr-equals' + }, + { + pattern: /^(\s*)["']|["']$/, + lookbehind: true + } + ] + } + }, + 'punctuation': /\/?>/, + 'attr-name': { + pattern: /[^\s>\/]+/, + inside: { + 'namespace': /^[^\s>\/:]+:/ + } + } + + } + }, + 'entity': [ + { + pattern: /&[\da-z]{1,8};/i, + alias: 'named-entity' + }, + /&#x?[\da-f]{1,8};/i + ] +}; + +Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] = + Prism.languages.markup['entity']; +Prism.languages.markup['doctype'].inside['internal-subset'].inside = Prism.languages.markup; + +// Plugin to make entity title show the real entity, idea by Roman Komarov +Prism.hooks.add('wrap', function (env) { + + if (env.type === 'entity') { + env.attributes['title'] = env.content.replace(/&/, '&'); + } +}); + +Object.defineProperty(Prism.languages.markup.tag, 'addInlined', { + /** + * Adds an inlined language to markup. + * + * An example of an inlined language is CSS with `