| @@ -1,13 +1,13 @@ |
| 1 | /* PrismJS 1.23.0 | 1 | /* PrismJS 1.23.0 |
| 2 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+c+cpp+coffeescript+crystal+d+dart+diff+django+elixir+erlang+go+groovy+java+json+julia+kotlin+lua+markup-templating+matlab+nginx+nim+ocaml+perl+php+python+jsx+ruby+rust+scss+shell-session+sql+typescript+yaml */ | 2 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+c+cpp+coffeescript+crystal+d+dart+diff+django+elixir+erlang+go+groovy+java+json+julia+kotlin+latex+lua+markup-templating+matlab+nginx+nim+ocaml+perl+php+python+jsx+ruby+rust+scss+shell-session+sql+typescript+yaml */ |
| 3 | /// <reference lib="WebWorker"/> | 3 | /// <reference lib="WebWorker"/> |
| 4 | | 4 | |
| 5 | var _self = (typeof window !== 'undefined') | 5 | var _self = (typeof window !== 'undefined') |
| 6 | ? window // if in browser | 6 | ? window // if in browser |
| 7 | : ( | 7 | : ( |
| 8 | (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) | 8 | (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) |
| 9 | ? self // if in worker | 9 | ? self // if in worker |
| 10 | : {} // if in node js | 10 | : {} // if in node js |
| 11 | ); | 11 | ); |
| 12 | | 12 | |
| 13 | /** | 13 | /** |
| @@ -18,1133 +18,1151 @@ var _self = (typeof window !== 'undefined') · 4 unmodified lines |
| 18 | * @namespace | 18 | * @namespace |
| 19 | * @public | 19 | * @public |
| 20 | */ | 20 | */ |
| 21 | var Prism = (function (_self){ | 21 | var Prism = (function (_self) { |
| 22 | | 22 | |
| 23 | // Private helper vars | 23 | // Private helper vars |
| 24 | var lang = /\blang(?:uage)?-([\w-]+)\b/i; | 24 | var lang = /\blang(?:uage)?-([\w-]+)\b/i; |
| 25 | var uniqueId = 0; | 25 | var uniqueId = 0; |
| 26 | | 26 | |
| | 27 | // The grammar object for plaintext |
| | 28 | var plainTextGrammar = {}; |
| 27 | | 29 | |
| 28 | var _ = { | | |
| 29 | /** | | |
| 30 | * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the | | |
| 31 | * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load | | |
| 32 | * additional languages or plugins yourself. | | |
| 33 | * | | |
| 34 | * By setting this value to `true`, Prism will not automatically highlight all code elements on the page. | | |
| 35 | * | | |
| 36 | * You obviously have to change this value before the automatic highlighting started. To do this, you can add an | | |
| 37 | * empty Prism object into the global scope before loading the Prism script like this: | | |
| 38 | * | | |
| 39 | * ```js | | |
| 40 | * window.Prism = window.Prism || {}; | | |
| 41 | * Prism.manual = true; | | |
| 42 | * // add a new <script> to load Prism's script | | |
| 43 | * ``` | | |
| 44 | * | | |
| 45 | * @default false | | |
| 46 | * @type {boolean} | | |
| 47 | * @memberof Prism | | |
| 48 | * @public | | |
| 49 | */ | | |
| 50 | manual: _self.Prism && _self.Prism.manual, | | |
| 51 | disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler, | | |
| 52 | | | |
| 53 | /** | | |
| 54 | * A namespace for utility methods. | | |
| 55 | * | | |
| 56 | * All function in this namespace that are not explicitly marked as _public_ are for __internal use only__ and may | | |
| 57 | * change or disappear at any time. | | |
| 58 | * | | |
| 59 | * @namespace | | |
| 60 | * @memberof Prism | | |
| 61 | */ | | |
| 62 | util: { | | |
| 63 | encode: function encode(tokens) { | | |
| 64 | if (tokens instanceof Token) { | | |
| 65 | return new Token(tokens.type, encode(tokens.content), tokens.alias); | | |
| 66 | } else if (Array.isArray(tokens)) { | | |
| 67 | return tokens.map(encode); | | |
| 68 | } else { | | |
| 69 | return tokens.replace(/&/g, '&').replace(/</g, '<').replace(/\u00a0/g, ' '); | | |
| 70 | } | | |
| 71 | }, | | |
| 72 | | 30 | |
| | 31 | var _ = { |
| 73 | /** | 32 | /** |
| 74 | * Returns the name of the type of the given value. | 33 | * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the |
| | 34 | * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load |
| | 35 | * additional languages or plugins yourself. |
| 75 | * | 36 | * |
| 76 | * @param {any} o | 37 | * By setting this value to `true`, Prism will not automatically highlight all code elements on the page. |
| 77 | * @returns {string} | 38 | * |
| 78 | * @example | 39 | * You obviously have to change this value before the automatic highlighting started. To do this, you can add an |
| 79 | * type(null) === 'Null' | 40 | * empty Prism object into the global scope before loading the Prism script like this: |
| 80 | * type(undefined) === 'Undefined' | | |
| 81 | * type(123) === 'Number' | | |
| 82 | * type('foo') === 'String' | | |
| 83 | * type(true) === 'Boolean' | | |
| 84 | * type([1, 2]) === 'Array' | | |
| 85 | * type({}) === 'Object' | | |
| 86 | * type(String) === 'Function' | | |
| 87 | * type(/abc+/) === 'RegExp' | | |
| 88 | */ | | |
| 89 | type: function (o) { | | |
| 90 | return Object.prototype.toString.call(o).slice(8, -1); | | |
| 91 | }, | | |
| 92 | | | |
| 93 | /** | | |
| 94 | * Returns a unique number for the given object. Later calls will still return the same number. | | |
| 95 | * | 41 | * |
| 96 | * @param {Object} obj | 42 | * ```js |
| 97 | * @returns {number} | 43 | * window.Prism = window.Prism || {}; |
| | 44 | * Prism.manual = true; |
| | 45 | * // add a new <script> to load Prism's script |
| | 46 | * ``` |
| | 47 | * |
| | 48 | * @default false |
| | 49 | * @type {boolean} |
| | 50 | * @memberof Prism |
| | 51 | * @public |
| 98 | */ | 52 | */ |
| 99 | objId: function (obj) { | 53 | manual: _self.Prism && _self.Prism.manual, |
| 100 | if (!obj['__id']) { | 54 | disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler, |
| 101 | Object.defineProperty(obj, '__id', { value: ++uniqueId }); | | |
| 102 | } | | |
| 103 | return obj['__id']; | | |
| 104 | }, | | |
| 105 | | 55 | |
| 106 | /** | 56 | /** |
| 107 | * Creates a deep clone of the given object. | 57 | * A namespace for utility methods. |
| 108 | * | 58 | * |
| 109 | * The main intended use of this function is to clone language definitions. | 59 | * All function in this namespace that are not explicitly marked as _public_ are for __internal use only__ and may |
| | 60 | * change or disappear at any time. |
| 110 | * | 61 | * |
| 111 | * @param {T} o | 62 | * @namespace |
| 112 | * @param {Record<number, any>} [visited] | 63 | * @memberof Prism |
| 113 | * @returns {T} | | |
| 114 | * @template T | | |
| 115 | */ | 64 | */ |
| 116 | clone: function deepClone(o, visited) { | 65 | util: { |
| 117 | visited = visited || {}; | 66 | encode: function encode(tokens) { |
| 118 | | 67 | if (tokens instanceof Token) { |
| 119 | var clone, id; | 68 | return new Token(tokens.type, encode(tokens.content), tokens.alias); |
| 120 | switch (_.util.type(o)) { | 69 | } else if (Array.isArray(tokens)) { |
| 121 | case 'Object': | 70 | return tokens.map(encode); |
| 122 | id = _.util.objId(o); | 71 | } else { |
| 123 | if (visited[id]) { | 72 | return tokens.replace(/&/g, '&').replace(/</g, '<').replace(/\u00a0/g, ' '); |
| 124 | return visited[id]; | 73 | } |
| 125 | } | 74 | }, |
| 126 | clone = /** @type {Record<string, any>} */ ({}); | 75 | |
| 127 | visited[id] = clone; | 76 | /** |
| | 77 | * Returns the name of the type of the given value. |
| | 78 | * |
| | 79 | * @param {any} o |
| | 80 | * @returns {string} |
| | 81 | * @example |
| | 82 | * type(null) === 'Null' |
| | 83 | * type(undefined) === 'Undefined' |
| | 84 | * type(123) === 'Number' |
| | 85 | * type('foo') === 'String' |
| | 86 | * type(true) === 'Boolean' |
| | 87 | * type([1, 2]) === 'Array' |
| | 88 | * type({}) === 'Object' |
| | 89 | * type(String) === 'Function' |
| | 90 | * type(/abc+/) === 'RegExp' |
| | 91 | */ |
| | 92 | type: function (o) { |
| | 93 | return Object.prototype.toString.call(o).slice(8, -1); |
| | 94 | }, |
| | 95 | |
| | 96 | /** |
| | 97 | * Returns a unique number for the given object. Later calls will still return the same number. |
| | 98 | * |
| | 99 | * @param {Object} obj |
| | 100 | * @returns {number} |
| | 101 | */ |
| | 102 | objId: function (obj) { |
| | 103 | if (!obj['__id']) { |
| | 104 | Object.defineProperty(obj, '__id', { value: ++uniqueId }); |
| | 105 | } |
| | 106 | return obj['__id']; |
| | 107 | }, |
| 128 | | 108 | |
| 129 | for (var key in o) { | 109 | /** |
| 130 | if (o.hasOwnProperty(key)) { | 110 | * Creates a deep clone of the given object. |
| 131 | clone[key] = deepClone(o[key], visited); | 111 | * |
| | 112 | * The main intended use of this function is to clone language definitions. |
| | 113 | * |
| | 114 | * @param {T} o |
| | 115 | * @param {Record<number, any>} [visited] |
| | 116 | * @returns {T} |
| | 117 | * @template T |
| | 118 | */ |
| | 119 | clone: function deepClone(o, visited) { |
| | 120 | visited = visited || {}; |
| | 121 | |
| | 122 | var clone; var id; |
| | 123 | switch (_.util.type(o)) { |
| | 124 | case 'Object': |
| | 125 | id = _.util.objId(o); |
| | 126 | if (visited[id]) { |
| | 127 | return visited[id]; |
| 132 | } | 128 | } |
| 133 | } | 129 | clone = /** @type {Record<string, any>} */ ({}); |
| | 130 | visited[id] = clone; |
| 134 | | 131 | |
| 135 | return /** @type {any} */ (clone); | 132 | for (var key in o) { |
| | 133 | if (o.hasOwnProperty(key)) { |
| | 134 | clone[key] = deepClone(o[key], visited); |
| | 135 | } |
| | 136 | } |
| 136 | | 137 | |
| 137 | case 'Array': | 138 | return /** @type {any} */ (clone); |
| 138 | id = _.util.objId(o); | | |
| 139 | if (visited[id]) { | | |
| 140 | return visited[id]; | | |
| 141 | } | | |
| 142 | clone = []; | | |
| 143 | visited[id] = clone; | | |
| 144 | | 139 | |
| 145 | (/** @type {Array} */(/** @type {any} */(o))).forEach(function (v, i) { | 140 | case 'Array': |
| 146 | clone[i] = deepClone(v, visited); | 141 | id = _.util.objId(o); |
| 147 | }); | 142 | if (visited[id]) { |
| | 143 | return visited[id]; |
| | 144 | } |
| | 145 | clone = []; |
| | 146 | visited[id] = clone; |
| 148 | | 147 | |
| 149 | return /** @type {any} */ (clone); | 148 | (/** @type {Array} */(/** @type {any} */(o))).forEach(function (v, i) { |
| | 149 | clone[i] = deepClone(v, visited); |
| | 150 | }); |
| 150 | | 151 | |
| 151 | default: | 152 | return /** @type {any} */ (clone); |
| 152 | return o; | | |
| 153 | } | | |
| 154 | }, | | |
| 155 | | 153 | |
| 156 | /** | 154 | default: |
| 157 | * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class. | 155 | return o; |
| 158 | * | 156 | } |
| 159 | * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned. | 157 | }, |
| 160 | * | | |
| 161 | * @param {Element} element | | |
| 162 | * @returns {string} | | |
| 163 | */ | | |
| 164 | getLanguage: function (element) { | | |
| 165 | while (element && !lang.test(element.className)) { | | |
| 166 | element = element.parentElement; | | |
| 167 | } | | |
| 168 | if (element) { | | |
| 169 | return (element.className.match(lang) || [, 'none'])[1].toLowerCase(); | | |
| 170 | } | | |
| 171 | return 'none'; | | |
| 172 | }, | | |
| 173 | | 158 | |
| 174 | /** | 159 | /** |
| 175 | * Returns the script element that is currently executing. | 160 | * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class. |
| 176 | * | 161 | * |
| 177 | * This does __not__ work for line script element. | 162 | * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned. |
| 178 | * | 163 | * |
| 179 | * @returns {HTMLScriptElement | null} | 164 | * @param {Element} element |
| 180 | */ | 165 | * @returns {string} |
| 181 | currentScript: function () { | 166 | */ |
| 182 | if (typeof document === 'undefined') { | 167 | getLanguage: function (element) { |
| 183 | return null; | 168 | while (element && !lang.test(element.className)) { |
| 184 | } | 169 | element = element.parentElement; |
| 185 | if ('currentScript' in document && 1 < 2 /* hack to trip TS' flow analysis */) { | 170 | } |
| 186 | return /** @type {any} */ (document.currentScript); | 171 | if (element) { |
| 187 | } | 172 | return (element.className.match(lang) || [, 'none'])[1].toLowerCase(); |
| | 173 | } |
| | 174 | return 'none'; |
| | 175 | }, |
| 188 | | 176 | |
| 189 | // IE11 workaround | 177 | /** |
| 190 | // we'll get the src of the current script by parsing IE11's error stack trace | 178 | * Returns the script element that is currently executing. |
| 191 | // this will not work for inline scripts | 179 | * |
| | 180 | * This does __not__ work for line script element. |
| | 181 | * |
| | 182 | * @returns {HTMLScriptElement | null} |
| | 183 | */ |
| | 184 | currentScript: function () { |
| | 185 | if (typeof document === 'undefined') { |
| | 186 | return null; |
| | 187 | } |
| | 188 | if ('currentScript' in document && 1 < 2 /* hack to trip TS' flow analysis */) { |
| | 189 | return /** @type {any} */ (document.currentScript); |
| | 190 | } |
| 192 | | 191 | |
| 193 | try { | 192 | // IE11 workaround |
| 194 | throw new Error(); | 193 | // we'll get the src of the current script by parsing IE11's error stack trace |
| 195 | } catch (err) { | 194 | // this will not work for inline scripts |
| 196 | // Get file src url from stack. Specifically works with the format of stack traces in IE. | 195 | |
| 197 | // A stack will look like this: | 196 | try { |
| 198 | // | 197 | throw new Error(); |
| 199 | // Error | 198 | } catch (err) { |
| 200 | // at _.util.currentScript (http://localhost/components/prism-core.js:119:5) | 199 | // Get file src url from stack. Specifically works with the format of stack traces in IE. |
| 201 | // at Global code (http://localhost/components/prism-core.js:606:1) | 200 | // A stack will look like this: |
| 202 | | 201 | // |
| 203 | var src = (/at [^(\r\n]*\((.*):.+:.+\)$/i.exec(err.stack) || [])[1]; | 202 | // Error |
| 204 | if (src) { | 203 | // at _.util.currentScript (http://localhost/components/prism-core.js:119:5) |
| 205 | var scripts = document.getElementsByTagName('script'); | 204 | // at Global code (http://localhost/components/prism-core.js:606:1) |
| 206 | for (var i in scripts) { | 205 | |
| 207 | if (scripts[i].src == src) { | 206 | var src = (/at [^(\r\n]*\((.*):.+:.+\)$/i.exec(err.stack) || [])[1]; |
| 208 | return scripts[i]; | 207 | if (src) { |
| | 208 | var scripts = document.getElementsByTagName('script'); |
| | 209 | for (var i in scripts) { |
| | 210 | if (scripts[i].src == src) { |
| | 211 | return scripts[i]; |
| | 212 | } |
| 209 | } | 213 | } |
| 210 | } | 214 | } |
| | 215 | return null; |
| | 216 | } |
| | 217 | }, |
| | 218 | |
| | 219 | /** |
| | 220 | * Returns whether a given class is active for `element`. |
| | 221 | * |
| | 222 | * The class can be activated if `element` or one of its ancestors has the given class and it can be deactivated |
| | 223 | * if `element` or one of its ancestors has the negated version of the given class. The _negated version_ of the |
| | 224 | * given class is just the given class with a `no-` prefix. |
| | 225 | * |
| | 226 | * Whether the class is active is determined by the closest ancestor of `element` (where `element` itself is |
| | 227 | * closest ancestor) that has the given class or the negated version of it. If neither `element` nor any of its |
| | 228 | * ancestors have the given class or the negated version of it, then the default activation will be returned. |
| | 229 | * |
| | 230 | * In the paradoxical situation where the closest ancestor contains __both__ the given class and the negated |
| | 231 | * version of it, the class is considered active. |
| | 232 | * |
| | 233 | * @param {Element} element |
| | 234 | * @param {string} className |
| | 235 | * @param {boolean} [defaultActivation=false] |
| | 236 | * @returns {boolean} |
| | 237 | */ |
| | 238 | isActive: function (element, className, defaultActivation) { |
| | 239 | var no = 'no-' + className; |
| | 240 | |
| | 241 | while (element) { |
| | 242 | var classList = element.classList; |
| | 243 | if (classList.contains(className)) { |
| | 244 | return true; |
| | 245 | } |
| | 246 | if (classList.contains(no)) { |
| | 247 | return false; |
| | 248 | } |
| | 249 | element = element.parentElement; |
| 211 | } | 250 | } |
| 212 | return null; | 251 | return !!defaultActivation; |
| 213 | } | 252 | } |
| 214 | }, | 253 | }, |
| 215 | | 254 | |
| 216 | /** | 255 | /** |
| 217 | * Returns whether a given class is active for `element`. | 256 | * This namespace contains all currently loaded languages and the some helper functions to create and modify languages. |
| 218 | * | 257 | * |
| 219 | * The class can be activated if `element` or one of its ancestors has the given class and it can be deactivated | 258 | * @namespace |
| 220 | * if `element` or one of its ancestors has the negated version of the given class. The _negated version_ of the | 259 | * @memberof Prism |
| 221 | * given class is just the given class with a `no-` prefix. | 260 | * @public |
| 222 | * | | |
| 223 | * Whether the class is active is determined by the closest ancestor of `element` (where `element` itself is | | |
| 224 | * closest ancestor) that has the given class or the negated version of it. If neither `element` nor any of its | | |
| 225 | * ancestors have the given class or the negated version of it, then the default activation will be returned. | | |
| 226 | * | | |
| 227 | * In the paradoxical situation where the closest ancestor contains __both__ the given class and the negated | | |
| 228 | * version of it, the class is considered active. | | |
| 229 | * | | |
| 230 | * @param {Element} element | | |
| 231 | * @param {string} className | | |
| 232 | * @param {boolean} [defaultActivation=false] | | |
| 233 | * @returns {boolean} | | |
| 234 | */ | 261 | */ |
| 235 | isActive: function (element, className, defaultActivation) { | 262 | languages: { |
| 236 | var no = 'no-' + className; | 263 | /** |
| | 264 | * The grammar for plain, unformatted text. |
| | 265 | */ |
| | 266 | plain: plainTextGrammar, |
| | 267 | plaintext: plainTextGrammar, |
| | 268 | text: plainTextGrammar, |
| | 269 | txt: plainTextGrammar, |
| 237 | | 270 | |
| 238 | while (element) { | 271 | /** |
| 239 | var classList = element.classList; | 272 | * Creates a deep copy of the language with the given id and appends the given tokens. |
| 240 | if (classList.contains(className)) { | 273 | * |
| 241 | return true; | 274 | * If a token in `redef` also appears in the copied language, then the existing token in the copied language |
| | 275 | * will be overwritten at its original position. |
| | 276 | * |
| | 277 | * ## Best practices |
| | 278 | * |
| | 279 | * Since the position of overwriting tokens (token in `redef` that overwrite tokens in the copied language) |
| | 280 | * doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to |
| | 281 | * understand the language definition because, normally, the order of tokens matters in Prism grammars. |
| | 282 | * |
| | 283 | * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens. |
| | 284 | * Furthermore, all non-overwriting tokens should be placed after the overwriting ones. |
| | 285 | * |
| | 286 | * @param {string} id The id of the language to extend. This has to be a key in `Prism.languages`. |
| | 287 | * @param {Grammar} redef The new tokens to append. |
| | 288 | * @returns {Grammar} The new language created. |
| | 289 | * @public |
| | 290 | * @example |
| | 291 | * Prism.languages['css-with-colors'] = Prism.languages.extend('css', { |
| | 292 | * // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token |
| | 293 | * // at its original position |
| | 294 | * 'comment': { ... }, |
| | 295 | * // CSS doesn't have a 'color' token, so this token will be appended |
| | 296 | * 'color': /\b(?:red|green|blue)\b/ |
| | 297 | * }); |
| | 298 | */ |
| | 299 | extend: function (id, redef) { |
| | 300 | var lang = _.util.clone(_.languages[id]); |
| | 301 | |
| | 302 | for (var key in redef) { |
| | 303 | lang[key] = redef[key]; |
| | 304 | } |
| | 305 | |
| | 306 | return lang; |
| | 307 | }, |
| | 308 | |
| | 309 | /** |
| | 310 | * Inserts tokens _before_ another token in a language definition or any other grammar. |
| | 311 | * |
| | 312 | * ## Usage |
| | 313 | * |
| | 314 | * This helper method makes it easy to modify existing languages. For example, the CSS language definition |
| | 315 | * not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded |
| | 316 | * in HTML through `<style>` elements. To do this, it needs to modify `Prism.languages.markup` and add the |
| | 317 | * appropriate tokens. However, `Prism.languages.markup` is a regular JavaScript object literal, so if you do |
| | 318 | * this: |
| | 319 | * |
| | 320 | * ```js |
| | 321 | * Prism.languages.markup.style = { |
| | 322 | * // token |
| | 323 | * }; |
| | 324 | * ``` |
| | 325 | * |
| | 326 | * then the `style` token will be added (and processed) at the end. `insertBefore` allows you to insert tokens |
| | 327 | * before existing tokens. For the CSS example above, you would use it like this: |
| | 328 | * |
| | 329 | * ```js |
| | 330 | * Prism.languages.insertBefore('markup', 'cdata', { |
| | 331 | * 'style': { |
| | 332 | * // token |
| | 333 | * } |
| | 334 | * }); |
| | 335 | * ``` |
| | 336 | * |
| | 337 | * ## Special cases |
| | 338 | * |
| | 339 | * If the grammars of `inside` and `insert` have tokens with the same name, the tokens in `inside`'s grammar |
| | 340 | * will be ignored. |
| | 341 | * |
| | 342 | * This behavior can be used to insert tokens after `before`: |
| | 343 | * |
| | 344 | * ```js |
| | 345 | * Prism.languages.insertBefore('markup', 'comment', { |
| | 346 | * 'comment': Prism.languages.markup.comment, |
| | 347 | * // tokens after 'comment' |
| | 348 | * }); |
| | 349 | * ``` |
| | 350 | * |
| | 351 | * ## Limitations |
| | 352 | * |
| | 353 | * The main problem `insertBefore` has to solve is iteration order. Since ES2015, the iteration order for object |
| | 354 | * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave |
| | 355 | * differently when keys are deleted and re-inserted. So `insertBefore` can't be implemented by temporarily |
| | 356 | * deleting properties which is necessary to insert at arbitrary positions. |
| | 357 | * |
| | 358 | * To solve this problem, `insertBefore` doesn't actually insert the given tokens into the target object. |
| | 359 | * Instead, it will create a new object and replace all references to the target object with the new one. This |
| | 360 | * can be done without temporarily deleting properties, so the iteration order is well-defined. |
| | 361 | * |
| | 362 | * However, only references that can be reached from `Prism.languages` or `insert` will be replaced. I.e. if |
| | 363 | * you hold the target object in a variable, then the value of the variable will not change. |
| | 364 | * |
| | 365 | * ```js |
| | 366 | * var oldMarkup = Prism.languages.markup; |
| | 367 | * var newMarkup = Prism.languages.insertBefore('markup', 'comment', { ... }); |
| | 368 | * |
| | 369 | * assert(oldMarkup !== Prism.languages.markup); |
| | 370 | * assert(newMarkup === Prism.languages.markup); |
| | 371 | * ``` |
| | 372 | * |
| | 373 | * @param {string} inside The property of `root` (e.g. a language id in `Prism.languages`) that contains the |
| | 374 | * object to be modified. |
| | 375 | * @param {string} before The key to insert before. |
| | 376 | * @param {Grammar} insert An object containing the key-value pairs to be inserted. |
| | 377 | * @param {Object<string, any>} [root] The object containing `inside`, i.e. the object that contains the |
| | 378 | * object to be modified. |
| | 379 | * |
| | 380 | * Defaults to `Prism.languages`. |
| | 381 | * @returns {Grammar} The new grammar object. |
| | 382 | * @public |
| | 383 | */ |
| | 384 | insertBefore: function (inside, before, insert, root) { |
| | 385 | root = root || /** @type {any} */ (_.languages); |
| | 386 | var grammar = root[inside]; |
| | 387 | /** @type {Grammar} */ |
| | 388 | var ret = {}; |
| | 389 | |
| | 390 | for (var token in grammar) { |
| | 391 | if (grammar.hasOwnProperty(token)) { |
| | 392 | |
| | 393 | if (token == before) { |
| | 394 | for (var newToken in insert) { |
| | 395 | if (insert.hasOwnProperty(newToken)) { |
| | 396 | ret[newToken] = insert[newToken]; |
| | 397 | } |
| | 398 | } |
| | 399 | } |
| | 400 | |
| | 401 | // Do not insert token which also occur in insert. See #1525 |
| | 402 | if (!insert.hasOwnProperty(token)) { |
| | 403 | ret[token] = grammar[token]; |
| | 404 | } |
| | 405 | } |
| 242 | } | 406 | } |
| 243 | if (classList.contains(no)) { | 407 | |
| 244 | return false; | 408 | var old = root[inside]; |
| | 409 | root[inside] = ret; |
| | 410 | |
| | 411 | // Update references in other language definitions |
| | 412 | _.languages.DFS(_.languages, function (key, value) { |
| | 413 | if (value === old && key != inside) { |
| | 414 | this[key] = ret; |
| | 415 | } |
| | 416 | }); |
| | 417 | |
| | 418 | return ret; |
| | 419 | }, |
| | 420 | |
| | 421 | // Traverse a language definition with Depth First Search |
| | 422 | DFS: function DFS(o, callback, type, visited) { |
| | 423 | visited = visited || {}; |
| | 424 | |
| | 425 | var objId = _.util.objId; |
| | 426 | |
| | 427 | for (var i in o) { |
| | 428 | if (o.hasOwnProperty(i)) { |
| | 429 | callback.call(o, i, o[i], type || i); |
| | 430 | |
| | 431 | var property = o[i]; |
| | 432 | var propertyType = _.util.type(property); |
| | 433 | |
| | 434 | if (propertyType === 'Object' && !visited[objId(property)]) { |
| | 435 | visited[objId(property)] = true; |
| | 436 | DFS(property, callback, null, visited); |
| | 437 | } else if (propertyType === 'Array' && !visited[objId(property)]) { |
| | 438 | visited[objId(property)] = true; |
| | 439 | DFS(property, callback, i, visited); |
| | 440 | } |
| | 441 | } |
| 245 | } | 442 | } |
| 246 | element = element.parentElement; | | |
| 247 | } | 443 | } |
| 248 | return !!defaultActivation; | 444 | }, |
| 249 | } | 445 | |
| 250 | }, | 446 | plugins: {}, |
| 251 | | 447 | |
| 252 | /** | | |
| 253 | * This namespace contains all currently loaded languages and the some helper functions to create and modify languages. | | |
| 254 | * | | |
| 255 | * @namespace | | |
| 256 | * @memberof Prism | | |
| 257 | * @public | | |
| 258 | */ | | |
| 259 | languages: { | | |
| 260 | /** | 448 | /** |
| 261 | * Creates a deep copy of the language with the given id and appends the given tokens. | 449 | * This is the most high-level function in Prism’s API. |
| | 450 | * It fetches all the elements that have a `.language-xxxx` class and then calls {@link Prism.highlightElement} on |
| | 451 | * each one of them. |
| 262 | * | 452 | * |
| 263 | * If a token in `redef` also appears in the copied language, then the existing token in the copied language | 453 | * This is equivalent to `Prism.highlightAllUnder(document, async, callback)`. |
| 264 | * will be overwritten at its original position. | | |
| 265 | * | 454 | * |
| 266 | * ## Best practices | 455 | * @param {boolean} [async=false] Same as in {@link Prism.highlightAllUnder}. |
| 267 | * | 456 | * @param {HighlightCallback} [callback] Same as in {@link Prism.highlightAllUnder}. |
| 268 | * Since the position of overwriting tokens (token in `redef` that overwrite tokens in the copied language) | 457 | * @memberof Prism |
| 269 | * doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to | 458 | * @public |
| 270 | * understand the language definition because, normally, the order of tokens matters in Prism grammars. | 459 | */ |
| | 460 | highlightAll: function (async, callback) { |
| | 461 | _.highlightAllUnder(document, async, callback); |
| | 462 | }, |
| | 463 | |
| | 464 | /** |
| | 465 | * Fetches all the descendants of `container` that have a `.language-xxxx` class and then calls |
| | 466 | * {@link Prism.highlightElement} on each one of them. |
| 271 | * | 467 | * |
| 272 | * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens. | 468 | * The following hooks will be run: |
| 273 | * Furthermore, all non-overwriting tokens should be placed after the overwriting ones. | 469 | * 1. `before-highlightall` |
| | 470 | * 2. `before-all-elements-highlight` |
| | 471 | * 3. All hooks of {@link Prism.highlightElement} for each element. |
| 274 | * | 472 | * |
| 275 | * @param {string} id The id of the language to extend. This has to be a key in `Prism.languages`. | 473 | * @param {ParentNode} container The root element, whose descendants that have a `.language-xxxx` class will be highlighted. |
| 276 | * @param {Grammar} redef The new tokens to append. | 474 | * @param {boolean} [async=false] Whether each element is to be highlighted asynchronously using Web Workers. |
| 277 | * @returns {Grammar} The new language created. | 475 | * @param {HighlightCallback} [callback] An optional callback to be invoked on each element after its highlighting is done. |
| | 476 | * @memberof Prism |
| 278 | * @public | 477 | * @public |
| 279 | * @example | | |
| 280 | * Prism.languages['css-with-colors'] = Prism.languages.extend('css', { | | |
| 281 | * // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token | | |
| 282 | * // at its original position | | |
| 283 | * 'comment': { ... }, | | |
| 284 | * // CSS doesn't have a 'color' token, so this token will be appended | | |
| 285 | * 'color': /\b(?:red|green|blue)\b/ | | |
| 286 | * }); | | |
| 287 | */ | 478 | */ |
| 288 | extend: function (id, redef) { | 479 | highlightAllUnder: function (container, async, callback) { |
| 289 | var lang = _.util.clone(_.languages[id]); | 480 | var env = { |
| | 481 | callback: callback, |
| | 482 | container: container, |
| | 483 | selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code' |
| | 484 | }; |
| 290 | | 485 | |
| 291 | for (var key in redef) { | 486 | _.hooks.run('before-highlightall', env); |
| 292 | lang[key] = redef[key]; | | |
| 293 | } | | |
| 294 | | 487 | |
| 295 | return lang; | 488 | env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector)); |
| | 489 | |
| | 490 | _.hooks.run('before-all-elements-highlight', env); |
| | 491 | |
| | 492 | for (var i = 0, element; (element = env.elements[i++]);) { |
| | 493 | _.highlightElement(element, async === true, env.callback); |
| | 494 | } |
| 296 | }, | 495 | }, |
| 297 | | 496 | |
| 298 | /** | 497 | /** |
| 299 | * Inserts tokens _before_ another token in a language definition or any other grammar. | 498 | * Highlights the code inside a single element. |
| 300 | * | | |
| 301 | * ## Usage | | |
| 302 | * | | |
| 303 | * This helper method makes it easy to modify existing languages. For example, the CSS language definition | | |
| 304 | * not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded | | |
| 305 | * in HTML through `<style>` elements. To do this, it needs to modify `Prism.languages.markup` and add the | | |
| 306 | * appropriate tokens. However, `Prism.languages.markup` is a regular JavaScript object literal, so if you do | | |
| 307 | * this: | | |
| 308 | * | | |
| 309 | * ```js | | |
| 310 | * Prism.languages.markup.style = { | | |
| 311 | * // token | | |
| 312 | * }; | | |
| 313 | * ``` | | |
| 314 | * | | |
| 315 | * then the `style` token will be added (and processed) at the end. `insertBefore` allows you to insert tokens | | |
| 316 | * before existing tokens. For the CSS example above, you would use it like this: | | |
| 317 | * | | |
| 318 | * ```js | | |
| 319 | * Prism.languages.insertBefore('markup', 'cdata', { | | |
| 320 | * 'style': { | | |
| 321 | * // token | | |
| 322 | * } | | |
| 323 | * }); | | |
| 324 | * ``` | | |
| 325 | * | | |
| 326 | * ## Special cases | | |
| 327 | * | | |
| 328 | * If the grammars of `inside` and `insert` have tokens with the same name, the tokens in `inside`'s grammar | | |
| 329 | * will be ignored. | | |
| 330 | * | | |
| 331 | * This behavior can be used to insert tokens after `before`: | | |
| 332 | * | | |
| 333 | * ```js | | |
| 334 | * Prism.languages.insertBefore('markup', 'comment', { | | |
| 335 | * 'comment': Prism.languages.markup.comment, | | |
| 336 | * // tokens after 'comment' | | |
| 337 | * }); | | |
| 338 | * ``` | | |
| 339 | * | | |
| 340 | * ## Limitations | | |
| 341 | * | | |
| 342 | * The main problem `insertBefore` has to solve is iteration order. Since ES2015, the iteration order for object | | |
| 343 | * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave | | |
| 344 | * differently when keys are deleted and re-inserted. So `insertBefore` can't be implemented by temporarily | | |
| 345 | * deleting properties which is necessary to insert at arbitrary positions. | | |
| 346 | * | | |
| 347 | * To solve this problem, `insertBefore` doesn't actually insert the given tokens into the target object. | | |
| 348 | * Instead, it will create a new object and replace all references to the target object with the new one. This | | |
| 349 | * can be done without temporarily deleting properties, so the iteration order is well-defined. | | |
| 350 | * | 499 | * |
| 351 | * However, only references that can be reached from `Prism.languages` or `insert` will be replaced. I.e. if | 500 | * The following hooks will be run: |
| 352 | * you hold the target object in a variable, then the value of the variable will not change. | 501 | * 1. `before-sanity-check` |
| | 502 | * 2. `before-highlight` |
| | 503 | * 3. All hooks of {@link Prism.highlight}. These hooks will be run by an asynchronous worker if `async` is `true`. |
| | 504 | * 4. `before-insert` |
| | 505 | * 5. `after-highlight` |
| | 506 | * 6. `complete` |
| 353 | * | 507 | * |
| 354 | * ```js | 508 | * Some the above hooks will be skipped if the element doesn't contain any text or there is no grammar loaded for |
| 355 | * var oldMarkup = Prism.languages.markup; | 509 | * the element's language. |
| 356 | * var newMarkup = Prism.languages.insertBefore('markup', 'comment', { ... }); | | |
| 357 | * | | |
| 358 | * assert(oldMarkup !== Prism.languages.markup); | | |
| 359 | * assert(newMarkup === Prism.languages.markup); | | |
| 360 | * ``` | | |
| 361 | * | 510 | * |
| 362 | * @param {string} inside The property of `root` (e.g. a language id in `Prism.languages`) that contains the | 511 | * @param {Element} element The element containing the code. |
| 363 | * object to be modified. | 512 | * It must have a class of `language-xxxx` to be processed, where `xxxx` is a valid language identifier. |
| 364 | * @param {string} before The key to insert before. | 513 | * @param {boolean} [async=false] Whether the element is to be highlighted asynchronously using Web Workers |
| 365 | * @param {Grammar} insert An object containing the key-value pairs to be inserted. | 514 | * to improve performance and avoid blocking the UI when highlighting very large chunks of code. This option is |
| 366 | * @param {Object<string, any>} [root] The object containing `inside`, i.e. the object that contains the | 515 | * [disabled by default](https://prismjs.com/faq.html#why-is-asynchronous-highlighting-disabled-by-default). |
| 367 | * object to be modified. | | |
| 368 | * | 516 | * |
| 369 | * Defaults to `Prism.languages`. | 517 | * Note: All language definitions required to highlight the code must be included in the main `prism.js` file for |
| 370 | * @returns {Grammar} The new grammar object. | 518 | * asynchronous highlighting to work. You can build your own bundle on the |
| | 519 | * [Download page](https://prismjs.com/download.html). |
| | 520 | * @param {HighlightCallback} [callback] An optional callback to be invoked after the highlighting is done. |
| | 521 | * Mostly useful when `async` is `true`, since in that case, the highlighting is done asynchronously. |
| | 522 | * @memberof Prism |
| 371 | * @public | 523 | * @public |
| 372 | */ | 524 | */ |
| 373 | insertBefore: function (inside, before, insert, root) { | 525 | highlightElement: function (element, async, callback) { |
| 374 | root = root || /** @type {any} */ (_.languages); | 526 | // Find language |
| 375 | var grammar = root[inside]; | 527 | var language = _.util.getLanguage(element); |
| 376 | /** @type {Grammar} */ | 528 | var grammar = _.languages[language]; |
| 377 | var ret = {}; | 529 | |
| 378 | | 530 | // Set language on the element, if not present |
| 379 | for (var token in grammar) { | 531 | element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; |
| 380 | if (grammar.hasOwnProperty(token)) { | 532 | |
| 381 | | 533 | // Set language on the parent, for styling |
| 382 | if (token == before) { | 534 | var parent = element.parentElement; |
| 383 | for (var newToken in insert) { | 535 | if (parent && parent.nodeName.toLowerCase() === 'pre') { |
| 384 | if (insert.hasOwnProperty(newToken)) { | 536 | parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; |
| 385 | ret[newToken] = insert[newToken]; | | |
| 386 | } | | |
| 387 | } | | |
| 388 | } | | |
| 389 | | | |
| 390 | // Do not insert token which also occur in insert. See #1525 | | |
| 391 | if (!insert.hasOwnProperty(token)) { | | |
| 392 | ret[token] = grammar[token]; | | |
| 393 | } | | |
| 394 | } | | |
| 395 | } | 537 | } |
| 396 | | 538 | |
| 397 | var old = root[inside]; | 539 | var code = element.textContent; |
| 398 | root[inside] = ret; | | |
| 399 | | 540 | |
| 400 | // Update references in other language definitions | 541 | var env = { |
| 401 | _.languages.DFS(_.languages, function(key, value) { | 542 | element: element, |
| 402 | if (value === old && key != inside) { | 543 | language: language, |
| 403 | this[key] = ret; | 544 | grammar: grammar, |
| 404 | } | 545 | code: code |
| 405 | }); | 546 | }; |
| 406 | | | |
| 407 | return ret; | | |
| 408 | }, | | |
| 409 | | | |
| 410 | // Traverse a language definition with Depth First Search | | |
| 411 | DFS: function DFS(o, callback, type, visited) { | | |
| 412 | visited = visited || {}; | | |
| 413 | | 547 | |
| 414 | var objId = _.util.objId; | 548 | function insertHighlightedCode(highlightedCode) { |
| | 549 | env.highlightedCode = highlightedCode; |
| 415 | | 550 | |
| 416 | for (var i in o) { | 551 | _.hooks.run('before-insert', env); |
| 417 | if (o.hasOwnProperty(i)) { | | |
| 418 | callback.call(o, i, o[i], type || i); | | |
| 419 | | 552 | |
| 420 | var property = o[i], | 553 | env.element.innerHTML = env.highlightedCode; |
| 421 | propertyType = _.util.type(property); | | |
| 422 | | 554 | |
| 423 | if (propertyType === 'Object' && !visited[objId(property)]) { | 555 | _.hooks.run('after-highlight', env); |
| 424 | visited[objId(property)] = true; | 556 | _.hooks.run('complete', env); |
| 425 | DFS(property, callback, null, visited); | 557 | callback && callback.call(env.element); |
| 426 | } | | |
| 427 | else if (propertyType === 'Array' && !visited[objId(property)]) { | | |
| 428 | visited[objId(property)] = true; | | |
| 429 | DFS(property, callback, i, visited); | | |
| 430 | } | | |
| 431 | } | | |
| 432 | } | 558 | } |
| 433 | } | | |
| 434 | }, | | |
| 435 | | 559 | |
| 436 | plugins: {}, | 560 | _.hooks.run('before-sanity-check', env); |
| 437 | | 561 | |
| 438 | /** | 562 | // plugins may change/add the parent/element |
| 439 | * This is the most high-level function in Prism’s API. | 563 | parent = env.element.parentElement; |
| 440 | * It fetches all the elements that have a `.language-xxxx` class and then calls {@link Prism.highlightElement} on | 564 | if (parent && parent.nodeName.toLowerCase() === 'pre' && !parent.hasAttribute('tabindex')) { |
| 441 | * each one of them. | 565 | parent.setAttribute('tabindex', '0'); |
| 442 | * | 566 | } |
| 443 | * This is equivalent to `Prism.highlightAllUnder(document, async, callback)`. | | |
| 444 | * | | |
| 445 | * @param {boolean} [async=false] Same as in {@link Prism.highlightAllUnder}. | | |
| 446 | * @param {HighlightCallback} [callback] Same as in {@link Prism.highlightAllUnder}. | | |
| 447 | * @memberof Prism | | |
| 448 | * @public | | |
| 449 | */ | | |
| 450 | highlightAll: function(async, callback) { | | |
| 451 | _.highlightAllUnder(document, async, callback); | | |
| 452 | }, | | |
| 453 | | | |
| 454 | /** | | |
| 455 | * Fetches all the descendants of `container` that have a `.language-xxxx` class and then calls | | |
| 456 | * {@link Prism.highlightElement} on each one of them. | | |
| 457 | * | | |
| 458 | * The following hooks will be run: | | |
| 459 | * 1. `before-highlightall` | | |
| 460 | * 2. `before-all-elements-highlight` | | |
| 461 | * 3. All hooks of {@link Prism.highlightElement} for each element. | | |
| 462 | * | | |
| 463 | * @param {ParentNode} container The root element, whose descendants that have a `.language-xxxx` class will be highlighted. | | |
| 464 | * @param {boolean} [async=false] Whether each element is to be highlighted asynchronously using Web Workers. | | |
| 465 | * @param {HighlightCallback} [callback] An optional callback to be invoked on each element after its highlighting is done. | | |
| 466 | * @memberof Prism | | |
| 467 | * @public | | |
| 468 | */ | | |
| 469 | highlightAllUnder: function(container, async, callback) { | | |
| 470 | var env = { | | |
| 471 | callback: callback, | | |
| 472 | container: container, | | |
| 473 | selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code' | | |
| 474 | }; | | |
| 475 | | | |
| 476 | _.hooks.run('before-highlightall', env); | | |
| 477 | | 567 | |
| 478 | env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector)); | 568 | if (!env.code) { |
| | 569 | _.hooks.run('complete', env); |
| | 570 | callback && callback.call(env.element); |
| | 571 | return; |
| | 572 | } |
| 479 | | 573 | |
| 480 | _.hooks.run('before-all-elements-highlight', env); | 574 | _.hooks.run('before-highlight', env); |
| 481 | | 575 | |
| 482 | for (var i = 0, element; element = env.elements[i++];) { | 576 | if (!env.grammar) { |
| 483 | _.highlightElement(element, async === true, env.callback); | 577 | insertHighlightedCode(_.util.encode(env.code)); |
| 484 | } | 578 | return; |
| 485 | }, | 579 | } |
| 486 | | 580 | |
| 487 | /** | 581 | if (async && _self.Worker) { |
| 488 | * Highlights the code inside a single element. | 582 | var worker = new Worker(_.filename); |
| 489 | * | | |
| 490 | * The following hooks will be run: | | |
| 491 | * 1. `before-sanity-check` | | |
| 492 | * 2. `before-highlight` | | |
| 493 | * 3. All hooks of {@link Prism.highlight}. These hooks will be run by an asynchronous worker if `async` is `true`. | | |
| 494 | * 4. `before-insert` | | |
| 495 | * 5. `after-highlight` | | |
| 496 | * 6. `complete` | | |
| 497 | * | | |
| 498 | * Some the above hooks will be skipped if the element doesn't contain any text or there is no grammar loaded for | | |
| 499 | * the element's language. | | |
| 500 | * | | |
| 501 | * @param {Element} element The element containing the code. | | |
| 502 | * It must have a class of `language-xxxx` to be processed, where `xxxx` is a valid language identifier. | | |
| 503 | * @param {boolean} [async=false] Whether the element is to be highlighted asynchronously using Web Workers | | |
| 504 | * to improve performance and avoid blocking the UI when highlighting very large chunks of code. This option is | | |
| 505 | * [disabled by default](https://prismjs.com/faq.html#why-is-asynchronous-highlighting-disabled-by-default). | | |
| 506 | * | | |
| 507 | * Note: All language definitions required to highlight the code must be included in the main `prism.js` file for | | |
| 508 | * asynchronous highlighting to work. You can build your own bundle on the | | |
| 509 | * [Download page](https://prismjs.com/download.html). | | |
| 510 | * @param {HighlightCallback} [callback] An optional callback to be invoked after the highlighting is done. | | |
| 511 | * Mostly useful when `async` is `true`, since in that case, the highlighting is done asynchronously. | | |
| 512 | * @memberof Prism | | |
| 513 | * @public | | |
| 514 | */ | | |
| 515 | highlightElement: function(element, async, callback) { | | |
| 516 | // Find language | | |
| 517 | var language = _.util.getLanguage(element); | | |
| 518 | var grammar = _.languages[language]; | | |
| 519 | | | |
| 520 | // Set language on the element, if not present | | |
| 521 | element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; | | |
| 522 | | | |
| 523 | // Set language on the parent, for styling | | |
| 524 | var parent = element.parentElement; | | |
| 525 | if (parent && parent.nodeName.toLowerCase() === 'pre') { | | |
| 526 | parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; | | |
| 527 | } | | |
| 528 | | 583 | |
| 529 | var code = element.textContent; | 584 | worker.onmessage = function (evt) { |
| | 585 | insertHighlightedCode(evt.data); |
| | 586 | }; |
| 530 | | 587 | |
| 531 | var env = { | 588 | worker.postMessage(JSON.stringify({ |
| 532 | element: element, | 589 | language: env.language, |
| 533 | language: language, | 590 | code: env.code, |
| 534 | grammar: grammar, | 591 | immediateClose: true |
| 535 | code: code | 592 | })); |
| 536 | }; | 593 | } else { |
| | 594 | insertHighlightedCode(_.highlight(env.code, env.grammar, env.language)); |
| | 595 | } |
| | 596 | }, |
| 537 | | 597 | |
| 538 | function insertHighlightedCode(highlightedCode) { | 598 | /** |
| 539 | env.highlightedCode = highlightedCode; | 599 | * Low-level function, only use if you know what you’re doing. It accepts a string of text as input |
| | 600 | * and the language definitions to use, and returns a string with the HTML produced. |
| | 601 | * |
| | 602 | * The following hooks will be run: |
| | 603 | * 1. `before-tokenize` |
| | 604 | * 2. `after-tokenize` |
| | 605 | * 3. `wrap`: On each {@link Token}. |
| | 606 | * |
| | 607 | * @param {string} text A string with the code to be highlighted. |
| | 608 | * @param {Grammar} grammar An object containing the tokens to use. |
| | 609 | * |
| | 610 | * Usually a language definition like `Prism.languages.markup`. |
| | 611 | * @param {string} language The name of the language definition passed to `grammar`. |
| | 612 | * @returns {string} The highlighted HTML. |
| | 613 | * @memberof Prism |
| | 614 | * @public |
| | 615 | * @example |
| | 616 | * Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript'); |
| | 617 | */ |
| | 618 | highlight: function (text, grammar, language) { |
| | 619 | var env = { |
| | 620 | code: text, |
| | 621 | grammar: grammar, |
| | 622 | language: language |
| | 623 | }; |
| | 624 | _.hooks.run('before-tokenize', env); |
| | 625 | env.tokens = _.tokenize(env.code, env.grammar); |
| | 626 | _.hooks.run('after-tokenize', env); |
| | 627 | return Token.stringify(_.util.encode(env.tokens), env.language); |
| | 628 | }, |
| 540 | | 629 | |
| 541 | _.hooks.run('before-insert', env); | 630 | /** |
| | 631 | * This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input |
| | 632 | * and the language definitions to use, and returns an array with the tokenized code. |
| | 633 | * |
| | 634 | * When the language definition includes nested tokens, the function is called recursively on each of these tokens. |
| | 635 | * |
| | 636 | * This method could be useful in other contexts as well, as a very crude parser. |
| | 637 | * |
| | 638 | * @param {string} text A string with the code to be highlighted. |
| | 639 | * @param {Grammar} grammar An object containing the tokens to use. |
| | 640 | * |
| | 641 | * Usually a language definition like `Prism.languages.markup`. |
| | 642 | * @returns {TokenStream} An array of strings and tokens, a token stream. |
| | 643 | * @memberof Prism |
| | 644 | * @public |
| | 645 | * @example |
| | 646 | * let code = `var foo = 0;`; |
| | 647 | * let tokens = Prism.tokenize(code, Prism.languages.javascript); |
| | 648 | * tokens.forEach(token => { |
| | 649 | * if (token instanceof Prism.Token && token.type === 'number') { |
| | 650 | * console.log(`Found numeric literal: ${token.content}`); |
| | 651 | * } |
| | 652 | * }); |
| | 653 | */ |
| | 654 | tokenize: function (text, grammar) { |
| | 655 | var rest = grammar.rest; |
| | 656 | if (rest) { |
| | 657 | for (var token in rest) { |
| | 658 | grammar[token] = rest[token]; |
| | 659 | } |
| 542 | | 660 | |
| 543 | env.element.innerHTML = env.highlightedCode; | 661 | delete grammar.rest; |
| | 662 | } |
| 544 | | 663 | |
| 545 | _.hooks.run('after-highlight', env); | 664 | var tokenList = new LinkedList(); |
| 546 | _.hooks.run('complete', env); | 665 | addAfter(tokenList, tokenList.head, text); |
| 547 | callback && callback.call(env.element); | | |
| 548 | } | | |
| 549 | | 666 | |
| 550 | _.hooks.run('before-sanity-check', env); | 667 | matchGrammar(text, tokenList, grammar, tokenList.head, 0); |
| 551 | | 668 | |
| 552 | if (!env.code) { | 669 | return toArray(tokenList); |
| 553 | _.hooks.run('complete', env); | 670 | }, |
| 554 | callback && callback.call(env.element); | | |
| 555 | return; | | |
| 556 | } | | |
| 557 | | 671 | |
| 558 | _.hooks.run('before-highlight', env); | 672 | /** |
| | 673 | * @namespace |
| | 674 | * @memberof Prism |
| | 675 | * @public |
| | 676 | */ |
| | 677 | hooks: { |
| | 678 | all: {}, |
| 559 | | 679 | |
| 560 | if (!env.grammar) { | 680 | /** |
| 561 | insertHighlightedCode(_.util.encode(env.code)); | 681 | * Adds the given callback to the list of callbacks for the given hook. |
| 562 | return; | 682 | * |
| 563 | } | 683 | * The callback will be invoked when the hook it is registered for is run. |
| | 684 | * Hooks are usually directly run by a highlight function but you can also run hooks yourself. |
| | 685 | * |
| | 686 | * One callback function can be registered to multiple hooks and the same hook multiple times. |
| | 687 | * |
| | 688 | * @param {string} name The name of the hook. |
| | 689 | * @param {HookCallback} callback The callback function which is given environment variables. |
| | 690 | * @public |
| | 691 | */ |
| | 692 | add: function (name, callback) { |
| | 693 | var hooks = _.hooks.all; |
| 564 | | 694 | |
| 565 | if (async && _self.Worker) { | 695 | hooks[name] = hooks[name] || []; |
| 566 | var worker = new Worker(_.filename); | | |
| 567 | | 696 | |
| 568 | worker.onmessage = function(evt) { | 697 | hooks[name].push(callback); |
| 569 | insertHighlightedCode(evt.data); | 698 | }, |
| 570 | }; | | |
| 571 | | 699 | |
| 572 | worker.postMessage(JSON.stringify({ | 700 | /** |
| 573 | language: env.language, | 701 | * Runs a hook invoking all registered callbacks with the given environment variables. |
| 574 | code: env.code, | 702 | * |
| 575 | immediateClose: true | 703 | * Callbacks will be invoked synchronously and in the order in which they were registered. |
| 576 | })); | 704 | * |
| 577 | } | 705 | * @param {string} name The name of the hook. |
| 578 | else { | 706 | * @param {Object<string, any>} env The environment variables of the hook passed to all callbacks registered. |
| 579 | insertHighlightedCode(_.highlight(env.code, env.grammar, env.language)); | 707 | * @public |
| 580 | } | 708 | */ |
| 581 | }, | 709 | run: function (name, env) { |
| | 710 | var callbacks = _.hooks.all[name]; |
| 582 | | 711 | |
| 583 | /** | 712 | if (!callbacks || !callbacks.length) { |
| 584 | * Low-level function, only use if you know what you’re doing. It accepts a string of text as input | 713 | return; |
| 585 | * and the language definitions to use, and returns a string with the HTML produced. | 714 | } |
| 586 | * | | |
| 587 | * The following hooks will be run: | | |
| 588 | * 1. `before-tokenize` | | |
| 589 | * 2. `after-tokenize` | | |
| 590 | * 3. `wrap`: On each {@link Token}. | | |
| 591 | * | | |
| 592 | * @param {string} text A string with the code to be highlighted. | | |
| 593 | * @param {Grammar} grammar An object containing the tokens to use. | | |
| 594 | * | | |
| 595 | * Usually a language definition like `Prism.languages.markup`. | | |
| 596 | * @param {string} language The name of the language definition passed to `grammar`. | | |
| 597 | * @returns {string} The highlighted HTML. | | |
| 598 | * @memberof Prism | | |
| 599 | * @public | | |
| 600 | * @example | | |
| 601 | * Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript'); | | |
| 602 | */ | | |
| 603 | highlight: function (text, grammar, language) { | | |
| 604 | var env = { | | |
| 605 | code: text, | | |
| 606 | grammar: grammar, | | |
| 607 | language: language | | |
| 608 | }; | | |
| 609 | _.hooks.run('before-tokenize', env); | | |
| 610 | env.tokens = _.tokenize(env.code, env.grammar); | | |
| 611 | _.hooks.run('after-tokenize', env); | | |
| 612 | return Token.stringify(_.util.encode(env.tokens), env.language); | | |
| 613 | }, | | |
| 614 | | 715 | |
| 615 | /** | 716 | for (var i = 0, callback; (callback = callbacks[i++]);) { |
| 616 | * This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input | 717 | callback(env); |
| 617 | * and the language definitions to use, and returns an array with the tokenized code. | 718 | } |
| 618 | * | | |
| 619 | * When the language definition includes nested tokens, the function is called recursively on each of these tokens. | | |
| 620 | * | | |
| 621 | * This method could be useful in other contexts as well, as a very crude parser. | | |
| 622 | * | | |
| 623 | * @param {string} text A string with the code to be highlighted. | | |
| 624 | * @param {Grammar} grammar An object containing the tokens to use. | | |
| 625 | * | | |
| 626 | * Usually a language definition like `Prism.languages.markup`. | | |
| 627 | * @returns {TokenStream} An array of strings and tokens, a token stream. | | |
| 628 | * @memberof Prism | | |
| 629 | * @public | | |
| 630 | * @example | | |
| 631 | * let code = `var foo = 0;`; | | |
| 632 | * let tokens = Prism.tokenize(code, Prism.languages.javascript); | | |
| 633 | * tokens.forEach(token => { | | |
| 634 | * if (token instanceof Prism.Token && token.type === 'number') { | | |
| 635 | * console.log(`Found numeric literal: ${token.content}`); | | |
| 636 | * } | | |
| 637 | * }); | | |
| 638 | */ | | |
| 639 | tokenize: function(text, grammar) { | | |
| 640 | var rest = grammar.rest; | | |
| 641 | if (rest) { | | |
| 642 | for (var token in rest) { | | |
| 643 | grammar[token] = rest[token]; | | |
| 644 | } | 719 | } |
| | 720 | }, |
| 645 | | 721 | |
| 646 | delete grammar.rest; | 722 | Token: Token |
| 647 | } | 723 | }; |
| 648 | | 724 | _self.Prism = _; |
| 649 | var tokenList = new LinkedList(); | | |
| 650 | addAfter(tokenList, tokenList.head, text); | | |
| 651 | | 725 | |
| 652 | matchGrammar(text, tokenList, grammar, tokenList.head, 0); | | |
| 653 | | 726 | |
| 654 | return toArray(tokenList); | 727 | // Typescript note: |
| 655 | }, | 728 | // The following can be used to import the Token type in JSDoc: |
| | 729 | // |
| | 730 | // @typedef {InstanceType<import("./prism-core")["Token"]>} Token |
| 656 | | 731 | |
| 657 | /** | 732 | /** |
| 658 | * @namespace | 733 | * Creates a new token. |
| 659 | * @memberof Prism | 734 | * |
| | 735 | * @param {string} type See {@link Token#type type} |
| | 736 | * @param {string | TokenStream} content See {@link Token#content content} |
| | 737 | * @param {string|string[]} [alias] The alias(es) of the token. |
| | 738 | * @param {string} [matchedStr=""] A copy of the full string this token was created from. |
| | 739 | * @class |
| | 740 | * @global |
| 660 | * @public | 741 | * @public |
| 661 | */ | 742 | */ |
| 662 | hooks: { | 743 | function Token(type, content, alias, matchedStr) { |
| 663 | all: {}, | | |
| 664 | | | |
| 665 | /** | 744 | /** |
| 666 | * Adds the given callback to the list of callbacks for the given hook. | 745 | * The type of the token. |
| 667 | * | 746 | * |
| 668 | * The callback will be invoked when the hook it is registered for is run. | 747 | * This is usually the key of a pattern in a {@link Grammar}. |
| 669 | * Hooks are usually directly run by a highlight function but you can also run hooks yourself. | | |
| 670 | * | 748 | * |
| 671 | * One callback function can be registered to multiple hooks and the same hook multiple times. | 749 | * @type {string} |
| 672 | * | 750 | * @see GrammarToken |
| 673 | * @param {string} name The name of the hook. | | |
| 674 | * @param {HookCallback} callback The callback function which is given environment variables. | | |
| 675 | * @public | 751 | * @public |
| 676 | */ | 752 | */ |
| 677 | add: function (name, callback) { | 753 | this.type = type; |
| 678 | var hooks = _.hooks.all; | | |
| 679 | | | |
| 680 | hooks[name] = hooks[name] || []; | | |
| 681 | | | |
| 682 | hooks[name].push(callback); | | |
| 683 | }, | | |
| 684 | | | |
| 685 | /** | 754 | /** |
| 686 | * Runs a hook invoking all registered callbacks with the given environment variables. | 755 | * The strings or tokens contained by this token. |
| 687 | * | 756 | * |
| 688 | * Callbacks will be invoked synchronously and in the order in which they were registered. | 757 | * This will be a token stream if the pattern matched also defined an `inside` grammar. |
| 689 | * | 758 | * |
| 690 | * @param {string} name The name of the hook. | 759 | * @type {string | TokenStream} |
| 691 | * @param {Object<string, any>} env The environment variables of the hook passed to all callbacks registered. | | |
| 692 | * @public | 760 | * @public |
| 693 | */ | 761 | */ |
| 694 | run: function (name, env) { | 762 | this.content = content; |
| 695 | var callbacks = _.hooks.all[name]; | 763 | /** |
| 696 | | 764 | * The alias(es) of the token. |
| 697 | if (!callbacks || !callbacks.length) { | 765 | * |
| 698 | return; | 766 | * @type {string|string[]} |
| 699 | } | 767 | * @see GrammarToken |
| 700 | | 768 | * @public |
| 701 | for (var i=0, callback; callback = callbacks[i++];) { | 769 | */ |
| 702 | callback(env); | 770 | this.alias = alias; |
| 703 | } | 771 | // Copy of the full string this token was created from |
| 704 | } | 772 | this.length = (matchedStr || '').length | 0; |
| 705 | }, | 773 | } |
| 706 | | | |
| 707 | Token: Token | | |
| 708 | }; | | |
| 709 | _self.Prism = _; | | |
| 710 | | | |
| 711 | | | |
| 712 | // Typescript note: | | |
| 713 | // The following can be used to import the Token type in JSDoc: | | |
| 714 | // | | |
| 715 | // @typedef {InstanceType<import("./prism-core")["Token"]>} Token | | |
| 716 | | 774 | |
| 717 | /** | | |
| 718 | * Creates a new token. | | |
| 719 | * | | |
| 720 | * @param {string} type See {@link Token#type type} | | |
| 721 | * @param {string | TokenStream} content See {@link Token#content content} | | |
| 722 | * @param {string|string[]} [alias] The alias(es) of the token. | | |
| 723 | * @param {string} [matchedStr=""] A copy of the full string this token was created from. | | |
| 724 | * @class | | |
| 725 | * @global | | |
| 726 | * @public | | |
| 727 | */ | | |
| 728 | function Token(type, content, alias, matchedStr) { | | |
| 729 | /** | 775 | /** |
| 730 | * The type of the token. | 776 | * A token stream is an array of strings and {@link Token Token} objects. |
| 731 | * | 777 | * |
| 732 | * This is usually the key of a pattern in a {@link Grammar}. | 778 | * Token streams have to fulfill a few properties that are assumed by most functions (mostly internal ones) that process |
| | 779 | * them. |
| 733 | * | 780 | * |
| 734 | * @type {string} | 781 | * 1. No adjacent strings. |
| 735 | * @see GrammarToken | 782 | * 2. No empty strings. |
| 736 | * @public | | |
| 737 | */ | | |
| 738 | this.type = type; | | |
| 739 | /** | | |
| 740 | * The strings or tokens contained by this token. | | |
| 741 | * | 783 | * |
| 742 | * This will be a token stream if the pattern matched also defined an `inside` grammar. | 784 | * The only exception here is the token stream that only contains the empty string and nothing else. |
| 743 | * | 785 | * |
| 744 | * @type {string | TokenStream} | 786 | * @typedef {Array<string | Token>} TokenStream |
| | 787 | * @global |
| 745 | * @public | 788 | * @public |
| 746 | */ | 789 | */ |
| 747 | this.content = content; | 790 | |
| 748 | /** | 791 | /** |
| 749 | * The alias(es) of the token. | 792 | * Converts the given token or token stream to an HTML representation. |
| 750 | * | 793 | * |
| 751 | * @type {string|string[]} | 794 | * The following hooks will be run: |
| 752 | * @see GrammarToken | 795 | * 1. `wrap`: On each {@link Token}. |
| 753 | * @public | 796 | * |
| | 797 | * @param {string | Token | TokenStream} o The token or token stream to be converted. |
| | 798 | * @param {string} language The name of current language. |
| | 799 | * @returns {string} The HTML representation of the token or token stream. |
| | 800 | * @memberof Token |
| | 801 | * @static |
| 754 | */ | 802 | */ |
| 755 | this.alias = alias; | 803 | Token.stringify = function stringify(o, language) { |
| 756 | // Copy of the full string this token was created from | 804 | if (typeof o == 'string') { |
| 757 | this.length = (matchedStr || '').length | 0; | 805 | return o; |
| 758 | } | 806 | } |
| 759 | | 807 | if (Array.isArray(o)) { |
| 760 | /** | 808 | var s = ''; |
| 761 | * A token stream is an array of strings and {@link Token Token} objects. | 809 | o.forEach(function (e) { |
| 762 | * | 810 | s += stringify(e, language); |
| 763 | * Token streams have to fulfill a few properties that are assumed by most functions (mostly internal ones) that process | 811 | }); |
| 764 | * them. | 812 | return s; |
| 765 | * | | |
| 766 | * 1. No adjacent strings. | | |
| 767 | * 2. No empty strings. | | |
| 768 | * | | |
| 769 | * The only exception here is the token stream that only contains the empty string and nothing else. | | |
| 770 | * | | |
| 771 | * @typedef {Array<string | Token>} TokenStream | | |
| 772 | * @global | | |
| 773 | * @public | | |
| 774 | */ | | |
| 775 | | | |
| 776 | /** | | |
| 777 | * Converts the given token or token stream to an HTML representation. | | |
| 778 | * | | |
| 779 | * The following hooks will be run: | | |
| 780 | * 1. `wrap`: On each {@link Token}. | | |
| 781 | * | | |
| 782 | * @param {string | Token | TokenStream} o The token or token stream to be converted. | | |
| 783 | * @param {string} language The name of current language. | | |
| 784 | * @returns {string} The HTML representation of the token or token stream. | | |
| 785 | * @memberof Token | | |
| 786 | * @static | | |
| 787 | */ | | |
| 788 | Token.stringify = function stringify(o, language) { | | |
| 789 | if (typeof o == 'string') { | | |
| 790 | return o; | | |
| 791 | } | | |
| 792 | if (Array.isArray(o)) { | | |
| 793 | var s = ''; | | |
| 794 | o.forEach(function (e) { | | |
| 795 | s += stringify(e, language); | | |
| 796 | }); | | |
| 797 | return s; | | |
| 798 | } | | |
| 799 | | | |
| 800 | var env = { | | |
| 801 | type: o.type, | | |
| 802 | content: stringify(o.content, language), | | |
| 803 | tag: 'span', | | |
| 804 | classes: ['token', o.type], | | |
| 805 | attributes: {}, | | |
| 806 | language: language | | |
| 807 | }; | | |
| 808 | | | |
| 809 | var aliases = o.alias; | | |
| 810 | if (aliases) { | | |
| 811 | if (Array.isArray(aliases)) { | | |
| 812 | Array.prototype.push.apply(env.classes, aliases); | | |
| 813 | } else { | | |
| 814 | env.classes.push(aliases); | | |
| 815 | } | 813 | } |
| 816 | } | | |
| 817 | | 814 | |
| 818 | _.hooks.run('wrap', env); | 815 | var env = { |
| | 816 | type: o.type, |
| | 817 | content: stringify(o.content, language), |
| | 818 | tag: 'span', |
| | 819 | classes: ['token', o.type], |
| | 820 | attributes: {}, |
| | 821 | language: language |
| | 822 | }; |
| 819 | | 823 | |
| 820 | var attributes = ''; | 824 | var aliases = o.alias; |
| 821 | for (var name in env.attributes) { | 825 | if (aliases) { |
| 822 | attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '"') + '"'; | 826 | if (Array.isArray(aliases)) { |
| 823 | } | 827 | Array.prototype.push.apply(env.classes, aliases); |
| | 828 | } else { |
| | 829 | env.classes.push(aliases); |
| | 830 | } |
| | 831 | } |
| 824 | | 832 | |
| 825 | return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>'; | 833 | _.hooks.run('wrap', env); |
| 826 | }; | | |
| 827 | | 834 | |
| 828 | /** | 835 | var attributes = ''; |
| 829 | * @param {RegExp} pattern | 836 | for (var name in env.attributes) { |
| 830 | * @param {number} pos | 837 | attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '"') + '"'; |
| 831 | * @param {string} text | | |
| 832 | * @param {boolean} lookbehind | | |
| 833 | * @returns {RegExpExecArray | null} | | |
| 834 | */ | | |
| 835 | function matchPattern(pattern, pos, text, lookbehind) { | | |
| 836 | pattern.lastIndex = pos; | | |
| 837 | var match = pattern.exec(text); | | |
| 838 | if (match && lookbehind && match[1]) { | | |
| 839 | // change the match to remove the text matched by the Prism lookbehind group | | |
| 840 | var lookbehindLength = match[1].length; | | |
| 841 | match.index += lookbehindLength; | | |
| 842 | match[0] = match[0].slice(lookbehindLength); | | |
| 843 | } | | |
| 844 | return match; | | |
| 845 | } | | |
| 846 | | | |
| 847 | /** | | |
| 848 | * @param {string} text | | |
| 849 | * @param {LinkedList<string | Token>} tokenList | | |
| 850 | * @param {any} grammar | | |
| 851 | * @param {LinkedListNode<string | Token>} startNode | | |
| 852 | * @param {number} startPos | | |
| 853 | * @param {RematchOptions} [rematch] | | |
| 854 | * @returns {void} | | |
| 855 | * @private | | |
| 856 | * | | |
| 857 | * @typedef RematchOptions | | |
| 858 | * @property {string} cause | | |
| 859 | * @property {number} reach | | |
| 860 | */ | | |
| 861 | function matchGrammar(text, tokenList, grammar, startNode, startPos, rematch) { | | |
| 862 | for (var token in grammar) { | | |
| 863 | if (!grammar.hasOwnProperty(token) || !grammar[token]) { | | |
| 864 | continue; | | |
| 865 | } | 838 | } |
| 866 | | 839 | |
| 867 | var patterns = grammar[token]; | 840 | return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>'; |
| 868 | patterns = Array.isArray(patterns) ? patterns : [patterns]; | 841 | }; |
| 869 | | | |
| 870 | for (var j = 0; j < patterns.length; ++j) { | | |
| 871 | if (rematch && rematch.cause == token + ',' + j) { | | |
| 872 | return; | | |
| 873 | } | | |
| 874 | | 842 | |
| 875 | var patternObj = patterns[j], | 843 | /** |
| 876 | inside = patternObj.inside, | 844 | * @param {RegExp} pattern |
| 877 | lookbehind = !!patternObj.lookbehind, | 845 | * @param {number} pos |
| 878 | greedy = !!patternObj.greedy, | 846 | * @param {string} text |
| 879 | alias = patternObj.alias; | 847 | * @param {boolean} lookbehind |
| | 848 | * @returns {RegExpExecArray | null} |
| | 849 | */ |
| | 850 | function matchPattern(pattern, pos, text, lookbehind) { |
| | 851 | pattern.lastIndex = pos; |
| | 852 | var match = pattern.exec(text); |
| | 853 | if (match && lookbehind && match[1]) { |
| | 854 | // change the match to remove the text matched by the Prism lookbehind group |
| | 855 | var lookbehindLength = match[1].length; |
| | 856 | match.index += lookbehindLength; |
| | 857 | match[0] = match[0].slice(lookbehindLength); |
| | 858 | } |
| | 859 | return match; |
| | 860 | } |
| 880 | | 861 | |
| 881 | if (greedy && !patternObj.pattern.global) { | 862 | /** |
| 882 | // Without the global flag, lastIndex won't work | 863 | * @param {string} text |
| 883 | var flags = patternObj.pattern.toString().match(/[imsuy]*$/)[0]; | 864 | * @param {LinkedList<string | Token>} tokenList |
| 884 | patternObj.pattern = RegExp(patternObj.pattern.source, flags + 'g'); | 865 | * @param {any} grammar |
| | 866 | * @param {LinkedListNode<string | Token>} startNode |
| | 867 | * @param {number} startPos |
| | 868 | * @param {RematchOptions} [rematch] |
| | 869 | * @returns {void} |
| | 870 | * @private |
| | 871 | * |
| | 872 | * @typedef RematchOptions |
| | 873 | * @property {string} cause |
| | 874 | * @property {number} reach |
| | 875 | */ |
| | 876 | function matchGrammar(text, tokenList, grammar, startNode, startPos, rematch) { |
| | 877 | for (var token in grammar) { |
| | 878 | if (!grammar.hasOwnProperty(token) || !grammar[token]) { |
| | 879 | continue; |
| 885 | } | 880 | } |
| 886 | | 881 | |
| 887 | /** @type {RegExp} */ | 882 | var patterns = grammar[token]; |
| 888 | var pattern = patternObj.pattern || patternObj; | 883 | patterns = Array.isArray(patterns) ? patterns : [patterns]; |
| 889 | | | |
| 890 | for ( // iterate the token list and keep track of the current token/string position | | |
| 891 | var currentNode = startNode.next, pos = startPos; | | |
| 892 | currentNode !== tokenList.tail; | | |
| 893 | pos += currentNode.value.length, currentNode = currentNode.next | | |
| 894 | ) { | | |
| 895 | | 884 | |
| 896 | if (rematch && pos >= rematch.reach) { | 885 | for (var j = 0; j < patterns.length; ++j) { |
| 897 | break; | 886 | if (rematch && rematch.cause == token + ',' + j) { |
| | 887 | return; |
| 898 | } | 888 | } |
| 899 | | 889 | |
| 900 | var str = currentNode.value; | 890 | var patternObj = patterns[j]; |
| | 891 | var inside = patternObj.inside; |
| | 892 | var lookbehind = !!patternObj.lookbehind; |
| | 893 | var greedy = !!patternObj.greedy; |
| | 894 | var alias = patternObj.alias; |
| 901 | | 895 | |
| 902 | if (tokenList.length > text.length) { | 896 | if (greedy && !patternObj.pattern.global) { |
| 903 | // Something went terribly wrong, ABORT, ABORT! | 897 | // Without the global flag, lastIndex won't work |
| 904 | return; | 898 | var flags = patternObj.pattern.toString().match(/[imsuy]*$/)[0]; |
| | 899 | patternObj.pattern = RegExp(patternObj.pattern.source, flags + 'g'); |
| 905 | } | 900 | } |
| 906 | | 901 | |
| 907 | if (str instanceof Token) { | 902 | /** @type {RegExp} */ |
| 908 | continue; | 903 | var pattern = patternObj.pattern || patternObj; |
| 909 | } | | |
| 910 | | 904 | |
| 911 | var removeCount = 1; // this is the to parameter of removeBetween | 905 | for ( // iterate the token list and keep track of the current token/string position |
| 912 | var match; | 906 | var currentNode = startNode.next, pos = startPos; |
| | 907 | currentNode !== tokenList.tail; |
| | 908 | pos += currentNode.value.length, currentNode = currentNode.next |
| | 909 | ) { |
| 913 | | 910 | |
| 914 | if (greedy) { | 911 | if (rematch && pos >= rematch.reach) { |
| 915 | match = matchPattern(pattern, pos, text, lookbehind); | | |
| 916 | if (!match) { | | |
| 917 | break; | 912 | break; |
| 918 | } | 913 | } |
| 919 | | 914 | |
| 920 | var from = match.index; | 915 | var str = currentNode.value; |
| 921 | var to = match.index + match[0].length; | | |
| 922 | var p = pos; | | |
| 923 | | 916 | |
| 924 | // find the node that contains the match | 917 | if (tokenList.length > text.length) { |
| 925 | p += currentNode.value.length; | 918 | // Something went terribly wrong, ABORT, ABORT! |
| 926 | while (from >= p) { | 919 | return; |
| 927 | currentNode = currentNode.next; | | |
| 928 | p += currentNode.value.length; | | |
| 929 | } | 920 | } |
| 930 | // adjust pos (and p) | | |
| 931 | p -= currentNode.value.length; | | |
| 932 | pos = p; | | |
| 933 | | 921 | |
| 934 | // the current node is a Token, then the match starts inside another Token, which is invalid | 922 | if (str instanceof Token) { |
| 935 | if (currentNode.value instanceof Token) { | | |
| 936 | continue; | 923 | continue; |
| 937 | } | 924 | } |
| 938 | | 925 | |
| 939 | // find the last node which is affected by this match | 926 | var removeCount = 1; // this is the to parameter of removeBetween |
| 940 | for ( | 927 | var match; |
| 941 | var k = currentNode; | | |
| 942 | k !== tokenList.tail && (p < to || typeof k.value === 'string'); | | |
| 943 | k = k.next | | |
| 944 | ) { | | |
| 945 | removeCount++; | | |
| 946 | p += k.value.length; | | |
| 947 | } | | |
| 948 | removeCount--; | | |
| 949 | | 928 | |
| 950 | // replace with the new match | 929 | if (greedy) { |
| 951 | str = text.slice(pos, p); | 930 | match = matchPattern(pattern, pos, text, lookbehind); |
| 952 | match.index -= pos; | 931 | if (!match) { |
| 953 | } else { | 932 | break; |
| 954 | match = matchPattern(pattern, 0, str, lookbehind); | 933 | } |
| 955 | if (!match) { | 934 | |
| 956 | continue; | 935 | var from = match.index; |
| | 936 | var to = match.index + match[0].length; |
| | 937 | var p = pos; |
| | 938 | |
| | 939 | // find the node that contains the match |
| | 940 | p += currentNode.value.length; |
| | 941 | while (from >= p) { |
| | 942 | currentNode = currentNode.next; |
| | 943 | p += currentNode.value.length; |
| | 944 | } |
| | 945 | // adjust pos (and p) |
| | 946 | p -= currentNode.value.length; |
| | 947 | pos = p; |
| | 948 | |
| | 949 | // the current node is a Token, then the match starts inside another Token, which is invalid |
| | 950 | if (currentNode.value instanceof Token) { |
| | 951 | continue; |
| | 952 | } |
| | 953 | |
| | 954 | // find the last node which is affected by this match |
| | 955 | for ( |
| | 956 | var k = currentNode; |
| | 957 | k !== tokenList.tail && (p < to || typeof k.value === 'string'); |
| | 958 | k = k.next |
| | 959 | ) { |
| | 960 | removeCount++; |
| | 961 | p += k.value.length; |
| | 962 | } |
| | 963 | removeCount--; |
| | 964 | |
| | 965 | // replace with the new match |
| | 966 | str = text.slice(pos, p); |
| | 967 | match.index -= pos; |
| | 968 | } else { |
| | 969 | match = matchPattern(pattern, 0, str, lookbehind); |
| | 970 | if (!match) { |
| | 971 | continue; |
| | 972 | } |
| 957 | } | 973 | } |
| 958 | } | | |
| 959 | | 974 | |
| 960 | var from = match.index, | 975 | // eslint-disable-next-line no-redeclare |
| 961 | matchStr = match[0], | 976 | var from = match.index; |
| 962 | before = str.slice(0, from), | 977 | var matchStr = match[0]; |
| 963 | after = str.slice(from + matchStr.length); | 978 | var before = str.slice(0, from); |
| | 979 | var after = str.slice(from + matchStr.length); |
| 964 | | 980 | |
| 965 | var reach = pos + str.length; | 981 | var reach = pos + str.length; |
| 966 | if (rematch && reach > rematch.reach) { | 982 | if (rematch && reach > rematch.reach) { |
| 967 | rematch.reach = reach; | 983 | rematch.reach = reach; |
| 968 | } | 984 | } |
| 969 | | 985 | |
| 970 | var removeFrom = currentNode.prev; | 986 | var removeFrom = currentNode.prev; |
| 971 | | 987 | |
| 972 | if (before) { | 988 | if (before) { |
| 973 | removeFrom = addAfter(tokenList, removeFrom, before); | 989 | removeFrom = addAfter(tokenList, removeFrom, before); |
| 974 | pos += before.length; | 990 | pos += before.length; |
| 975 | } | 991 | } |
| 976 | | 992 | |
| 977 | removeRange(tokenList, removeFrom, removeCount); | 993 | removeRange(tokenList, removeFrom, removeCount); |
| 978 | | 994 | |
| 979 | var wrapped = new Token(token, inside ? _.tokenize(matchStr, inside) : matchStr, alias, matchStr); | 995 | var wrapped = new Token(token, inside ? _.tokenize(matchStr, inside) : matchStr, alias, matchStr); |
| 980 | currentNode = addAfter(tokenList, removeFrom, wrapped); | 996 | currentNode = addAfter(tokenList, removeFrom, wrapped); |
| 981 | | 997 | |
| 982 | if (after) { | 998 | if (after) { |
| 983 | addAfter(tokenList, currentNode, after); | 999 | addAfter(tokenList, currentNode, after); |
| 984 | } | 1000 | } |
| 985 | | 1001 | |
| 986 | if (removeCount > 1) { | 1002 | if (removeCount > 1) { |
| 987 | // at least one Token object was removed, so we have to do some rematching | 1003 | // at least one Token object was removed, so we have to do some rematching |
| 988 | // this can only happen if the current pattern is greedy | 1004 | // this can only happen if the current pattern is greedy |
| 989 | | 1005 | |
| 990 | /** @type {RematchOptions} */ | 1006 | /** @type {RematchOptions} */ |
| 991 | var nestedRematch = { | 1007 | var nestedRematch = { |
| 992 | cause: token + ',' + j, | 1008 | cause: token + ',' + j, |
| 993 | reach: reach | 1009 | reach: reach |
| 994 | }; | 1010 | }; |
| 995 | matchGrammar(text, tokenList, grammar, currentNode.prev, pos, nestedRematch); | 1011 | matchGrammar(text, tokenList, grammar, currentNode.prev, pos, nestedRematch); |
| 996 | | 1012 | |
| 997 | // the reach might have been extended because of the rematching | 1013 | // the reach might have been extended because of the rematching |
| 998 | if (rematch && nestedRematch.reach > rematch.reach) { | 1014 | if (rematch && nestedRematch.reach > rematch.reach) { |
| 999 | rematch.reach = nestedRematch.reach; | 1015 | rematch.reach = nestedRematch.reach; |
| | 1016 | } |
| 1000 | } | 1017 | } |
| 1001 | } | 1018 | } |
| 1002 | } | 1019 | } |
| 1003 | } | 1020 | } |
| 1004 | } | 1021 | } |
| 1005 | } | | |
| 1006 | | 1022 | |
| 1007 | /** | 1023 | /** |
| 1008 | * @typedef LinkedListNode | 1024 | * @typedef LinkedListNode |
| 1009 | * @property {T} value | 1025 | * @property {T} value |
| 1010 | * @property {LinkedListNode<T> | null} prev The previous node. | 1026 | * @property {LinkedListNode<T> | null} prev The previous node. |
| 1011 | * @property {LinkedListNode<T> | null} next The next node. | 1027 | * @property {LinkedListNode<T> | null} next The next node. |
| 1012 | * @template T | 1028 | * @template T |
| 1013 | * @private | 1029 | * @private |
| 1014 | */ | 1030 | */ |
| 1015 | | 1031 | |
| 1016 | /** | 1032 | /** |
| 1017 | * @template T | 1033 | * @template T |
| 1018 | * @private | 1034 | * @private |
| 1019 | */ | 1035 | */ |
| 1020 | function LinkedList() { | 1036 | function LinkedList() { |
| 1021 | /** @type {LinkedListNode<T>} */ | 1037 | /** @type {LinkedListNode<T>} */ |
| 1022 | var head = { value: null, prev: null, next: null }; | 1038 | var head = { value: null, prev: null, next: null }; |
| 1023 | /** @type {LinkedListNode<T>} */ | 1039 | /** @type {LinkedListNode<T>} */ |
| 1024 | var tail = { value: null, prev: head, next: null }; | 1040 | var tail = { value: null, prev: head, next: null }; |
| 1025 | head.next = tail; | 1041 | head.next = tail; |
| 1026 | | 1042 | |
| 1027 | /** @type {LinkedListNode<T>} */ | 1043 | /** @type {LinkedListNode<T>} */ |
| 1028 | this.head = head; | 1044 | this.head = head; |
| 1029 | /** @type {LinkedListNode<T>} */ | 1045 | /** @type {LinkedListNode<T>} */ |
| 1030 | this.tail = tail; | 1046 | this.tail = tail; |
| 1031 | this.length = 0; | 1047 | this.length = 0; |
| 1032 | } | 1048 | } |
| 1033 | | 1049 | |
| 1034 | /** | 1050 | /** |
| 1035 | * Adds a new node with the given value to the list. | 1051 | * Adds a new node with the given value to the list. |
| 1036 | * @param {LinkedList<T>} list | 1052 | * |
| 1037 | * @param {LinkedListNode<T>} node | 1053 | * @param {LinkedList<T>} list |
| 1038 | * @param {T} value | 1054 | * @param {LinkedListNode<T>} node |
| 1039 | * @returns {LinkedListNode<T>} The added node. | 1055 | * @param {T} value |
| 1040 | * @template T | 1056 | * @returns {LinkedListNode<T>} The added node. |
| 1041 | */ | 1057 | * @template T |
| 1042 | function addAfter(list, node, value) { | 1058 | */ |
| 1043 | // assumes that node != list.tail && values.length >= 0 | 1059 | function addAfter(list, node, value) { |
| 1044 | var next = node.next; | 1060 | // assumes that node != list.tail && values.length >= 0 |
| | 1061 | var next = node.next; |
| 1045 | | 1062 | |
| 1046 | var newNode = { value: value, prev: node, next: next }; | 1063 | var newNode = { value: value, prev: node, next: next }; |
| 1047 | node.next = newNode; | 1064 | node.next = newNode; |
| 1048 | next.prev = newNode; | 1065 | next.prev = newNode; |
| 1049 | list.length++; | 1066 | list.length++; |
| 1050 | | 1067 | |
| 1051 | return newNode; | 1068 | return newNode; |
| 1052 | } | | |
| 1053 | /** | | |
| 1054 | * Removes `count` nodes after the given node. The given node will not be removed. | | |
| 1055 | * @param {LinkedList<T>} list | | |
| 1056 | * @param {LinkedListNode<T>} node | | |
| 1057 | * @param {number} count | | |
| 1058 | * @template T | | |
| 1059 | */ | | |
| 1060 | function removeRange(list, node, count) { | | |
| 1061 | var next = node.next; | | |
| 1062 | for (var i = 0; i < count && next !== list.tail; i++) { | | |
| 1063 | next = next.next; | | |
| 1064 | } | 1069 | } |
| 1065 | node.next = next; | 1070 | /** |
| 1066 | next.prev = node; | 1071 | * Removes `count` nodes after the given node. The given node will not be removed. |
| 1067 | list.length -= i; | 1072 | * |
| 1068 | } | 1073 | * @param {LinkedList<T>} list |
| 1069 | /** | 1074 | * @param {LinkedListNode<T>} node |
| 1070 | * @param {LinkedList<T>} list | 1075 | * @param {number} count |
| 1071 | * @returns {T[]} | 1076 | * @template T |
| 1072 | * @template T | 1077 | */ |
| 1073 | */ | 1078 | function removeRange(list, node, count) { |
| 1074 | function toArray(list) { | 1079 | var next = node.next; |
| 1075 | var array = []; | 1080 | for (var i = 0; i < count && next !== list.tail; i++) { |
| 1076 | var node = list.head.next; | 1081 | next = next.next; |
| 1077 | while (node !== list.tail) { | 1082 | } |
| 1078 | array.push(node.value); | 1083 | node.next = next; |
| 1079 | node = node.next; | 1084 | next.prev = node; |
| | 1085 | list.length -= i; |
| | 1086 | } |
| | 1087 | /** |
| | 1088 | * @param {LinkedList<T>} list |
| | 1089 | * @returns {T[]} |
| | 1090 | * @template T |
| | 1091 | */ |
| | 1092 | function toArray(list) { |
| | 1093 | var array = []; |
| | 1094 | var node = list.head.next; |
| | 1095 | while (node !== list.tail) { |
| | 1096 | array.push(node.value); |
| | 1097 | node = node.next; |
| | 1098 | } |
| | 1099 | return array; |
| 1080 | } | 1100 | } |
| 1081 | return array; | | |
| 1082 | } | | |
| 1083 | | 1101 | |
| 1084 | | 1102 | |
| 1085 | if (!_self.document) { | 1103 | if (!_self.document) { |
| 1086 | if (!_self.addEventListener) { | 1104 | if (!_self.addEventListener) { |
| 1087 | // in Node.js | 1105 | // in Node.js |
| 1088 | return _; | 1106 | return _; |
| 1089 | } | 1107 | } |
| 1090 | | 1108 | |
| 1091 | if (!_.disableWorkerMessageHandler) { | 1109 | if (!_.disableWorkerMessageHandler) { |
| 1092 | // In worker | 1110 | // In worker |
| 1093 | _self.addEventListener('message', function (evt) { | 1111 | _self.addEventListener('message', function (evt) { |
| 1094 | var message = JSON.parse(evt.data), | 1112 | var message = JSON.parse(evt.data); |
| 1095 | lang = message.language, | 1113 | var lang = message.language; |
| 1096 | code = message.code, | 1114 | var code = message.code; |
| 1097 | immediateClose = message.immediateClose; | 1115 | var immediateClose = message.immediateClose; |
| 1098 | | 1116 | |
| 1099 | _self.postMessage(_.highlight(code, _.languages[lang], lang)); | 1117 | _self.postMessage(_.highlight(code, _.languages[lang], lang)); |
| 1100 | if (immediateClose) { | 1118 | if (immediateClose) { |
| 1101 | _self.close(); | 1119 | _self.close(); |
| 1102 | } | 1120 | } |
| 1103 | }, false); | 1121 | }, false); |
| 1104 | } | 1122 | } |
| 1105 | | 1123 | |
| 1106 | return _; | 1124 | return _; |
| 1107 | } | 1125 | } |
| 1108 | | 1126 | |
| 1109 | // Get current script and highlight | 1127 | // Get current script and highlight |
| 1110 | var script = _.util.currentScript(); | 1128 | var script = _.util.currentScript(); |
| 1111 | | 1129 | |
| 1112 | if (script) { | 1130 | if (script) { |
| 1113 | _.filename = script.src; | 1131 | _.filename = script.src; |
| 1114 | | 1132 | |
| 1115 | if (script.hasAttribute('data-manual')) { | 1133 | if (script.hasAttribute('data-manual')) { |
| 1116 | _.manual = true; | 1134 | _.manual = true; |
| | 1135 | } |
| 1117 | } | 1136 | } |
| 1118 | } | | |
| 1119 | | 1137 | |
| 1120 | function highlightAutomaticallyCallback() { | 1138 | function highlightAutomaticallyCallback() { |
| 1121 | if (!_.manual) { | 1139 | if (!_.manual) { |
| 1122 | _.highlightAll(); | 1140 | _.highlightAll(); |
| | 1141 | } |
| 1123 | } | 1142 | } |
| 1124 | } | | |
| 1125 | | 1143 | |
| 1126 | if (!_.manual) { | 1144 | if (!_.manual) { |
| 1127 | // If the document state is "loading", then we'll use DOMContentLoaded. | 1145 | // If the document state is "loading", then we'll use DOMContentLoaded. |
| 1128 | // If the document state is "interactive" and the prism.js script is deferred, then we'll also use the | 1146 | // If the document state is "interactive" and the prism.js script is deferred, then we'll also use the |
| 1129 | // DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they | 1147 | // DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they |
| 1130 | // might take longer one animation frame to execute which can create a race condition where only some plugins have | 1148 | // might take longer one animation frame to execute which can create a race condition where only some plugins have |
| 1131 | // been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded. | 1149 | // been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded. |
| 1132 | // See https://github.com/PrismJS/prism/issues/2102 | 1150 | // See https://github.com/PrismJS/prism/issues/2102 |
| 1133 | var readyState = document.readyState; | 1151 | var readyState = document.readyState; |
| 1134 | if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) { | 1152 | if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) { |
| 1135 | document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback); | 1153 | document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback); |
| 1136 | } else { | | |
| 1137 | if (window.requestAnimationFrame) { | | |
| 1138 | window.requestAnimationFrame(highlightAutomaticallyCallback); | | |
| 1139 | } else { | 1154 | } else { |
| 1140 | window.setTimeout(highlightAutomaticallyCallback, 16); | 1155 | if (window.requestAnimationFrame) { |
| | 1156 | window.requestAnimationFrame(highlightAutomaticallyCallback); |
| | 1157 | } else { |
| | 1158 | window.setTimeout(highlightAutomaticallyCallback, 16); |
| | 1159 | } |
| 1141 | } | 1160 | } |
| 1142 | } | 1161 | } |
| 1143 | } | | |
| 1144 | | 1162 | |
| 1145 | return _; | 1163 | return _; |
| 1146 | | 1164 | |
| 1147 | })(_self); | 1165 | }(_self)); |
| 1148 | | 1166 | |
| 1149 | if (typeof module !== 'undefined' && module.exports) { | 1167 | if (typeof module !== 'undefined' && module.exports) { |
| 1150 | module.exports = Prism; | 1168 | module.exports = Prism; |
| @@ -1176,7 +1194,7 @@ if (typeof global !== 'undefined') { · 25 unmodified lines |
| 1176 | * each another. | 1194 | * each another. |
| 1177 | * @global | 1195 | * @global |
| 1178 | * @public | 1196 | * @public |
| 1179 | */ | 1197 | */ |
| 1180 | | 1198 | |
| 1181 | /** | 1199 | /** |
| 1182 | * @typedef Grammar | 1200 | * @typedef Grammar |
| @@ -1194,7 +1212,7 @@ if (typeof global !== 'undefined') { · 11 unmodified lines |
| 1194 | * @returns {void} | 1212 | * @returns {void} |
| 1195 | * @global | 1213 | * @global |
| 1196 | * @public | 1214 | * @public |
| 1197 | */ | 1215 | */ |
| 1198 | | 1216 | |
| 1199 | /** | 1217 | /** |
| 1200 | * @callback HookCallback | 1218 | * @callback HookCallback |
| @@ -1239,6 +1257,7 @@ Prism.languages.markup = { · 38 unmodified lines |
| 1239 | 'namespace': /^[^\s>\/:]+:/ | 1257 | 'namespace': /^[^\s>\/:]+:/ |
| 1240 | } | 1258 | } |
| 1241 | }, | 1259 | }, |
| | 1260 | 'special-attr': [], |
| 1242 | 'attr-value': { | 1261 | 'attr-value': { |
| 1243 | pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/, | 1262 | pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/, |
| 1244 | inside: { | 1263 | inside: { |
| @@ -1325,6 +1344,49 @@ Object.defineProperty(Prism.languages.markup.tag, 'addInlined', { · 80 unmodified lines |
| 1325 | Prism.languages.insertBefore('markup', 'cdata', def); | 1344 | Prism.languages.insertBefore('markup', 'cdata', def); |
| 1326 | } | 1345 | } |
| 1327 | }); | 1346 | }); |
| | 1347 | Object.defineProperty(Prism.languages.markup.tag, 'addAttribute', { |
| | 1348 | /** |
| | 1349 | * Adds an pattern to highlight languages embedded in HTML attributes. |
| | 1350 | * |
| | 1351 | * An example of an inlined language is CSS with `style` attributes. |
| | 1352 | * |
| | 1353 | * @param {string} attrName The name of the tag that contains the inlined language. This name will be treated as |
| | 1354 | * case insensitive. |
| | 1355 | * @param {string} lang The language key. |
| | 1356 | * @example |
| | 1357 | * addAttribute('style', 'css'); |
| | 1358 | */ |
| | 1359 | value: function (attrName, lang) { |
| | 1360 | Prism.languages.markup.tag.inside['special-attr'].push({ |
| | 1361 | pattern: RegExp( |
| | 1362 | /(^|["'\s])/.source + '(?:' + attrName + ')' + /\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source, |
| | 1363 | 'i' |
| | 1364 | ), |
| | 1365 | lookbehind: true, |
| | 1366 | inside: { |
| | 1367 | 'attr-name': /^[^\s=]+/, |
| | 1368 | 'attr-value': { |
| | 1369 | pattern: /=[\s\S]+/, |
| | 1370 | inside: { |
| | 1371 | 'value': { |
| | 1372 | pattern: /(=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/, |
| | 1373 | lookbehind: true, |
| | 1374 | alias: [lang, 'language-' + lang], |
| | 1375 | inside: Prism.languages[lang] |
| | 1376 | }, |
| | 1377 | 'punctuation': [ |
| | 1378 | { |
| | 1379 | pattern: /^=/, |
| | 1380 | alias: 'attr-equals' |
| | 1381 | }, |
| | 1382 | /"|'/ |
| | 1383 | ] |
| | 1384 | } |
| | 1385 | } |
| | 1386 | } |
| | 1387 | }); |
| | 1388 | } |
| | 1389 | }); |
| 1328 | | 1390 | |
| 1329 | Prism.languages.html = Prism.languages.markup; | 1391 | Prism.languages.html = Prism.languages.markup; |
| 1330 | Prism.languages.mathml = Prism.languages.markup; | 1392 | Prism.languages.mathml = Prism.languages.markup; |
| @@ -1386,34 +1448,7 @@ Prism.languages.rss = Prism.languages.xml; · 55 unmodified lines |
| 1386 | var markup = Prism.languages.markup; | 1448 | var markup = Prism.languages.markup; |
| 1387 | if (markup) { | 1449 | if (markup) { |
| 1388 | markup.tag.addInlined('style', 'css'); | 1450 | markup.tag.addInlined('style', 'css'); |
| 1389 | | 1451 | markup.tag.addAttribute('style', 'css'); |
| 1390 | Prism.languages.insertBefore('inside', 'attr-value', { | | |
| 1391 | 'style-attr': { | | |
| 1392 | pattern: /(^|["'\s])style\s*=\s*(?:"[^"]*"|'[^']*')/i, | | |
| 1393 | lookbehind: true, | | |
| 1394 | inside: { | | |
| 1395 | 'attr-value': { | | |
| 1396 | pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/, | | |
| 1397 | inside: { | | |
| 1398 | 'style': { | | |
| 1399 | pattern: /(["'])[\s\S]+(?=["']$)/, | | |
| 1400 | lookbehind: true, | | |
| 1401 | alias: 'language-css', | | |
| 1402 | inside: Prism.languages.css | | |
| 1403 | }, | | |
| 1404 | 'punctuation': [ | | |
| 1405 | { | | |
| 1406 | pattern: /^=/, | | |
| 1407 | alias: 'attr-equals' | | |
| 1408 | }, | | |
| 1409 | /"|'/ | | |
| 1410 | ] | | |
| 1411 | } | | |
| 1412 | }, | | |
| 1413 | 'attr-name': /^style/i | | |
| 1414 | } | | |
| 1415 | } | | |
| 1416 | }, markup.tag); | | |
| 1417 | } | 1452 | } |
| 1418 | | 1453 | |
| 1419 | }(Prism)); | 1454 | }(Prism)); |
| @@ -1464,7 +1499,7 @@ Prism.languages.javascript = Prism.languages.extend('clike', { · 44 unmodified lines |
| 1464 | lookbehind: true | 1499 | lookbehind: true |
| 1465 | }, | 1500 | }, |
| 1466 | { | 1501 | { |
| 1467 | pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|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/, | 1502 | pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|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/, |
| 1468 | lookbehind: true | 1503 | lookbehind: true |
| 1469 | }, | 1504 | }, |
| 1470 | ], | 1505 | ], |
| @@ -1478,7 +1513,7 @@ Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|interface|ext · 7 unmodified lines |
| 1478 | | 1513 | |
| 1479 | Prism.languages.insertBefore('javascript', 'keyword', { | 1514 | Prism.languages.insertBefore('javascript', 'keyword', { |
| 1480 | 'regex': { | 1515 | 'regex': { |
| 1481 | pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/, | 1516 | pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/, |
| 1482 | lookbehind: true, | 1517 | lookbehind: true, |
| 1483 | greedy: true, | 1518 | greedy: true, |
| 1484 | inside: { | 1519 | inside: { |
| @@ -1522,6 +1557,11 @@ Prism.languages.insertBefore('javascript', 'keyword', { · 37 unmodified lines |
| 1522 | }); | 1557 | }); |
| 1523 | | 1558 | |
| 1524 | Prism.languages.insertBefore('javascript', 'string', { | 1559 | Prism.languages.insertBefore('javascript', 'string', { |
| | 1560 | 'hashbang': { |
| | 1561 | pattern: /^#!.*/, |
| | 1562 | greedy: true, |
| | 1563 | alias: 'comment' |
| | 1564 | }, |
| 1525 | 'template-string': { | 1565 | 'template-string': { |
| 1526 | pattern: /`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/, | 1566 | pattern: /`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/, |
| 1527 | greedy: true, | 1567 | greedy: true, |
| @@ -1548,11 +1588,18 @@ Prism.languages.insertBefore('javascript', 'string', { · 20 unmodified lines |
| 1548 | | 1588 | |
| 1549 | if (Prism.languages.markup) { | 1589 | if (Prism.languages.markup) { |
| 1550 | Prism.languages.markup.tag.addInlined('script', 'javascript'); | 1590 | Prism.languages.markup.tag.addInlined('script', 'javascript'); |
| | 1591 | |
| | 1592 | // add attribute support for all DOM events. |
| | 1593 | // https://developer.mozilla.org/en-US/docs/Web/Events#Standard_events |
| | 1594 | Prism.languages.markup.tag.addAttribute( |
| | 1595 | /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, |
| | 1596 | 'javascript' |
| | 1597 | ); |
| 1551 | } | 1598 | } |
| 1552 | | 1599 | |
| 1553 | Prism.languages.js = Prism.languages.javascript; | 1600 | Prism.languages.js = Prism.languages.javascript; |
| 1554 | | 1601 | |
| 1555 | (function(Prism) { | 1602 | (function (Prism) { |
| 1556 | // $ set | grep '^[A-Z][^[:space:]]*=' | cut -d= -f1 | tr '\n' '|' | 1603 | // $ set | grep '^[A-Z][^[:space:]]*=' | cut -d= -f1 | tr '\n' '|' |
| 1557 | // + LC_ALL, RANDOM, REPLY, SECONDS. | 1604 | // + LC_ALL, RANDOM, REPLY, SECONDS. |
| 1558 | // + make sure PS1..4 are here as they are not always set, | 1605 | // + make sure PS1..4 are here as they are not always set, |
| @@ -1569,7 +1616,7 @@ Prism.languages.js = Prism.languages.javascript; · 10 unmodified lines |
| 1569 | var insideString = { | 1616 | var insideString = { |
| 1570 | 'bash': commandAfterHeredoc, | 1617 | 'bash': commandAfterHeredoc, |
| 1571 | 'environment': { | 1618 | 'environment': { |
| 1572 | pattern: RegExp("\\$" + envVars), | 1619 | pattern: RegExp('\\$' + envVars), |
| 1573 | alias: 'constant' | 1620 | alias: 'constant' |
| 1574 | }, | 1621 | }, |
| 1575 | 'variable': [ | 1622 | 'variable': [ |
| @@ -1609,7 +1656,7 @@ Prism.languages.js = Prism.languages.javascript; · 33 unmodified lines |
| 1609 | 'operator': /:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/, | 1656 | 'operator': /:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/, |
| 1610 | 'punctuation': /[\[\]]/, | 1657 | 'punctuation': /[\[\]]/, |
| 1611 | 'environment': { | 1658 | 'environment': { |
| 1612 | pattern: RegExp("(\\{)" + envVars), | 1659 | pattern: RegExp('(\\{)' + envVars), |
| 1613 | lookbehind: true, | 1660 | lookbehind: true, |
| 1614 | alias: 'constant' | 1661 | alias: 'constant' |
| 1615 | } | 1662 | } |
| @@ -1637,13 +1684,13 @@ Prism.languages.js = Prism.languages.javascript; · 21 unmodified lines |
| 1637 | // but not “foo {” | 1684 | // but not “foo {” |
| 1638 | { | 1685 | { |
| 1639 | // a) and c) | 1686 | // a) and c) |
| 1640 | pattern: /(\bfunction\s+)\w+(?=(?:\s*\(?:\s*\))?\s*\{)/, | 1687 | pattern: /(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/, |
| 1641 | lookbehind: true, | 1688 | lookbehind: true, |
| 1642 | alias: 'function' | 1689 | alias: 'function' |
| 1643 | }, | 1690 | }, |
| 1644 | { | 1691 | { |
| 1645 | // b) | 1692 | // b) |
| 1646 | pattern: /\b\w+(?=\s*\(\s*\)\s*\{)/, | 1693 | pattern: /\b[\w-]+(?=\s*\(\s*\)\s*\{)/, |
| 1647 | alias: 'function' | 1694 | alias: 'function' |
| 1648 | } | 1695 | } |
| 1649 | ], | 1696 | ], |
| @@ -1659,7 +1706,7 @@ Prism.languages.js = Prism.languages.javascript; · 9 unmodified lines |
| 1659 | pattern: /(^|[\s;|&]|[<>]\()\w+(?=\+?=)/, | 1706 | pattern: /(^|[\s;|&]|[<>]\()\w+(?=\+?=)/, |
| 1660 | inside: { | 1707 | inside: { |
| 1661 | 'environment': { | 1708 | 'environment': { |
| 1662 | pattern: RegExp("(^|[\\s;|&]|[<>]\\()" + envVars), | 1709 | pattern: RegExp('(^|[\\s;|&]|[<>]\\()' + envVars), |
| 1663 | lookbehind: true, | 1710 | lookbehind: true, |
| 1664 | alias: 'constant' | 1711 | alias: 'constant' |
| 1665 | } | 1712 | } |
| @@ -1687,14 +1734,29 @@ Prism.languages.js = Prism.languages.javascript; · 21 unmodified lines |
| 1687 | }, | 1734 | }, |
| 1688 | // “Normal” string | 1735 | // “Normal” string |
| 1689 | { | 1736 | { |
| 1690 | pattern: /(^|[^\\](?:\\\\)*)(["'])(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|(?!\2)[^\\`$])*\2/, | 1737 | // https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html |
| | 1738 | pattern: /(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/, |
| 1691 | lookbehind: true, | 1739 | lookbehind: true, |
| 1692 | greedy: true, | 1740 | greedy: true, |
| 1693 | inside: insideString | 1741 | inside: insideString |
| | 1742 | }, |
| | 1743 | { |
| | 1744 | // https://www.gnu.org/software/bash/manual/html_node/Single-Quotes.html |
| | 1745 | pattern: /(^|[^$\\])'[^']*'/, |
| | 1746 | lookbehind: true, |
| | 1747 | greedy: true |
| | 1748 | }, |
| | 1749 | { |
| | 1750 | // https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html |
| | 1751 | pattern: /\$'(?:[^'\\]|\\[\s\S])*'/, |
| | 1752 | greedy: true, |
| | 1753 | inside: { |
| | 1754 | 'entity': insideString.entity |
| | 1755 | } |
| 1694 | } | 1756 | } |
| 1695 | ], | 1757 | ], |
| 1696 | 'environment': { | 1758 | 'environment': { |
| 1697 | pattern: RegExp("\\$?" + envVars), | 1759 | pattern: RegExp('\\$?' + envVars), |
| 1698 | alias: 'constant' | 1760 | alias: 'constant' |
| 1699 | }, | 1761 | }, |
| 1700 | 'variable': insideString.variable, | 1762 | 'variable': insideString.variable, |
| @@ -1758,12 +1820,12 @@ Prism.languages.js = Prism.languages.javascript; · 57 unmodified lines |
| 1758 | 'number' | 1820 | 'number' |
| 1759 | ]; | 1821 | ]; |
| 1760 | var inside = insideString.variable[1].inside; | 1822 | var inside = insideString.variable[1].inside; |
| 1761 | for(var i = 0; i < toBeCopied.length; i++) { | 1823 | for (var i = 0; i < toBeCopied.length; i++) { |
| 1762 | inside[toBeCopied[i]] = Prism.languages.bash[toBeCopied[i]]; | 1824 | inside[toBeCopied[i]] = Prism.languages.bash[toBeCopied[i]]; |
| 1763 | } | 1825 | } |
| 1764 | | 1826 | |
| 1765 | Prism.languages.shell = Prism.languages.bash; | 1827 | Prism.languages.shell = Prism.languages.bash; |
| 1766 | })(Prism); | 1828 | }(Prism)); |
| 1767 | | 1829 | |
| 1768 | Prism.languages.c = Prism.languages.extend('clike', { | 1830 | Prism.languages.c = Prism.languages.extend('clike', { |
| 1769 | 'comment': { | 1831 | 'comment': { |
| @@ -1831,7 +1893,8 @@ delete Prism.languages.c['boolean']; · 61 unmodified lines |
| 1831 | | 1893 | |
| 1832 | (function (Prism) { | 1894 | (function (Prism) { |
| 1833 | | 1895 | |
| 1834 | var keyword = /\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/; | 1896 | var keyword = /\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/; |
| | 1897 | var modName = /\b(?!<keyword>)\w+(?:\s*\.\s*\w+)*\b/.source.replace(/<keyword>/g, function () { return keyword.source; }); |
| 1835 | | 1898 | |
| 1836 | Prism.languages.cpp = Prism.languages.extend('c', { | 1899 | Prism.languages.cpp = Prism.languages.extend('c', { |
| 1837 | 'class-name': [ | 1900 | 'class-name': [ |
| @@ -1857,11 +1920,31 @@ delete Prism.languages.c['boolean']; · 19 unmodified lines |
| 1857 | pattern: /(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i, | 1920 | pattern: /(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i, |
| 1858 | greedy: true | 1921 | greedy: true |
| 1859 | }, | 1922 | }, |
| 1860 | 'operator': />>=?|<<=?|->|([-+&|:])\1|[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/, | 1923 | 'operator': />>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/, |
| 1861 | 'boolean': /\b(?:true|false)\b/ | 1924 | 'boolean': /\b(?:true|false)\b/ |
| 1862 | }); | 1925 | }); |
| 1863 | | 1926 | |
| 1864 | Prism.languages.insertBefore('cpp', 'string', { | 1927 | Prism.languages.insertBefore('cpp', 'string', { |
| | 1928 | 'module': { |
| | 1929 | // https://en.cppreference.com/w/cpp/language/modules |
| | 1930 | pattern: RegExp( |
| | 1931 | /(\b(?:module|import)\s+)/.source + |
| | 1932 | '(?:' + |
| | 1933 | // header-name |
| | 1934 | /"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source + |
| | 1935 | '|' + |
| | 1936 | // module name or partition or both |
| | 1937 | /<mod-name>(?:\s*:\s*<mod-name>)?|:\s*<mod-name>/.source.replace(/<mod-name>/g, function () { return modName; }) + |
| | 1938 | ')' |
| | 1939 | ), |
| | 1940 | lookbehind: true, |
| | 1941 | greedy: true, |
| | 1942 | inside: { |
| | 1943 | 'string': /^[<"][\s\S]+/, |
| | 1944 | 'operator': /:/, |
| | 1945 | 'punctuation': /\./ |
| | 1946 | } |
| | 1947 | }, |
| 1865 | 'raw-string': { | 1948 | 'raw-string': { |
| 1866 | pattern: /R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/, | 1949 | pattern: /R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/, |
| 1867 | alias: 'string', | 1950 | alias: 'string', |
| @@ -1869,6 +1952,27 @@ delete Prism.languages.c['boolean']; · 1 unmodified line |
| 1869 | } | 1952 | } |
| 1870 | }); | 1953 | }); |
| 1871 | | 1954 | |
| | 1955 | Prism.languages.insertBefore('cpp', 'keyword', { |
| | 1956 | 'generic-function': { |
| | 1957 | pattern: /\b[a-z_]\w*\s*<(?:[^<>]|<(?:[^<>])*>)*>(?=\s*\()/i, |
| | 1958 | inside: { |
| | 1959 | 'function': /^\w+/, |
| | 1960 | 'generic': { |
| | 1961 | pattern: /<[\s\S]+/, |
| | 1962 | alias: 'class-name', |
| | 1963 | inside: Prism.languages.cpp |
| | 1964 | } |
| | 1965 | } |
| | 1966 | } |
| | 1967 | }); |
| | 1968 | |
| | 1969 | Prism.languages.insertBefore('cpp', 'operator', { |
| | 1970 | 'double-colon': { |
| | 1971 | pattern: /::/, |
| | 1972 | alias: 'punctuation' |
| | 1973 | } |
| | 1974 | }); |
| | 1975 | |
| 1872 | Prism.languages.insertBefore('cpp', 'class-name', { | 1976 | Prism.languages.insertBefore('cpp', 'class-name', { |
| 1873 | // the base clause is an optional list of parent classes | 1977 | // the base clause is an optional list of parent classes |
| 1874 | // https://en.cppreference.com/w/cpp/language/class | 1978 | // https://en.cppreference.com/w/cpp/language/class |
| @@ -1879,108 +1983,109 @@ delete Prism.languages.c['boolean']; · 4 unmodified lines |
| 1879 | inside: Prism.languages.extend('cpp', {}) | 1983 | inside: Prism.languages.extend('cpp', {}) |
| 1880 | } | 1984 | } |
| 1881 | }); | 1985 | }); |
| 1882 | Prism.languages.insertBefore('inside', 'operator', { | 1986 | |
| | 1987 | Prism.languages.insertBefore('inside', 'double-colon', { |
| 1883 | // All untokenized words that are not namespaces should be class names | 1988 | // All untokenized words that are not namespaces should be class names |
| 1884 | 'class-name': /\b[a-z_]\w*\b(?!\s*::)/i | 1989 | 'class-name': /\b[a-z_]\w*\b(?!\s*::)/i |
| 1885 | }, Prism.languages.cpp['base-clause']); | 1990 | }, Prism.languages.cpp['base-clause']); |
| 1886 | | 1991 | |
| 1887 | }(Prism)); | 1992 | }(Prism)); |
| 1888 | | 1993 | |
| 1889 | (function(Prism) { | 1994 | (function (Prism) { |
| 1890 | | | |
| 1891 | // Ignore comments starting with { to privilege string interpolation highlighting | | |
| 1892 | var comment = /#(?!\{).+/, | | |
| 1893 | interpolation = { | | |
| 1894 | pattern: /#\{[^}]+\}/, | | |
| 1895 | alias: 'variable' | | |
| 1896 | }; | | |
| 1897 | | 1995 | |
| 1898 | Prism.languages.coffeescript = Prism.languages.extend('javascript', { | 1996 | // Ignore comments starting with { to privilege string interpolation highlighting |
| 1899 | 'comment': comment, | 1997 | var comment = /#(?!\{).+/; |
| 1900 | 'string': [ | 1998 | var interpolation = { |
| | 1999 | pattern: /#\{[^}]+\}/, |
| | 2000 | alias: 'variable' |
| | 2001 | }; |
| 1901 | | 2002 | |
| 1902 | // Strings are multiline | 2003 | Prism.languages.coffeescript = Prism.languages.extend('javascript', { |
| 1903 | { | 2004 | 'comment': comment, |
| 1904 | pattern: /'(?:\\[\s\S]|[^\\'])*'/, | 2005 | 'string': [ |
| 1905 | greedy: true | | |
| 1906 | }, | | |
| 1907 | | 2006 | |
| 1908 | { | | |
| 1909 | // Strings are multiline | 2007 | // Strings are multiline |
| 1910 | pattern: /"(?:\\[\s\S]|[^\\"])*"/, | 2008 | { |
| 1911 | greedy: true, | 2009 | pattern: /'(?:\\[\s\S]|[^\\'])*'/, |
| 1912 | inside: { | 2010 | greedy: true |
| 1913 | 'interpolation': interpolation | 2011 | }, |
| | 2012 | |
| | 2013 | { |
| | 2014 | // Strings are multiline |
| | 2015 | pattern: /"(?:\\[\s\S]|[^\\"])*"/, |
| | 2016 | greedy: true, |
| | 2017 | inside: { |
| | 2018 | 'interpolation': interpolation |
| | 2019 | } |
| 1914 | } | 2020 | } |
| | 2021 | ], |
| | 2022 | 'keyword': /\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/, |
| | 2023 | 'class-member': { |
| | 2024 | pattern: /@(?!\d)\w+/, |
| | 2025 | alias: 'variable' |
| 1915 | } | 2026 | } |
| 1916 | ], | 2027 | }); |
| 1917 | 'keyword': /\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/, | | |
| 1918 | 'class-member': { | | |
| 1919 | pattern: /@(?!\d)\w+/, | | |
| 1920 | alias: 'variable' | | |
| 1921 | } | | |
| 1922 | }); | | |
| 1923 | | | |
| 1924 | Prism.languages.insertBefore('coffeescript', 'comment', { | | |
| 1925 | 'multiline-comment': { | | |
| 1926 | pattern: /###[\s\S]+?###/, | | |
| 1927 | alias: 'comment' | | |
| 1928 | }, | | |
| 1929 | | 2028 | |
| 1930 | // Block regexp can contain comments and interpolation | 2029 | Prism.languages.insertBefore('coffeescript', 'comment', { |
| 1931 | 'block-regex': { | 2030 | 'multiline-comment': { |
| 1932 | pattern: /\/{3}[\s\S]*?\/{3}/, | 2031 | pattern: /###[\s\S]+?###/, |
| 1933 | alias: 'regex', | 2032 | alias: 'comment' |
| 1934 | inside: { | 2033 | }, |
| 1935 | 'comment': comment, | | |
| 1936 | 'interpolation': interpolation | | |
| 1937 | } | | |
| 1938 | } | | |
| 1939 | }); | | |
| 1940 | | 2034 | |
| 1941 | Prism.languages.insertBefore('coffeescript', 'string', { | 2035 | // Block regexp can contain comments and interpolation |
| 1942 | 'inline-javascript': { | 2036 | 'block-regex': { |
| 1943 | pattern: /`(?:\\[\s\S]|[^\\`])*`/, | 2037 | pattern: /\/{3}[\s\S]*?\/{3}/, |
| 1944 | inside: { | 2038 | alias: 'regex', |
| 1945 | 'delimiter': { | 2039 | inside: { |
| 1946 | pattern: /^`|`$/, | 2040 | 'comment': comment, |
| 1947 | alias: 'punctuation' | 2041 | 'interpolation': interpolation |
| 1948 | }, | | |
| 1949 | 'script': { | | |
| 1950 | pattern: /[\s\S]+/, | | |
| 1951 | alias: 'language-javascript', | | |
| 1952 | inside: Prism.languages.javascript | | |
| 1953 | } | 2042 | } |
| 1954 | } | 2043 | } |
| 1955 | }, | 2044 | }); |
| 1956 | | 2045 | |
| 1957 | // Block strings | 2046 | Prism.languages.insertBefore('coffeescript', 'string', { |
| 1958 | 'multiline-string': [ | 2047 | 'inline-javascript': { |
| 1959 | { | 2048 | pattern: /`(?:\\[\s\S]|[^\\`])*`/, |
| 1960 | pattern: /'''[\s\S]*?'''/, | | |
| 1961 | greedy: true, | | |
| 1962 | alias: 'string' | | |
| 1963 | }, | | |
| 1964 | { | | |
| 1965 | pattern: /"""[\s\S]*?"""/, | | |
| 1966 | greedy: true, | | |
| 1967 | alias: 'string', | | |
| 1968 | inside: { | 2049 | inside: { |
| 1969 | interpolation: interpolation | 2050 | 'delimiter': { |
| | 2051 | pattern: /^`|`$/, |
| | 2052 | alias: 'punctuation' |
| | 2053 | }, |
| | 2054 | 'script': { |
| | 2055 | pattern: /[\s\S]+/, |
| | 2056 | alias: 'language-javascript', |
| | 2057 | inside: Prism.languages.javascript |
| | 2058 | } |
| 1970 | } | 2059 | } |
| 1971 | } | 2060 | }, |
| 1972 | ] | | |
| 1973 | | 2061 | |
| 1974 | }); | 2062 | // Block strings |
| | 2063 | 'multiline-string': [ |
| | 2064 | { |
| | 2065 | pattern: /'''[\s\S]*?'''/, |
| | 2066 | greedy: true, |
| | 2067 | alias: 'string' |
| | 2068 | }, |
| | 2069 | { |
| | 2070 | pattern: /"""[\s\S]*?"""/, |
| | 2071 | greedy: true, |
| | 2072 | alias: 'string', |
| | 2073 | inside: { |
| | 2074 | interpolation: interpolation |
| | 2075 | } |
| | 2076 | } |
| | 2077 | ] |
| 1975 | | 2078 | |
| 1976 | Prism.languages.insertBefore('coffeescript', 'keyword', { | 2079 | }); |
| 1977 | // Object property | 2080 | |
| 1978 | 'property': /(?!\d)\w+(?=\s*:(?!:))/ | 2081 | Prism.languages.insertBefore('coffeescript', 'keyword', { |
| 1979 | }); | 2082 | // Object property |
| | 2083 | 'property': /(?!\d)\w+(?=\s*:(?!:))/ |
| | 2084 | }); |
| 1980 | | 2085 | |
| 1981 | delete Prism.languages.coffeescript['template-string']; | 2086 | delete Prism.languages.coffeescript['template-string']; |
| 1982 | | 2087 | |
| 1983 | Prism.languages.coffee = Prism.languages.coffeescript; | 2088 | Prism.languages.coffee = Prism.languages.coffeescript; |
| 1984 | }(Prism)); | 2089 | }(Prism)); |
| 1985 | | 2090 | |
| 1986 | /** | 2091 | /** |
| @@ -2025,22 +2130,25 @@ Prism.languages.coffee = Prism.languages.coffeescript; · 38 unmodified lines |
| 2025 | 'regex': [ | 2130 | 'regex': [ |
| 2026 | { | 2131 | { |
| 2027 | pattern: RegExp(/%r/.source + '(?:' + [ | 2132 | pattern: RegExp(/%r/.source + '(?:' + [ |
| 2028 | /([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[gim]{0,3}/.source, | 2133 | /([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source, |
| 2029 | /\((?:[^()\\]|\\[\s\S])*\)[gim]{0,3}/.source, | 2134 | /\((?:[^()\\]|\\[\s\S])*\)/.source, |
| 2030 | // Here we need to specifically allow interpolation | 2135 | // Here we need to specifically allow interpolation |
| 2031 | /\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}[gim]{0,3}/.source, | 2136 | /\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}/.source, |
| 2032 | /\[(?:[^\[\]\\]|\\[\s\S])*\][gim]{0,3}/.source, | 2137 | /\[(?:[^\[\]\\]|\\[\s\S])*\]/.source, |
| 2033 | /<(?:[^<>\\]|\\[\s\S])*>[gim]{0,3}/.source | 2138 | /<(?:[^<>\\]|\\[\s\S])*>/.source |
| 2034 | ].join('|') + ')'), | 2139 | ].join('|') + ')' + /[egimnosux]{0,6}/.source), |
| 2035 | greedy: true, | 2140 | greedy: true, |
| 2036 | inside: { | 2141 | inside: { |
| 2037 | 'interpolation': interpolation | 2142 | 'interpolation': interpolation |
| 2038 | } | 2143 | } |
| 2039 | }, | 2144 | }, |
| 2040 | { | 2145 | { |
| 2041 | pattern: /(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[gim]{0,3}(?=\s*(?:$|[\r\n,.;})]))/, | 2146 | pattern: /(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/, |
| 2042 | lookbehind: true, | 2147 | lookbehind: true, |
| 2043 | greedy: true | 2148 | greedy: true, |
| | 2149 | inside: { |
| | 2150 | 'interpolation': interpolation |
| | 2151 | } |
| 2044 | } | 2152 | } |
| 2045 | ], | 2153 | ], |
| 2046 | 'variable': /[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/, | 2154 | 'variable': /[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/, |
| @@ -2084,13 +2192,42 @@ Prism.languages.coffee = Prism.languages.coffeescript; · 37 unmodified lines |
| 2084 | inside: { | 2192 | inside: { |
| 2085 | 'interpolation': interpolation | 2193 | 'interpolation': interpolation |
| 2086 | } | 2194 | } |
| | 2195 | }, |
| | 2196 | { |
| | 2197 | pattern: /<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i, |
| | 2198 | alias: 'heredoc-string', |
| | 2199 | greedy: true, |
| | 2200 | inside: { |
| | 2201 | 'delimiter': { |
| | 2202 | pattern: /^<<[-~]?[a-z_]\w*|[a-z_]\w*$/i, |
| | 2203 | alias: 'symbol', |
| | 2204 | inside: { |
| | 2205 | 'punctuation': /^<<[-~]?/ |
| | 2206 | } |
| | 2207 | }, |
| | 2208 | 'interpolation': interpolation |
| | 2209 | } |
| | 2210 | }, |
| | 2211 | { |
| | 2212 | pattern: /<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i, |
| | 2213 | alias: 'heredoc-string', |
| | 2214 | greedy: true, |
| | 2215 | inside: { |
| | 2216 | 'delimiter': { |
| | 2217 | pattern: /^<<[-~]?'[a-z_]\w*'|[a-z_]\w*$/i, |
| | 2218 | alias: 'symbol', |
| | 2219 | inside: { |
| | 2220 | 'punctuation': /^<<[-~]?'|'$/, |
| | 2221 | } |
| | 2222 | } |
| | 2223 | } |
| 2087 | } | 2224 | } |
| 2088 | ]; | 2225 | ]; |
| 2089 | | 2226 | |
| 2090 | Prism.languages.rb = Prism.languages.ruby; | 2227 | Prism.languages.rb = Prism.languages.ruby; |
| 2091 | }(Prism)); | 2228 | }(Prism)); |
| 2092 | | 2229 | |
| 2093 | (function(Prism) { | 2230 | (function (Prism) { |
| 2094 | Prism.languages.crystal = Prism.languages.extend('ruby', { | 2231 | Prism.languages.crystal = Prism.languages.extend('ruby', { |
| 2095 | keyword: [ | 2232 | keyword: [ |
| 2096 | /\b(?:abstract|alias|as|asm|begin|break|case|class|def|do|else|elsif|end|ensure|enum|extend|for|fun|if|include|instance_sizeof|lib|macro|module|next|of|out|pointerof|private|protected|rescue|return|require|select|self|sizeof|struct|super|then|type|typeof|uninitialized|union|unless|until|when|while|with|yield|__DIR__|__END_LINE__|__FILE__|__LINE__)\b/, | 2233 | /\b(?:abstract|alias|as|asm|begin|break|case|class|def|do|else|elsif|end|ensure|enum|extend|for|fun|if|include|instance_sizeof|lib|macro|module|next|of|out|pointerof|private|protected|rescue|return|require|select|self|sizeof|struct|super|then|type|typeof|uninitialized|union|unless|until|when|while|with|yield|__DIR__|__END_LINE__|__FILE__|__LINE__)\b/, |
| @@ -2117,26 +2254,26 @@ Prism.languages.coffee = Prism.languages.coffeescript; · 20 unmodified lines |
| 2117 | }, | 2254 | }, |
| 2118 | | 2255 | |
| 2119 | expansion: [ | 2256 | expansion: [ |
| 2120 | { | 2257 | { |
| 2121 | pattern: /\{\{.+?\}\}/, | 2258 | pattern: /\{\{.+?\}\}/, |
| 2122 | inside: { | 2259 | inside: { |
| 2123 | delimiter: { | 2260 | delimiter: { |
| 2124 | pattern: /^\{\{|\}\}$/, | 2261 | pattern: /^\{\{|\}\}$/, |
| 2125 | alias: 'tag' | 2262 | alias: 'tag' |
| 2126 | }, | 2263 | }, |
| 2127 | rest: Prism.languages.crystal | 2264 | rest: Prism.languages.crystal |
| 2128 | } | 2265 | } |
| 2129 | }, | 2266 | }, |
| 2130 | { | 2267 | { |
| 2131 | pattern: /\{%.+?%\}/, | 2268 | pattern: /\{%.+?%\}/, |
| 2132 | inside: { | 2269 | inside: { |
| 2133 | delimiter: { | 2270 | delimiter: { |
| 2134 | pattern: /^\{%|%\}$/, | 2271 | pattern: /^\{%|%\}$/, |
| 2135 | alias: 'tag' | 2272 | alias: 'tag' |
| 2136 | }, | 2273 | }, |
| 2137 | rest: Prism.languages.crystal | 2274 | rest: Prism.languages.crystal |
| | 2275 | } |
| 2138 | } | 2276 | } |
| 2139 | } | | |
| 2140 | ] | 2277 | ] |
| 2141 | }); | 2278 | }); |
| 2142 | | 2279 | |
| @@ -2223,30 +2360,73 @@ Prism.languages.insertBefore('d', 'function', { · 80 unmodified lines |
| 2223 | } | 2360 | } |
| 2224 | }); | 2361 | }); |
| 2225 | | 2362 | |
| 2226 | Prism.languages.dart = Prism.languages.extend('clike', { | 2363 | (function (Prism) { |
| 2227 | 'string': [ | 2364 | var keywords = [ |
| 2228 | { | | |
| 2229 | pattern: /r?("""|''')[\s\S]*?\1/, | | |
| 2230 | greedy: true | | |
| 2231 | }, | | |
| 2232 | { | | |
| 2233 | pattern: /r?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/, | | |
| 2234 | greedy: true | | |
| 2235 | } | | |
| 2236 | ], | | |
| 2237 | 'keyword': [ | | |
| 2238 | /\b(?:async|sync|yield)\*/, | 2365 | /\b(?:async|sync|yield)\*/, |
| 2239 | /\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extension|external|extends|factory|final|finally|for|Function|get|hide|if|implements|interface|import|in|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/ | 2366 | /\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extension|external|extends|factory|final|finally|for|get|hide|if|implements|interface|import|in|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/ |
| 2240 | ], | 2367 | ]; |
| 2241 | 'operator': /\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/ | | |
| 2242 | }); | | |
| 2243 | | 2368 | |
| 2244 | Prism.languages.insertBefore('dart','function',{ | 2369 | // Handles named imports, such as http.Client |
| 2245 | 'metadata': { | 2370 | var packagePrefix = /(^|[^\w.])(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source; |
| 2246 | pattern: /@\w+/, | 2371 | |
| 2247 | alias: 'symbol' | 2372 | // based on the dart naming conventions |
| 2248 | } | 2373 | var className = { |
| 2249 | }); | 2374 | pattern: RegExp(packagePrefix + /[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source), |
| | 2375 | lookbehind: true, |
| | 2376 | inside: { |
| | 2377 | 'namespace': { |
| | 2378 | pattern: /^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/, |
| | 2379 | inside: { |
| | 2380 | 'punctuation': /\./ |
| | 2381 | } |
| | 2382 | }, |
| | 2383 | } |
| | 2384 | }; |
| | 2385 | |
| | 2386 | Prism.languages.dart = Prism.languages.extend('clike', { |
| | 2387 | 'string': [ |
| | 2388 | { |
| | 2389 | pattern: /r?("""|''')[\s\S]*?\1/, |
| | 2390 | greedy: true |
| | 2391 | }, |
| | 2392 | { |
| | 2393 | pattern: /r?(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/, |
| | 2394 | greedy: true |
| | 2395 | } |
| | 2396 | ], |
| | 2397 | 'class-name': [ |
| | 2398 | className, |
| | 2399 | { |
| | 2400 | // variables and parameters |
| | 2401 | // this to support class names (or generic parameters) which do not contain a lower case letter (also works for methods) |
| | 2402 | pattern: RegExp(packagePrefix + /[A-Z]\w*(?=\s+\w+\s*[;,=()])/.source), |
| | 2403 | lookbehind: true, |
| | 2404 | inside: className.inside |
| | 2405 | } |
| | 2406 | ], |
| | 2407 | 'keyword': keywords, |
| | 2408 | 'operator': /\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/ |
| | 2409 | }); |
| | 2410 | |
| | 2411 | Prism.languages.insertBefore('dart', 'function', { |
| | 2412 | 'metadata': { |
| | 2413 | pattern: /@\w+/, |
| | 2414 | alias: 'symbol' |
| | 2415 | } |
| | 2416 | }); |
| | 2417 | |
| | 2418 | Prism.languages.insertBefore('dart', 'class-name', { |
| | 2419 | 'generics': { |
| | 2420 | pattern: /<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/, |
| | 2421 | inside: { |
| | 2422 | 'class-name': className, |
| | 2423 | 'keyword': keywords, |
| | 2424 | 'punctuation': /[<>(),.:]/, |
| | 2425 | 'operator': /[?&|]/ |
| | 2426 | } |
| | 2427 | }, |
| | 2428 | }); |
| | 2429 | }(Prism)); |
| 2250 | | 2430 | |
| 2251 | (function (Prism) { | 2431 | (function (Prism) { |
| 2252 | | 2432 | |
| @@ -2285,8 +2465,8 @@ Prism.languages.insertBefore('dart','function',{ · 32 unmodified lines |
| 2285 | if (!/^\w+$/.test(name)) { // "deleted-sign" -> "deleted" | 2465 | if (!/^\w+$/.test(name)) { // "deleted-sign" -> "deleted" |
| 2286 | alias.push(/\w+/.exec(name)[0]); | 2466 | alias.push(/\w+/.exec(name)[0]); |
| 2287 | } | 2467 | } |
| 2288 | if (name === "diff") { | 2468 | if (name === 'diff') { |
| 2289 | alias.push("bold"); | 2469 | alias.push('bold'); |
| 2290 | } | 2470 | } |
| 2291 | | 2471 | |
| 2292 | Prism.languages.diff[name] = { | 2472 | Prism.languages.diff[name] = { |
| @@ -2354,8 +2534,9 @@ Prism.languages.insertBefore('dart','function',{ · 61 unmodified lines |
| 2354 | var placeholder; | 2534 | var placeholder; |
| 2355 | | 2535 | |
| 2356 | // Check for existing strings | 2536 | // Check for existing strings |
| 2357 | while (env.code.indexOf(placeholder = getPlaceholder(language, i)) !== -1) | 2537 | while (env.code.indexOf(placeholder = getPlaceholder(language, i)) !== -1) { |
| 2358 | ++i; | 2538 | ++i; |
| | 2539 | } |
| 2359 | | 2540 | |
| 2360 | // Create a sparse array | 2541 | // Create a sparse array |
| 2361 | tokenStack[i] = match; | 2542 | tokenStack[i] = match; |
| @@ -2496,10 +2677,20 @@ Prism.languages.insertBefore('dart','function',{ · 134 unmodified lines |
| 2496 | markupTemplating.tokenizePlaceholders(env, 'jinja2'); | 2677 | markupTemplating.tokenizePlaceholders(env, 'jinja2'); |
| 2497 | }); | 2678 | }); |
| 2498 | | 2679 | |
| 2499 | })(Prism); | 2680 | }(Prism)); |
| 2500 | | 2681 | |
| 2501 | Prism.languages.elixir = { | 2682 | Prism.languages.elixir = { |
| 2502 | 'comment': /#.*/m, | 2683 | 'doc': { |
| | 2684 | pattern: /@(?:doc|moduledoc)\s+(?:("""|''')[\s\S]*?\1|("|')(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2)/, |
| | 2685 | inside: { |
| | 2686 | 'attribute': /^@\w+/, |
| | 2687 | 'string': /['"][\s\S]+/ |
| | 2688 | } |
| | 2689 | }, |
| | 2690 | 'comment': { |
| | 2691 | pattern: /#.*/m, |
| | 2692 | greedy: true |
| | 2693 | }, |
| 2503 | // ~r"""foo""" (multi-line), ~r'''foo''' (multi-line), ~r/foo/, ~r|foo|, ~r"foo", ~r'foo', ~r(foo), ~r[foo], ~r{foo}, ~r<foo> | 2694 | // ~r"""foo""" (multi-line), ~r'''foo''' (multi-line), ~r/foo/, ~r|foo|, ~r"foo", ~r'foo', ~r(foo), ~r[foo], ~r{foo}, ~r<foo> |
| 2504 | 'regex': { | 2695 | 'regex': { |
| 2505 | pattern: /~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/, | 2696 | pattern: /~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/, |
| @@ -2536,14 +2727,12 @@ Prism.languages.elixir = { · 30 unmodified lines |
| 2536 | lookbehind: true, | 2727 | lookbehind: true, |
| 2537 | alias: 'symbol' | 2728 | alias: 'symbol' |
| 2538 | }, | 2729 | }, |
| | 2730 | 'module': { |
| | 2731 | pattern: /\b[A-Z]\w*\b/, |
| | 2732 | alias: 'class-name' |
| | 2733 | }, |
| 2539 | // Look-ahead prevents bad highlighting of the :: operator | 2734 | // Look-ahead prevents bad highlighting of the :: operator |
| 2540 | 'attr-name': /\w+\??:(?!:)/, | 2735 | 'attr-name': /\w+\??:(?!:)/, |
| 2541 | 'capture': { | | |
| 2542 | // Look-behind prevents bad highlighting of the && operator | | |
| 2543 | pattern: /(^|[^&])&(?:[^&\s\d()][^\s()]*|(?=\())/, | | |
| 2544 | lookbehind: true, | | |
| 2545 | alias: 'function' | | |
| 2546 | }, | | |
| 2547 | 'argument': { | 2736 | 'argument': { |
| 2548 | // Look-behind prevents bad highlighting of the && operator | 2737 | // Look-behind prevents bad highlighting of the && operator |
| 2549 | pattern: /(^|[^&])&\d+/, | 2738 | pattern: /(^|[^&])&\d+/, |
| @@ -2554,8 +2743,9 @@ Prism.languages.elixir = { · 4 unmodified lines |
| 2554 | pattern: /@\w+/, | 2743 | pattern: /@\w+/, |
| 2555 | alias: 'variable' | 2744 | alias: 'variable' |
| 2556 | }, | 2745 | }, |
| | 2746 | 'function': /\b[_a-zA-Z]\w*[?!]?(?:(?=\s*(?:\.\s*)?\()|(?=\/\d+))/, |
| 2557 | 'number': /\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i, | 2747 | 'number': /\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i, |
| 2558 | 'keyword': /\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct|delegate)?|do|else|end|fn|for|if|import|not|or|require|rescue|try|unless|use|when)\b/, | 2748 | 'keyword': /\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct|delegate)?|do|else|end|fn|for|if|import|not|or|raise|require|rescue|try|unless|use|when)\b/, |
| 2559 | 'boolean': /\b(?:true|false|nil)\b/, | 2749 | 'boolean': /\b(?:true|false|nil)\b/, |
| 2560 | 'operator': [ | 2750 | 'operator': [ |
| 2561 | /\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/, | 2751 | /\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/, |
| @@ -2573,19 +2763,7 @@ Prism.languages.elixir = { · 11 unmodified lines |
| 2573 | 'punctuation': /<<|>>|[.,%\[\]{}()]/ | 2763 | 'punctuation': /<<|>>|[.,%\[\]{}()]/ |
| 2574 | }; | 2764 | }; |
| 2575 | | 2765 | |
| 2576 | Prism.languages.insertBefore('elixir', 'keyword', { | 2766 | Prism.languages.elixir.string.forEach(function (o) { |
| 2577 | 'module': { | | |
| 2578 | pattern: /\b(defmodule\s)[A-Z][\w.\\]+/, | | |
| 2579 | lookbehind: true, | | |
| 2580 | alias: 'class-name' | | |
| 2581 | }, | | |
| 2582 | 'function': { | | |
| 2583 | pattern: /\b(defp?\s)[\w.\\]+/, | | |
| 2584 | lookbehind: true | | |
| 2585 | } | | |
| 2586 | }); | | |
| 2587 | | | |
| 2588 | Prism.languages.elixir.string.forEach(function(o) { | | |
| 2589 | o.inside = { | 2767 | o.inside = { |
| 2590 | 'interpolation': { | 2768 | 'interpolation': { |
| 2591 | pattern: /#\{[^}]+\}/, | 2769 | pattern: /#\{[^}]+\}/, |
| @@ -2701,7 +2879,7 @@ Prism.languages.insertBefore('groovy', 'function', { · 109 unmodified lines |
| 2701 | }); | 2879 | }); |
| 2702 | | 2880 | |
| 2703 | // Handle string interpolation | 2881 | // Handle string interpolation |
| 2704 | Prism.hooks.add('wrap', function(env) { | 2882 | Prism.hooks.add('wrap', function (env) { |
| 2705 | if (env.language === 'groovy' && env.type === 'string') { | 2883 | if (env.language === 'groovy' && env.type === 'string') { |
| 2706 | var delimiter = env.content[0]; | 2884 | var delimiter = env.content[0]; |
| 2707 | | 2885 | |
| @@ -2791,7 +2969,7 @@ Prism.hooks.add('wrap', function(env) { · 83 unmodified lines |
| 2791 | alias: 'punctuation' | 2969 | alias: 'punctuation' |
| 2792 | }, | 2970 | }, |
| 2793 | 'generics': { | 2971 | 'generics': { |
| 2794 | pattern: /<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/, | 2972 | pattern: /<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/, |
| 2795 | inside: { | 2973 | inside: { |
| 2796 | 'class-name': className, | 2974 | 'class-name': className, |
| 2797 | 'keyword': keywords, | 2975 | 'keyword': keywords, |
| @@ -2893,7 +3071,7 @@ Prism.languages.julia = { · 95 unmodified lines |
| 2893 | 'operator': /\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/ | 3071 | 'operator': /\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/ |
| 2894 | }); | 3072 | }); |
| 2895 | | 3073 | |
| 2896 | delete Prism.languages.kotlin["class-name"]; | 3074 | delete Prism.languages.kotlin['class-name']; |
| 2897 | | 3075 | |
| 2898 | Prism.languages.insertBefore('kotlin', 'string', { | 3076 | Prism.languages.insertBefore('kotlin', 'string', { |
| 2899 | 'raw-string': { | 3077 | 'raw-string': { |
| @@ -2940,6 +3118,71 @@ Prism.languages.julia = { · 40 unmodified lines |
| 2940 | Prism.languages.kts = Prism.languages.kotlin; | 3118 | Prism.languages.kts = Prism.languages.kotlin; |
| 2941 | }(Prism)); | 3119 | }(Prism)); |
| 2942 | | 3120 | |
| | 3121 | (function (Prism) { |
| | 3122 | var funcPattern = /\\(?:[^a-z()[\]]|[a-z*]+)/i; |
| | 3123 | var insideEqu = { |
| | 3124 | 'equation-command': { |
| | 3125 | pattern: funcPattern, |
| | 3126 | alias: 'regex' |
| | 3127 | } |
| | 3128 | }; |
| | 3129 | |
| | 3130 | Prism.languages.latex = { |
| | 3131 | 'comment': /%.*/m, |
| | 3132 | // the verbatim environment prints whitespace to the document |
| | 3133 | 'cdata': { |
| | 3134 | pattern: /(\\begin\{((?:verbatim|lstlisting)\*?)\})[\s\S]*?(?=\\end\{\2\})/, |
| | 3135 | lookbehind: true |
| | 3136 | }, |
| | 3137 | /* |
| | 3138 | * equations can be between $$ $$ or $ $ or \( \) or \[ \] |
| | 3139 | * (all are multiline) |
| | 3140 | */ |
| | 3141 | 'equation': [ |
| | 3142 | { |
| | 3143 | pattern: /\$\$(?:\\[\s\S]|[^\\$])+\$\$|\$(?:\\[\s\S]|[^\\$])+\$|\\\([\s\S]*?\\\)|\\\[[\s\S]*?\\\]/, |
| | 3144 | inside: insideEqu, |
| | 3145 | alias: 'string' |
| | 3146 | }, |
| | 3147 | { |
| | 3148 | pattern: /(\\begin\{((?:equation|math|eqnarray|align|multline|gather)\*?)\})[\s\S]*?(?=\\end\{\2\})/, |
| | 3149 | lookbehind: true, |
| | 3150 | inside: insideEqu, |
| | 3151 | alias: 'string' |
| | 3152 | } |
| | 3153 | ], |
| | 3154 | /* |
| | 3155 | * arguments which are keywords or references are highlighted |
| | 3156 | * as keywords |
| | 3157 | */ |
| | 3158 | 'keyword': { |
| | 3159 | pattern: /(\\(?:begin|end|ref|cite|label|usepackage|documentclass)(?:\[[^\]]+\])?\{)[^}]+(?=\})/, |
| | 3160 | lookbehind: true |
| | 3161 | }, |
| | 3162 | 'url': { |
| | 3163 | pattern: /(\\url\{)[^}]+(?=\})/, |
| | 3164 | lookbehind: true |
| | 3165 | }, |
| | 3166 | /* |
| | 3167 | * section or chapter headlines are highlighted as bold so that |
| | 3168 | * they stand out more |
| | 3169 | */ |
| | 3170 | 'headline': { |
| | 3171 | pattern: /(\\(?:part|chapter|section|subsection|frametitle|subsubsection|paragraph|subparagraph|subsubparagraph|subsubsubparagraph)\*?(?:\[[^\]]+\])?\{)[^}]+(?=\}(?:\[[^\]]+\])?)/, |
| | 3172 | lookbehind: true, |
| | 3173 | alias: 'class-name' |
| | 3174 | }, |
| | 3175 | 'function': { |
| | 3176 | pattern: funcPattern, |
| | 3177 | alias: 'selector' |
| | 3178 | }, |
| | 3179 | 'punctuation': /[[\]{}&]/ |
| | 3180 | }; |
| | 3181 | |
| | 3182 | Prism.languages.tex = Prism.languages.latex; |
| | 3183 | Prism.languages.context = Prism.languages.latex; |
| | 3184 | }(Prism)); |
| | 3185 | |
| 2943 | Prism.languages.lua = { | 3186 | Prism.languages.lua = { |
| 2944 | 'comment': /^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m, | 3187 | 'comment': /^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m, |
| 2945 | // \z may be used to skip the following space | 3188 | // \z may be used to skip the following space |
| @@ -2978,17 +3221,58 @@ Prism.languages.matlab = { · 32 unmodified lines |
| 2978 | 'punctuation': /\.{3}|[.,;\[\](){}!]/ | 3221 | 'punctuation': /\.{3}|[.,;\[\](){}!]/ |
| 2979 | }; | 3222 | }; |
| 2980 | | 3223 | |
| 2981 | Prism.languages.nginx = Prism.languages.extend('clike', { | 3224 | (function (Prism) { |
| 2982 | 'comment': { | | |
| 2983 | pattern: /(^|[^"{\\])#.*/, | | |
| 2984 | lookbehind: true | | |
| 2985 | }, | | |
| 2986 | 'keyword': /\b(?:CONTENT_|DOCUMENT_|GATEWAY_|HTTP_|HTTPS|if_not_empty|PATH_|QUERY_|REDIRECT_|REMOTE_|REQUEST_|SCGI|SCRIPT_|SERVER_|http|events|accept_mutex|accept_mutex_delay|access_log|add_after_body|add_before_body|add_header|addition_types|aio|alias|allow|ancient_browser|ancient_browser_value|auth|auth_basic|auth_basic_user_file|auth_http|auth_http_header|auth_http_timeout|autoindex|autoindex_exact_size|autoindex_localtime|break|charset|charset_map|charset_types|chunked_transfer_encoding|client_body_buffer_size|client_body_in_file_only|client_body_in_single_buffer|client_body_temp_path|client_body_timeout|client_header_buffer_size|client_header_timeout|client_max_body_size|connection_pool_size|create_full_put_path|daemon|dav_access|dav_methods|debug_connection|debug_points|default_type|deny|devpoll_changes|devpoll_events|directio|directio_alignment|disable_symlinks|empty_gif|env|epoll_events|error_log|error_page|expires|fastcgi_buffer_size|fastcgi_buffers|fastcgi_busy_buffers_size|fastcgi_cache|fastcgi_cache_bypass|fastcgi_cache_key|fastcgi_cache_lock|fastcgi_cache_lock_timeout|fastcgi_cache_methods|fastcgi_cache_min_uses|fastcgi_cache_path|fastcgi_cache_purge|fastcgi_cache_use_stale|fastcgi_cache_valid|fastcgi_connect_timeout|fastcgi_hide_header|fastcgi_ignore_client_abort|fastcgi_ignore_headers|fastcgi_index|fastcgi_intercept_errors|fastcgi_keep_conn|fastcgi_max_temp_file_size|fastcgi_next_upstream|fastcgi_no_cache|fastcgi_param|fastcgi_pass|fastcgi_pass_header|fastcgi_read_timeout|fastcgi_redirect_errors|fastcgi_send_timeout|fastcgi_split_path_info|fastcgi_store|fastcgi_store_access|fastcgi_temp_file_write_size|fastcgi_temp_path|flv|geo|geoip_city|geoip_country|google_perftools_profiles|gzip|gzip_buffers|gzip_comp_level|gzip_disable|gzip_http_version|gzip_min_length|gzip_proxied|gzip_static|gzip_types|gzip_vary|if|if_modified_since|ignore_invalid_headers|image_filter|image_filter_buffer|image_filter_jpeg_quality|image_filter_sharpen|image_filter_transparency|imap_capabilities|imap_client_buffer|include|index|internal|ip_hash|keepalive|keepalive_disable|keepalive_requests|keepalive_timeout|kqueue_changes|kqueue_events|large_client_header_buffers|limit_conn|limit_conn_log_level|limit_conn_zone|limit_except|limit_rate|limit_rate_after|limit_req|limit_req_log_level|limit_req_zone|limit_zone|lingering_close|lingering_time|lingering_timeout|listen|location|lock_file|log_format|log_format_combined|log_not_found|log_subrequest|map|map_hash_bucket_size|map_hash_max_size|master_process|max_ranges|memcached_buffer_size|memcached_connect_timeout|memcached_next_upstream|memcached_pass|memcached_read_timeout|memcached_send_timeout|merge_slashes|min_delete_depth|modern_browser|modern_browser_value|mp4|mp4_buffer_size|mp4_max_buffer_size|msie_padding|msie_refresh|multi_accept|open_file_cache|open_file_cache_errors|open_file_cache_min_uses|open_file_cache_valid|open_log_file_cache|optimize_server_names|override_charset|pcre_jit|perl|perl_modules|perl_require|perl_set|pid|pop3_auth|pop3_capabilities|port_in_redirect|post_action|postpone_output|protocol|proxy|proxy_buffer|proxy_buffer_size|proxy_buffering|proxy_buffers|proxy_busy_buffers_size|proxy_cache|proxy_cache_bypass|proxy_cache_key|proxy_cache_lock|proxy_cache_lock_timeout|proxy_cache_methods|proxy_cache_min_uses|proxy_cache_path|proxy_cache_use_stale|proxy_cache_valid|proxy_connect_timeout|proxy_cookie_domain|proxy_cookie_path|proxy_headers_hash_bucket_size|proxy_headers_hash_max_size|proxy_hide_header|proxy_http_version|proxy_ignore_client_abort|proxy_ignore_headers|proxy_intercept_errors|proxy_max_temp_file_size|proxy_method|proxy_next_upstream|proxy_no_cache|proxy_pass|proxy_pass_error_message|proxy_pass_header|proxy_pass_request_body|proxy_pass_request_headers|proxy_read_timeout|proxy_redirect|proxy_redirect_errors|proxy_send_lowat|proxy_send_timeout|proxy_set_body|proxy_set_header|proxy_ssl_session_reuse|proxy_store|proxy_store_access|proxy_temp_file_write_size|proxy_temp_path|proxy_timeout|proxy_upstream_fail_timeout|proxy_upstream_max_fails|random_index|read_ahead|real_ip_header|recursive_error_pages|request_pool_size|reset_timedout_connection|resolver|resolver_timeout|return|rewrite|root|rtsig_overflow_events|rtsig_overflow_test|rtsig_overflow_threshold|rtsig_signo|satisfy|satisfy_any|secure_link_secret|send_lowat|send_timeout|sendfile|sendfile_max_chunk|server|server_name|server_name_in_redirect|server_names_hash_bucket_size|server_names_hash_max_size|server_tokens|set|set_real_ip_from|smtp_auth|smtp_capabilities|so_keepalive|source_charset|split_clients|ssi|ssi_silent_errors|ssi_types|ssi_value_length|ssl|ssl_certificate|ssl_certificate_key|ssl_ciphers|ssl_client_certificate|ssl_crl|ssl_dhparam|ssl_engine|ssl_prefer_server_ciphers|ssl_protocols|ssl_session_cache|ssl_session_timeout|ssl_verify_client|ssl_verify_depth|starttls|stub_status|sub_filter|sub_filter_once|sub_filter_types|tcp_nodelay|tcp_nopush|timeout|timer_resolution|try_files|types|types_hash_bucket_size|types_hash_max_size|underscores_in_headers|uninitialized_variable_warn|upstream|use|user|userid|userid_domain|userid_expires|userid_name|userid_p3p|userid_path|userid_service|valid_referers|variables_hash_bucket_size|variables_hash_max_size|worker_connections|worker_cpu_affinity|worker_priority|worker_processes|worker_rlimit_core|worker_rlimit_nofile|worker_rlimit_sigpending|working_directory|xclient|xml_entities|xslt_entities|xslt_stylesheet|xslt_types|ssl_session_tickets|ssl_stapling|ssl_stapling_verify|ssl_ecdh_curve|ssl_trusted_certificate|more_set_headers|ssl_early_data)\b/i | | |
| 2987 | }); | | |
| 2988 | | 3225 | |
| 2989 | Prism.languages.insertBefore('nginx', 'keyword', { | 3226 | var variable = /\$(?:\w[a-z\d]*(?:_[^\x00-\x1F\s"'\\()$]*)?|\{[^}\s"'\\]+\})/i; |
| 2990 | 'variable': /\$[a-z_]+/i | 3227 | |
| 2991 | }); | 3228 | Prism.languages.nginx = { |
| | 3229 | 'comment': { |
| | 3230 | pattern: /(^|[\s{};])#.*/, |
| | 3231 | lookbehind: true |
| | 3232 | }, |
| | 3233 | 'directive': { |
| | 3234 | pattern: /(^|\s)\w(?:[^;{}"'\\\s]|\\.|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\s+(?:#.*(?!.)|(?![#\s])))*?(?=\s*[;{])/, |
| | 3235 | lookbehind: true, |
| | 3236 | greedy: true, |
| | 3237 | inside: { |
| | 3238 | 'string': { |
| | 3239 | pattern: /((?:^|[^\\])(?:\\\\)*)(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/, |
| | 3240 | lookbehind: true, |
| | 3241 | inside: { |
| | 3242 | 'escape': { |
| | 3243 | pattern: /\\["'\\nrt]/, |
| | 3244 | alias: 'entity' |
| | 3245 | }, |
| | 3246 | 'variable': variable |
| | 3247 | } |
| | 3248 | }, |
| | 3249 | 'comment': { |
| | 3250 | pattern: /(\s)#.*/, |
| | 3251 | lookbehind: true, |
| | 3252 | greedy: true |
| | 3253 | }, |
| | 3254 | 'keyword': { |
| | 3255 | pattern: /^\S+/, |
| | 3256 | greedy: true |
| | 3257 | }, |
| | 3258 | |
| | 3259 | // other patterns |
| | 3260 | |
| | 3261 | 'boolean': { |
| | 3262 | pattern: /(\s)(?:off|on)(?!\S)/, |
| | 3263 | lookbehind: true |
| | 3264 | }, |
| | 3265 | 'number': { |
| | 3266 | pattern: /(\s)\d+[a-z]*(?!\S)/i, |
| | 3267 | lookbehind: true |
| | 3268 | }, |
| | 3269 | 'variable': variable |
| | 3270 | } |
| | 3271 | }, |
| | 3272 | 'punctuation': /[{};]/ |
| | 3273 | }; |
| | 3274 | |
| | 3275 | }(Prism)); |
| 2992 | | 3276 | |
| 2993 | Prism.languages.nim = { | 3277 | Prism.languages.nim = { |
| 2994 | 'comment': /#.*/, | 3278 | 'comment': /#.*/, |
| @@ -3023,6 +3307,7 @@ Prism.languages.nim = { · 28 unmodified lines |
| 3023 | }, | 3307 | }, |
| 3024 | 'punctuation': /[({\[]\.|\.[)}\]]|[`(){}\[\],:]/ | 3308 | 'punctuation': /[({\[]\.|\.[)}\]]|[`(){}\[\],:]/ |
| 3025 | }; | 3309 | }; |
| | 3310 | |
| 3026 | Prism.languages.ocaml = { | 3311 | Prism.languages.ocaml = { |
| 3027 | 'comment': /\(\*[\s\S]*?\*\)/, | 3312 | 'comment': /\(\*[\s\S]*?\*\)/, |
| 3028 | 'string': [ | 3313 | 'string': [ |
| @@ -3228,7 +3513,7 @@ Prism.languages.perl = { · 199 unmodified lines |
| 3228 | // ${...} | 3513 | // ${...} |
| 3229 | /[&*$@%]#?(?=\{)/, | 3514 | /[&*$@%]#?(?=\{)/, |
| 3230 | // $foo | 3515 | // $foo |
| 3231 | /[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+)+(?:::)*/i, | 3516 | /[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+(?![\w$]))+(?:::)*/i, |
| 3232 | // $1 | 3517 | // $1 |
| 3233 | /[&*$@%]\d+/, | 3518 | /[&*$@%]\d+/, |
| 3234 | // $_, @_, %! | 3519 | // $_, @_, %! |
| @@ -3271,8 +3556,18 @@ Prism.languages.perl = { · 36 unmodified lines |
| 3271 | pattern: /\b(?:false|true)\b/i, | 3556 | pattern: /\b(?:false|true)\b/i, |
| 3272 | alias: 'boolean' | 3557 | alias: 'boolean' |
| 3273 | }, | 3558 | }, |
| 3274 | /\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/, | 3559 | { |
| | 3560 | pattern: /(::\s*)\b[a-z_]\w*\b(?!\s*\()/i, |
| | 3561 | greedy: true, |
| | 3562 | lookbehind: true, |
| | 3563 | }, |
| | 3564 | { |
| | 3565 | pattern: /(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i, |
| | 3566 | greedy: true, |
| | 3567 | lookbehind: true, |
| | 3568 | }, |
| 3275 | /\b(?:null)\b/i, | 3569 | /\b(?:null)\b/i, |
| | 3570 | /\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/, |
| 3276 | ]; | 3571 | ]; |
| 3277 | var number = /\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i; | 3572 | var number = /\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i; |
| 3278 | var operator = /<?=>|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/; | 3573 | var operator = /<?=>|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/; |
| @@ -3297,6 +3592,11 @@ Prism.languages.perl = { · 18 unmodified lines |
| 3297 | lookbehind: true, | 3592 | lookbehind: true, |
| 3298 | alias: 'class-name' | 3593 | alias: 'class-name' |
| 3299 | }, | 3594 | }, |
| | 3595 | 'function-definition': { |
| | 3596 | pattern: /(\bfunction\s+)[a-z_]\w*(?=\s*\()/i, |
| | 3597 | lookbehind: true, |
| | 3598 | alias: 'function' |
| | 3599 | }, |
| 3300 | 'keyword': [ | 3600 | 'keyword': [ |
| 3301 | { | 3601 | { |
| 3302 | pattern: /(\(\s*)\b(?:bool|boolean|int|integer|float|string|object|array)\b(?=\s*\))/i, | 3602 | pattern: /(\(\s*)\b(?:bool|boolean|int|integer|float|string|object|array)\b(?=\s*\))/i, |
| @@ -3344,9 +3644,26 @@ Prism.languages.perl = { · 41 unmodified lines |
| 3344 | alias: 'static-context', | 3644 | alias: 'static-context', |
| 3345 | greedy: true | 3645 | greedy: true |
| 3346 | }, | 3646 | }, |
| 3347 | /\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|match|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i | 3647 | { |
| | 3648 | // yield from |
| | 3649 | pattern: /(\byield\s+)from\b/i, |
| | 3650 | lookbehind: true |
| | 3651 | }, |
| | 3652 | // `class` is always a keyword unlike other keywords |
| | 3653 | /\bclass\b/i, |
| | 3654 | { |
| | 3655 | // https://www.php.net/manual/en/reserved.keywords.php |
| | 3656 | // |
| | 3657 | // keywords cannot be preceded by "->" |
| | 3658 | // the complex lookbehind means `(?<!(?:->|::)\s*)` |
| | 3659 | pattern: /((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|match|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i, |
| | 3660 | lookbehind: true |
| | 3661 | } |
| 3348 | ], | 3662 | ], |
| 3349 | 'argument-name': /\b[a-z_]\w*(?=\s*:(?!:))/i, | 3663 | 'argument-name': { |
| | 3664 | pattern: /([(,]\s+)\b[a-z_]\w*(?=\s*:(?!:))/i, |
| | 3665 | lookbehind: true |
| | 3666 | }, |
| 3350 | 'class-name': [ | 3667 | 'class-name': [ |
| 3351 | { | 3668 | { |
| 3352 | pattern: /(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i, | 3669 | pattern: /(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i, |
| @@ -3446,9 +3763,15 @@ Prism.languages.perl = { · 93 unmodified lines |
| 3446 | } | 3763 | } |
| 3447 | ], | 3764 | ], |
| 3448 | 'constant': constant, | 3765 | 'constant': constant, |
| 3449 | 'function': /\w+\s*(?=\()/, | 3766 | 'function': { |
| | 3767 | pattern: /(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i, |
| | 3768 | lookbehind: true, |
| | 3769 | inside: { |
| | 3770 | 'punctuation': /\\/ |
| | 3771 | } |
| | 3772 | }, |
| 3450 | 'property': { | 3773 | 'property': { |
| 3451 | pattern: /(->)[\w]+/, | 3774 | pattern: /(->\s*)\w+/, |
| 3452 | lookbehind: true | 3775 | lookbehind: true |
| 3453 | }, | 3776 | }, |
| 3454 | 'number': number, | 3777 | 'number': number, |
| @@ -3457,7 +3780,7 @@ Prism.languages.perl = { · 2 unmodified lines |
| 3457 | }; | 3780 | }; |
| 3458 | | 3781 | |
| 3459 | var string_interpolation = { | 3782 | var string_interpolation = { |
| 3460 | pattern: /{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)*)/, | 3783 | pattern: /{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/, |
| 3461 | lookbehind: true, | 3784 | lookbehind: true, |
| 3462 | inside: Prism.languages.php | 3785 | inside: Prism.languages.php |
| 3463 | }; | 3786 | }; |
| @@ -3489,7 +3812,7 @@ Prism.languages.perl = { · 25 unmodified lines |
| 3489 | 'punctuation': /^<<<"?|[";]$/ | 3812 | 'punctuation': /^<<<"?|[";]$/ |
| 3490 | } | 3813 | } |
| 3491 | }, | 3814 | }, |
| 3492 | 'interpolation': string_interpolation // See below | 3815 | 'interpolation': string_interpolation |
| 3493 | } | 3816 | } |
| 3494 | }, | 3817 | }, |
| 3495 | { | 3818 | { |
| @@ -3507,16 +3830,13 @@ Prism.languages.perl = { · 11 unmodified lines |
| 3507 | alias: 'double-quoted-string', | 3830 | alias: 'double-quoted-string', |
| 3508 | greedy: true, | 3831 | greedy: true, |
| 3509 | inside: { | 3832 | inside: { |
| 3510 | 'interpolation': string_interpolation // See below | 3833 | 'interpolation': string_interpolation |
| 3511 | } | 3834 | } |
| 3512 | } | 3835 | } |
| 3513 | ]; | 3836 | ]; |
| 3514 | | 3837 | |
| 3515 | Prism.languages.insertBefore('php', 'variable', { | 3838 | Prism.languages.insertBefore('php', 'variable', { |
| 3516 | 'string': string, | 3839 | 'string': string, |
| 3517 | }); | | |
| 3518 | | | |
| 3519 | Prism.languages.insertBefore('php', 'variable', { | | |
| 3520 | 'attribute': { | 3840 | 'attribute': { |
| 3521 | pattern: /#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/mi, | 3841 | pattern: /#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/mi, |
| 3522 | greedy: true, | 3842 | greedy: true, |
| @@ -3562,7 +3882,7 @@ Prism.languages.perl = { · 39 unmodified lines |
| 3562 | }, | 3882 | }, |
| 3563 | }); | 3883 | }); |
| 3564 | | 3884 | |
| 3565 | Prism.hooks.add('before-tokenize', function(env) { | 3885 | Prism.hooks.add('before-tokenize', function (env) { |
| 3566 | if (!/<\?/.test(env.code)) { | 3886 | if (!/<\?/.test(env.code)) { |
| 3567 | return; | 3887 | return; |
| 3568 | } | 3888 | } |
| @@ -3571,7 +3891,7 @@ Prism.languages.perl = { · 2 unmodified lines |
| 3571 | Prism.languages['markup-templating'].buildPlaceholders(env, 'php', phpPattern); | 3891 | Prism.languages['markup-templating'].buildPlaceholders(env, 'php', phpPattern); |
| 3572 | }); | 3892 | }); |
| 3573 | | 3893 | |
| 3574 | Prism.hooks.add('after-tokenize', function(env) { | 3894 | Prism.hooks.add('after-tokenize', function (env) { |
| 3575 | Prism.languages['markup-templating'].tokenizePlaceholders(env, 'php'); | 3895 | Prism.languages['markup-templating'].tokenizePlaceholders(env, 'php'); |
| 3576 | }); | 3896 | }); |
| 3577 | | 3897 | |
| @@ -3642,149 +3962,149 @@ Prism.languages.python['string-interpolation'].inside['interpolation'].inside.re · 64 unmodified lines |
| 3642 | | 3962 | |
| 3643 | Prism.languages.py = Prism.languages.python; | 3963 | Prism.languages.py = Prism.languages.python; |
| 3644 | | 3964 | |
| 3645 | (function(Prism) { | 3965 | (function (Prism) { |
| 3646 | | 3966 | |
| 3647 | var javascript = Prism.util.clone(Prism.languages.javascript); | 3967 | var javascript = Prism.util.clone(Prism.languages.javascript); |
| 3648 | | 3968 | |
| 3649 | var space = /(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source; | 3969 | var space = /(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source; |
| 3650 | var braces = /(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source; | 3970 | var braces = /(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source; |
| 3651 | var spread = /(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source; | 3971 | var spread = /(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source; |
| 3652 | | 3972 | |
| 3653 | /** | 3973 | /** |
| 3654 | * @param {string} source | 3974 | * @param {string} source |
| 3655 | * @param {string} [flags] | 3975 | * @param {string} [flags] |
| 3656 | */ | 3976 | */ |
| 3657 | function re(source, flags) { | 3977 | function re(source, flags) { |
| 3658 | source = source | 3978 | source = source |
| 3659 | .replace(/<S>/g, function () { return space; }) | 3979 | .replace(/<S>/g, function () { return space; }) |
| 3660 | .replace(/<BRACES>/g, function () { return braces; }) | 3980 | .replace(/<BRACES>/g, function () { return braces; }) |
| 3661 | .replace(/<SPREAD>/g, function () { return spread; }); | 3981 | .replace(/<SPREAD>/g, function () { return spread; }); |
| 3662 | return RegExp(source, flags); | 3982 | return RegExp(source, flags); |
| 3663 | } | 3983 | } |
| 3664 | | 3984 | |
| 3665 | spread = re(spread).source; | 3985 | spread = re(spread).source; |
| 3666 | | 3986 | |
| 3667 | | 3987 | |
| 3668 | Prism.languages.jsx = Prism.languages.extend('markup', javascript); | 3988 | Prism.languages.jsx = Prism.languages.extend('markup', javascript); |
| 3669 | Prism.languages.jsx.tag.pattern = re( | 3989 | Prism.languages.jsx.tag.pattern = re( |
| 3670 | /<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[^]|[^\\"])*"|'(?:\\[^]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source | 3990 | /<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[^]|[^\\"])*"|'(?:\\[^]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source |
| 3671 | ); | 3991 | ); |
| 3672 | | 3992 | |
| 3673 | Prism.languages.jsx.tag.inside['tag'].pattern = /^<\/?[^\s>\/]*/i; | 3993 | Prism.languages.jsx.tag.inside['tag'].pattern = /^<\/?[^\s>\/]*/i; |
| 3674 | Prism.languages.jsx.tag.inside['attr-value'].pattern = /=(?!\{)(?:"(?:\\[^]|[^\\"])*"|'(?:\\[^]|[^\\'])*'|[^\s'">]+)/i; | 3994 | Prism.languages.jsx.tag.inside['attr-value'].pattern = /=(?!\{)(?:"(?:\\[^]|[^\\"])*"|'(?:\\[^]|[^\\'])*'|[^\s'">]+)/i; |
| 3675 | Prism.languages.jsx.tag.inside['tag'].inside['class-name'] = /^[A-Z]\w*(?:\.[A-Z]\w*)*$/; | 3995 | Prism.languages.jsx.tag.inside['tag'].inside['class-name'] = /^[A-Z]\w*(?:\.[A-Z]\w*)*$/; |
| 3676 | Prism.languages.jsx.tag.inside['comment'] = javascript['comment']; | 3996 | Prism.languages.jsx.tag.inside['comment'] = javascript['comment']; |
| 3677 | | 3997 | |
| 3678 | Prism.languages.insertBefore('inside', 'attr-name', { | 3998 | Prism.languages.insertBefore('inside', 'attr-name', { |
| 3679 | 'spread': { | 3999 | 'spread': { |
| 3680 | pattern: re(/<SPREAD>/.source), | 4000 | pattern: re(/<SPREAD>/.source), |
| 3681 | inside: Prism.languages.jsx | 4001 | inside: Prism.languages.jsx |
| 3682 | } | 4002 | } |
| 3683 | }, Prism.languages.jsx.tag); | 4003 | }, Prism.languages.jsx.tag); |
| 3684 | | 4004 | |
| 3685 | Prism.languages.insertBefore('inside', 'attr-value',{ | 4005 | Prism.languages.insertBefore('inside', 'special-attr', { |
| 3686 | 'script': { | 4006 | 'script': { |
| 3687 | // Allow for two levels of nesting | 4007 | // Allow for two levels of nesting |
| 3688 | pattern: re(/=<BRACES>/.source), | 4008 | pattern: re(/=<BRACES>/.source), |
| 3689 | inside: { | 4009 | inside: { |
| 3690 | 'script-punctuation': { | 4010 | 'script-punctuation': { |
| 3691 | pattern: /^=(?={)/, | 4011 | pattern: /^=(?={)/, |
| 3692 | alias: 'punctuation' | 4012 | alias: 'punctuation' |
| | 4013 | }, |
| | 4014 | rest: Prism.languages.jsx |
| 3693 | }, | 4015 | }, |
| 3694 | rest: Prism.languages.jsx | 4016 | 'alias': 'language-javascript' |
| 3695 | }, | 4017 | } |
| 3696 | 'alias': 'language-javascript' | 4018 | }, Prism.languages.jsx.tag); |
| 3697 | } | | |
| 3698 | }, Prism.languages.jsx.tag); | | |
| 3699 | | 4019 | |
| 3700 | // The following will handle plain text inside tags | 4020 | // The following will handle plain text inside tags |
| 3701 | var stringifyToken = function (token) { | 4021 | var stringifyToken = function (token) { |
| 3702 | if (!token) { | 4022 | if (!token) { |
| 3703 | return ''; | 4023 | return ''; |
| 3704 | } | 4024 | } |
| 3705 | if (typeof token === 'string') { | 4025 | if (typeof token === 'string') { |
| 3706 | return token; | 4026 | return token; |
| 3707 | } | 4027 | } |
| 3708 | if (typeof token.content === 'string') { | 4028 | if (typeof token.content === 'string') { |
| 3709 | return token.content; | 4029 | return token.content; |
| 3710 | } | 4030 | } |
| 3711 | return token.content.map(stringifyToken).join(''); | 4031 | return token.content.map(stringifyToken).join(''); |
| 3712 | }; | 4032 | }; |
| 3713 | | 4033 | |
| 3714 | var walkTokens = function (tokens) { | 4034 | var walkTokens = function (tokens) { |
| 3715 | var openedTags = []; | 4035 | var openedTags = []; |
| 3716 | for (var i = 0; i < tokens.length; i++) { | 4036 | for (var i = 0; i < tokens.length; i++) { |
| 3717 | var token = tokens[i]; | 4037 | var token = tokens[i]; |
| 3718 | var notTagNorBrace = false; | 4038 | var notTagNorBrace = false; |
| 3719 | | 4039 | |
| 3720 | if (typeof token !== 'string') { | 4040 | if (typeof token !== 'string') { |
| 3721 | if (token.type === 'tag' && token.content[0] && token.content[0].type === 'tag') { | 4041 | if (token.type === 'tag' && token.content[0] && token.content[0].type === 'tag') { |
| 3722 | // We found a tag, now find its kind | 4042 | // We found a tag, now find its kind |
| 3723 | | 4043 | |
| 3724 | if (token.content[0].content[0].content === '</') { | 4044 | if (token.content[0].content[0].content === '</') { |
| 3725 | // Closing tag | 4045 | // Closing tag |
| 3726 | if (openedTags.length > 0 && openedTags[openedTags.length - 1].tagName === stringifyToken(token.content[0].content[1])) { | 4046 | if (openedTags.length > 0 && openedTags[openedTags.length - 1].tagName === stringifyToken(token.content[0].content[1])) { |
| 3727 | // Pop matching opening tag | 4047 | // Pop matching opening tag |
| 3728 | openedTags.pop(); | 4048 | openedTags.pop(); |
| 3729 | } | 4049 | } |
| 3730 | } else { | | |
| 3731 | if (token.content[token.content.length - 1].content === '/>') { | | |
| 3732 | // Autoclosed tag, ignore | | |
| 3733 | } else { | 4050 | } else { |
| 3734 | // Opening tag | 4051 | if (token.content[token.content.length - 1].content === '/>') { |
| 3735 | openedTags.push({ | 4052 | // Autoclosed tag, ignore |
| 3736 | tagName: stringifyToken(token.content[0].content[1]), | 4053 | } else { |
| 3737 | openedBraces: 0 | 4054 | // Opening tag |
| 3738 | }); | 4055 | openedTags.push({ |
| | 4056 | tagName: stringifyToken(token.content[0].content[1]), |
| | 4057 | openedBraces: 0 |
| | 4058 | }); |
| | 4059 | } |
| 3739 | } | 4060 | } |
| 3740 | } | 4061 | } else if (openedTags.length > 0 && token.type === 'punctuation' && token.content === '{') { |
| 3741 | } else if (openedTags.length > 0 && token.type === 'punctuation' && token.content === '{') { | | |
| 3742 | | 4062 | |
| 3743 | // Here we might have entered a JSX context inside a tag | 4063 | // Here we might have entered a JSX context inside a tag |
| 3744 | openedTags[openedTags.length - 1].openedBraces++; | 4064 | openedTags[openedTags.length - 1].openedBraces++; |
| 3745 | | 4065 | |
| 3746 | } else if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces > 0 && token.type === 'punctuation' && token.content === '}') { | 4066 | } else if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces > 0 && token.type === 'punctuation' && token.content === '}') { |
| 3747 | | 4067 | |
| 3748 | // Here we might have left a JSX context inside a tag | 4068 | // Here we might have left a JSX context inside a tag |
| 3749 | openedTags[openedTags.length - 1].openedBraces--; | 4069 | openedTags[openedTags.length - 1].openedBraces--; |
| 3750 | | 4070 | |
| 3751 | } else { | 4071 | } else { |
| 3752 | notTagNorBrace = true | 4072 | notTagNorBrace = true; |
| 3753 | } | | |
| 3754 | } | | |
| 3755 | if (notTagNorBrace || typeof token === 'string') { | | |
| 3756 | if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces === 0) { | | |
| 3757 | // Here we are inside a tag, and not inside a JSX context. | | |
| 3758 | // That's plain text: drop any tokens matched. | | |
| 3759 | var plainText = stringifyToken(token); | | |
| 3760 | | | |
| 3761 | // And merge text with adjacent text | | |
| 3762 | if (i < tokens.length - 1 && (typeof tokens[i + 1] === 'string' || tokens[i + 1].type === 'plain-text')) { | | |
| 3763 | plainText += stringifyToken(tokens[i + 1]); | | |
| 3764 | tokens.splice(i + 1, 1); | | |
| 3765 | } | 4073 | } |
| 3766 | if (i > 0 && (typeof tokens[i - 1] === 'string' || tokens[i - 1].type === 'plain-text')) { | 4074 | } |
| 3767 | plainText = stringifyToken(tokens[i - 1]) + plainText; | 4075 | if (notTagNorBrace || typeof token === 'string') { |
| 3768 | tokens.splice(i - 1, 1); | 4076 | if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces === 0) { |
| 3769 | i--; | 4077 | // Here we are inside a tag, and not inside a JSX context. |
| | 4078 | // That's plain text: drop any tokens matched. |
| | 4079 | var plainText = stringifyToken(token); |
| | 4080 | |
| | 4081 | // And merge text with adjacent text |
| | 4082 | if (i < tokens.length - 1 && (typeof tokens[i + 1] === 'string' || tokens[i + 1].type === 'plain-text')) { |
| | 4083 | plainText += stringifyToken(tokens[i + 1]); |
| | 4084 | tokens.splice(i + 1, 1); |
| | 4085 | } |
| | 4086 | if (i > 0 && (typeof tokens[i - 1] === 'string' || tokens[i - 1].type === 'plain-text')) { |
| | 4087 | plainText = stringifyToken(tokens[i - 1]) + plainText; |
| | 4088 | tokens.splice(i - 1, 1); |
| | 4089 | i--; |
| | 4090 | } |
| | 4091 | |
| | 4092 | tokens[i] = new Prism.Token('plain-text', plainText, null, plainText); |
| 3770 | } | 4093 | } |
| | 4094 | } |
| 3771 | | 4095 | |
| 3772 | tokens[i] = new Prism.Token('plain-text', plainText, null, plainText); | 4096 | if (token.content && typeof token.content !== 'string') { |
| | 4097 | walkTokens(token.content); |
| 3773 | } | 4098 | } |
| 3774 | } | 4099 | } |
| | 4100 | }; |
| 3775 | | 4101 | |
| 3776 | if (token.content && typeof token.content !== 'string') { | 4102 | Prism.hooks.add('after-tokenize', function (env) { |
| 3777 | walkTokens(token.content); | 4103 | if (env.language !== 'jsx' && env.language !== 'tsx') { |
| | 4104 | return; |
| 3778 | } | 4105 | } |
| 3779 | } | 4106 | walkTokens(env.tokens); |
| 3780 | }; | 4107 | }); |
| 3781 | | | |
| 3782 | Prism.hooks.add('after-tokenize', function (env) { | | |
| 3783 | if (env.language !== 'jsx' && env.language !== 'tsx') { | | |
| 3784 | return; | | |
| 3785 | } | | |
| 3786 | walkTokens(env.tokens); | | |
| 3787 | }); | | |
| 3788 | | 4108 | |
| 3789 | }(Prism)); | 4109 | }(Prism)); |
| 3790 | | 4110 | |
| @@ -4007,17 +4327,26 @@ Prism.languages.scss['atrule'].inside.rest = Prism.languages.scss; · 216 unmodified lines |
| 4007 | | 4327 | |
| 4008 | var strings = [ | 4328 | var strings = [ |
| 4009 | // normal string | 4329 | // normal string |
| 4010 | // 1 capturing group | 4330 | /"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/.source, |
| 4011 | /(["'])(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|(?!\1)[^\\`$])*\1/.source, | 4331 | /'[^']*'/.source, |
| | 4332 | /\$'(?:[^'\\]|\\[\s\S])*'/.source, |
| 4012 | | 4333 | |
| 4013 | // here doc | 4334 | // here doc |
| 4014 | // 2 capturing groups | 4335 | // 2 capturing groups |
| 4015 | /<<-?\s*(["']?)(\w+)\2\s[\s\S]*?[\r\n]\3/.source | 4336 | /<<-?\s*(["']?)(\w+)\1\s[\s\S]*?[\r\n]\2/.source |
| 4016 | ].join('|'); | 4337 | ].join('|'); |
| 4017 | | 4338 | |
| 4018 | Prism.languages['shell-session'] = { | 4339 | Prism.languages['shell-session'] = { |
| 4019 | 'command': { | 4340 | 'command': { |
| 4020 | pattern: RegExp(/^(?:[^\s@:$#*!/\\]+@[^\s@:$#*!/\\]+(?::[^\0-\x1F$#*?"<>:;|]+)?|[^\0-\x1F$#*?"<>:;|]+)?[$#](?:[^\\\r\n'"<]|\\.|<<str>>)+/.source.replace(/<<str>>/g, function () { return strings; }), 'm'), | 4341 | pattern: RegExp( |
| | 4342 | // user info |
| | 4343 | /^(?:[^\s@:$#*!/\\]+@[^\s@:$#*!/\\]+(?::[^\0-\x1F$#*?"<>:;|]+)?|[^\0-\x1F$#*?"<>:;|]+)?/.source + |
| | 4344 | // shell symbol |
| | 4345 | /[$#]/.source + |
| | 4346 | // bash command |
| | 4347 | /(?:[^\\\r\n'"<$]|\\(?:[^\r]|\r\n?)|\$(?!')|<<str>>)+/.source.replace(/<<str>>/g, function () { return strings; }), |
| | 4348 | 'm' |
| | 4349 | ), |
| 4021 | greedy: true, | 4350 | greedy: true, |
| 4022 | inside: { | 4351 | inside: { |
| 4023 | 'info': { | 4352 | 'info': { |
| @@ -4085,11 +4414,16 @@ Prism.languages.sql = { · 61 unmodified lines |
| 4085 | greedy: true, | 4414 | greedy: true, |
| 4086 | inside: null // see below | 4415 | inside: null // see below |
| 4087 | }, | 4416 | }, |
| 4088 | // From JavaScript Prism keyword list and TypeScript language spec: https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#221-reserved-words | | |
| 4089 | 'keyword': /\b(?:abstract|as|asserts|async|await|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|is|keyof|let|module|namespace|new|null|of|package|private|protected|public|readonly|return|require|set|static|super|switch|this|throw|try|type|typeof|undefined|var|void|while|with|yield)\b/, | | |
| 4090 | 'builtin': /\b(?:string|Function|any|number|boolean|Array|symbol|console|Promise|unknown|never)\b/, | 4417 | 'builtin': /\b(?:string|Function|any|number|boolean|Array|symbol|console|Promise|unknown|never)\b/, |
| 4091 | }); | 4418 | }); |
| 4092 | | 4419 | |
| | 4420 | // The keywords TypeScript adds to JavaScript |
| | 4421 | Prism.languages.typescript.keyword.push( |
| | 4422 | /\b(?:abstract|as|declare|implements|is|keyof|readonly|require)\b/, |
| | 4423 | // keywords that have to be followed by an identifier |
| | 4424 | /\b(?:asserts|infer|interface|module|namespace|type)(?!\s*[^\s_${}*a-zA-Z\xA0-\uFFFF])/ |
| | 4425 | ); |
| | 4426 | |
| 4093 | // doesn't work with TS because TS is too complex | 4427 | // doesn't work with TS because TS is too complex |
| 4094 | delete Prism.languages.typescript['parameter']; | 4428 | delete Prism.languages.typescript['parameter']; |
| 4095 | | 4429 | |
| @@ -4100,6 +4434,16 @@ Prism.languages.sql = { · 4 unmodified lines |
| 4100 | Prism.languages.typescript['class-name'].inside = typeInside; | 4434 | Prism.languages.typescript['class-name'].inside = typeInside; |
| 4101 | | 4435 | |
| 4102 | Prism.languages.insertBefore('typescript', 'function', { | 4436 | Prism.languages.insertBefore('typescript', 'function', { |
| | 4437 | 'decorator': { |
| | 4438 | pattern: /@[$\w\xA0-\uFFFF]+/, |
| | 4439 | inside: { |
| | 4440 | 'at': { |
| | 4441 | pattern: /^@/, |
| | 4442 | alias: 'operator' |
| | 4443 | }, |
| | 4444 | 'function': /^[\s\S]+/ |
| | 4445 | } |
| | 4446 | }, |
| 4103 | 'generic-function': { | 4447 | 'generic-function': { |
| 4104 | // e.g. foo<T extends "bar" | "baz">( ... | 4448 | // e.g. foo<T extends "bar" | "baz">( ... |
| 4105 | pattern: /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/, | 4449 | pattern: /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/, |
| @@ -4146,7 +4490,7 @@ Prism.languages.sql = { · 40 unmodified lines |
| 4146 | flags = (flags || '').replace(/m/g, '') + 'm'; // add m flag | 4490 | flags = (flags || '').replace(/m/g, '') + 'm'; // add m flag |
| 4147 | var pattern = /([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|]|}|(?:[\r\n]\s*)?#))/.source | 4491 | var pattern = /([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|]|}|(?:[\r\n]\s*)?#))/.source |
| 4148 | .replace(/<<prop>>/g, function () { return properties; }).replace(/<<value>>/g, function () { return value; }); | 4492 | .replace(/<<prop>>/g, function () { return properties; }).replace(/<<value>>/g, function () { return value; }); |
| 4149 | return RegExp(pattern, flags) | 4493 | return RegExp(pattern, flags); |
| 4150 | } | 4494 | } |
| 4151 | | 4495 | |
| 4152 | Prism.languages.yaml = { | 4496 | Prism.languages.yaml = { |
| @@ -4202,4 +4546,3 @@ Prism.languages.sql = { · 49 unmodified lines |
| 4202 | Prism.languages.yml = Prism.languages.yaml; | 4546 | Prism.languages.yml = Prism.languages.yaml; |
| 4203 | | 4547 | |
| 4204 | }(Prism)); | 4548 | }(Prism)); |
| 4205 | | | |