Mercurial
comparison third_party/highlight/languages/javascript.js @ 157:2db6253f355d
[ThirdParty] Added highlight library for better readability on blog.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Tue, 13 Jan 2026 19:18:47 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 156:cd35e600ae34 | 157:2db6253f355d |
|---|---|
| 1 /*! `javascript` grammar compiled for Highlight.js 11.11.1 */ | |
| 2 (function(){ | |
| 3 var hljsGrammar = (function () { | |
| 4 'use strict'; | |
| 5 | |
| 6 const IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*'; | |
| 7 const KEYWORDS = [ | |
| 8 "as", // for exports | |
| 9 "in", | |
| 10 "of", | |
| 11 "if", | |
| 12 "for", | |
| 13 "while", | |
| 14 "finally", | |
| 15 "var", | |
| 16 "new", | |
| 17 "function", | |
| 18 "do", | |
| 19 "return", | |
| 20 "void", | |
| 21 "else", | |
| 22 "break", | |
| 23 "catch", | |
| 24 "instanceof", | |
| 25 "with", | |
| 26 "throw", | |
| 27 "case", | |
| 28 "default", | |
| 29 "try", | |
| 30 "switch", | |
| 31 "continue", | |
| 32 "typeof", | |
| 33 "delete", | |
| 34 "let", | |
| 35 "yield", | |
| 36 "const", | |
| 37 "class", | |
| 38 // JS handles these with a special rule | |
| 39 // "get", | |
| 40 // "set", | |
| 41 "debugger", | |
| 42 "async", | |
| 43 "await", | |
| 44 "static", | |
| 45 "import", | |
| 46 "from", | |
| 47 "export", | |
| 48 "extends", | |
| 49 // It's reached stage 3, which is "recommended for implementation": | |
| 50 "using" | |
| 51 ]; | |
| 52 const LITERALS = [ | |
| 53 "true", | |
| 54 "false", | |
| 55 "null", | |
| 56 "undefined", | |
| 57 "NaN", | |
| 58 "Infinity" | |
| 59 ]; | |
| 60 | |
| 61 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects | |
| 62 const TYPES = [ | |
| 63 // Fundamental objects | |
| 64 "Object", | |
| 65 "Function", | |
| 66 "Boolean", | |
| 67 "Symbol", | |
| 68 // numbers and dates | |
| 69 "Math", | |
| 70 "Date", | |
| 71 "Number", | |
| 72 "BigInt", | |
| 73 // text | |
| 74 "String", | |
| 75 "RegExp", | |
| 76 // Indexed collections | |
| 77 "Array", | |
| 78 "Float32Array", | |
| 79 "Float64Array", | |
| 80 "Int8Array", | |
| 81 "Uint8Array", | |
| 82 "Uint8ClampedArray", | |
| 83 "Int16Array", | |
| 84 "Int32Array", | |
| 85 "Uint16Array", | |
| 86 "Uint32Array", | |
| 87 "BigInt64Array", | |
| 88 "BigUint64Array", | |
| 89 // Keyed collections | |
| 90 "Set", | |
| 91 "Map", | |
| 92 "WeakSet", | |
| 93 "WeakMap", | |
| 94 // Structured data | |
| 95 "ArrayBuffer", | |
| 96 "SharedArrayBuffer", | |
| 97 "Atomics", | |
| 98 "DataView", | |
| 99 "JSON", | |
| 100 // Control abstraction objects | |
| 101 "Promise", | |
| 102 "Generator", | |
| 103 "GeneratorFunction", | |
| 104 "AsyncFunction", | |
| 105 // Reflection | |
| 106 "Reflect", | |
| 107 "Proxy", | |
| 108 // Internationalization | |
| 109 "Intl", | |
| 110 // WebAssembly | |
| 111 "WebAssembly" | |
| 112 ]; | |
| 113 | |
| 114 const ERROR_TYPES = [ | |
| 115 "Error", | |
| 116 "EvalError", | |
| 117 "InternalError", | |
| 118 "RangeError", | |
| 119 "ReferenceError", | |
| 120 "SyntaxError", | |
| 121 "TypeError", | |
| 122 "URIError" | |
| 123 ]; | |
| 124 | |
| 125 const BUILT_IN_GLOBALS = [ | |
| 126 "setInterval", | |
| 127 "setTimeout", | |
| 128 "clearInterval", | |
| 129 "clearTimeout", | |
| 130 | |
| 131 "require", | |
| 132 "exports", | |
| 133 | |
| 134 "eval", | |
| 135 "isFinite", | |
| 136 "isNaN", | |
| 137 "parseFloat", | |
| 138 "parseInt", | |
| 139 "decodeURI", | |
| 140 "decodeURIComponent", | |
| 141 "encodeURI", | |
| 142 "encodeURIComponent", | |
| 143 "escape", | |
| 144 "unescape" | |
| 145 ]; | |
| 146 | |
| 147 const BUILT_IN_VARIABLES = [ | |
| 148 "arguments", | |
| 149 "this", | |
| 150 "super", | |
| 151 "console", | |
| 152 "window", | |
| 153 "document", | |
| 154 "localStorage", | |
| 155 "sessionStorage", | |
| 156 "module", | |
| 157 "global" // Node.js | |
| 158 ]; | |
| 159 | |
| 160 const BUILT_INS = [].concat( | |
| 161 BUILT_IN_GLOBALS, | |
| 162 TYPES, | |
| 163 ERROR_TYPES | |
| 164 ); | |
| 165 | |
| 166 /* | |
| 167 Language: JavaScript | |
| 168 Description: JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions. | |
| 169 Category: common, scripting, web | |
| 170 Website: https://developer.mozilla.org/en-US/docs/Web/JavaScript | |
| 171 */ | |
| 172 | |
| 173 | |
| 174 /** @type LanguageFn */ | |
| 175 function javascript(hljs) { | |
| 176 const regex = hljs.regex; | |
| 177 /** | |
| 178 * Takes a string like "<Booger" and checks to see | |
| 179 * if we can find a matching "</Booger" later in the | |
| 180 * content. | |
| 181 * @param {RegExpMatchArray} match | |
| 182 * @param {{after:number}} param1 | |
| 183 */ | |
| 184 const hasClosingTag = (match, { after }) => { | |
| 185 const tag = "</" + match[0].slice(1); | |
| 186 const pos = match.input.indexOf(tag, after); | |
| 187 return pos !== -1; | |
| 188 }; | |
| 189 | |
| 190 const IDENT_RE$1 = IDENT_RE; | |
| 191 const FRAGMENT = { | |
| 192 begin: '<>', | |
| 193 end: '</>' | |
| 194 }; | |
| 195 // to avoid some special cases inside isTrulyOpeningTag | |
| 196 const XML_SELF_CLOSING = /<[A-Za-z0-9\\._:-]+\s*\/>/; | |
| 197 const XML_TAG = { | |
| 198 begin: /<[A-Za-z0-9\\._:-]+/, | |
| 199 end: /\/[A-Za-z0-9\\._:-]+>|\/>/, | |
| 200 /** | |
| 201 * @param {RegExpMatchArray} match | |
| 202 * @param {CallbackResponse} response | |
| 203 */ | |
| 204 isTrulyOpeningTag: (match, response) => { | |
| 205 const afterMatchIndex = match[0].length + match.index; | |
| 206 const nextChar = match.input[afterMatchIndex]; | |
| 207 if ( | |
| 208 // HTML should not include another raw `<` inside a tag | |
| 209 // nested type? | |
| 210 // `<Array<Array<number>>`, etc. | |
| 211 nextChar === "<" || | |
| 212 // the , gives away that this is not HTML | |
| 213 // `<T, A extends keyof T, V>` | |
| 214 nextChar === "," | |
| 215 ) { | |
| 216 response.ignoreMatch(); | |
| 217 return; | |
| 218 } | |
| 219 | |
| 220 // `<something>` | |
| 221 // Quite possibly a tag, lets look for a matching closing tag... | |
| 222 if (nextChar === ">") { | |
| 223 // if we cannot find a matching closing tag, then we | |
| 224 // will ignore it | |
| 225 if (!hasClosingTag(match, { after: afterMatchIndex })) { | |
| 226 response.ignoreMatch(); | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 // `<blah />` (self-closing) | |
| 231 // handled by simpleSelfClosing rule | |
| 232 | |
| 233 let m; | |
| 234 const afterMatch = match.input.substring(afterMatchIndex); | |
| 235 | |
| 236 // some more template typing stuff | |
| 237 // <T = any>(key?: string) => Modify< | |
| 238 if ((m = afterMatch.match(/^\s*=/))) { | |
| 239 response.ignoreMatch(); | |
| 240 return; | |
| 241 } | |
| 242 | |
| 243 // `<From extends string>` | |
| 244 // technically this could be HTML, but it smells like a type | |
| 245 // NOTE: This is ugh, but added specifically for https://github.com/highlightjs/highlight.js/issues/3276 | |
| 246 if ((m = afterMatch.match(/^\s+extends\s+/))) { | |
| 247 if (m.index === 0) { | |
| 248 response.ignoreMatch(); | |
| 249 // eslint-disable-next-line no-useless-return | |
| 250 return; | |
| 251 } | |
| 252 } | |
| 253 } | |
| 254 }; | |
| 255 const KEYWORDS$1 = { | |
| 256 $pattern: IDENT_RE, | |
| 257 keyword: KEYWORDS, | |
| 258 literal: LITERALS, | |
| 259 built_in: BUILT_INS, | |
| 260 "variable.language": BUILT_IN_VARIABLES | |
| 261 }; | |
| 262 | |
| 263 // https://tc39.es/ecma262/#sec-literals-numeric-literals | |
| 264 const decimalDigits = '[0-9](_?[0-9])*'; | |
| 265 const frac = `\\.(${decimalDigits})`; | |
| 266 // DecimalIntegerLiteral, including Annex B NonOctalDecimalIntegerLiteral | |
| 267 // https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals | |
| 268 const decimalInteger = `0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*`; | |
| 269 const NUMBER = { | |
| 270 className: 'number', | |
| 271 variants: [ | |
| 272 // DecimalLiteral | |
| 273 { begin: `(\\b(${decimalInteger})((${frac})|\\.)?|(${frac}))` + | |
| 274 `[eE][+-]?(${decimalDigits})\\b` }, | |
| 275 { begin: `\\b(${decimalInteger})\\b((${frac})\\b|\\.)?|(${frac})\\b` }, | |
| 276 | |
| 277 // DecimalBigIntegerLiteral | |
| 278 { begin: `\\b(0|[1-9](_?[0-9])*)n\\b` }, | |
| 279 | |
| 280 // NonDecimalIntegerLiteral | |
| 281 { begin: "\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b" }, | |
| 282 { begin: "\\b0[bB][0-1](_?[0-1])*n?\\b" }, | |
| 283 { begin: "\\b0[oO][0-7](_?[0-7])*n?\\b" }, | |
| 284 | |
| 285 // LegacyOctalIntegerLiteral (does not include underscore separators) | |
| 286 // https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals | |
| 287 { begin: "\\b0[0-7]+n?\\b" }, | |
| 288 ], | |
| 289 relevance: 0 | |
| 290 }; | |
| 291 | |
| 292 const SUBST = { | |
| 293 className: 'subst', | |
| 294 begin: '\\$\\{', | |
| 295 end: '\\}', | |
| 296 keywords: KEYWORDS$1, | |
| 297 contains: [] // defined later | |
| 298 }; | |
| 299 const HTML_TEMPLATE = { | |
| 300 begin: '\.?html`', | |
| 301 end: '', | |
| 302 starts: { | |
| 303 end: '`', | |
| 304 returnEnd: false, | |
| 305 contains: [ | |
| 306 hljs.BACKSLASH_ESCAPE, | |
| 307 SUBST | |
| 308 ], | |
| 309 subLanguage: 'xml' | |
| 310 } | |
| 311 }; | |
| 312 const CSS_TEMPLATE = { | |
| 313 begin: '\.?css`', | |
| 314 end: '', | |
| 315 starts: { | |
| 316 end: '`', | |
| 317 returnEnd: false, | |
| 318 contains: [ | |
| 319 hljs.BACKSLASH_ESCAPE, | |
| 320 SUBST | |
| 321 ], | |
| 322 subLanguage: 'css' | |
| 323 } | |
| 324 }; | |
| 325 const GRAPHQL_TEMPLATE = { | |
| 326 begin: '\.?gql`', | |
| 327 end: '', | |
| 328 starts: { | |
| 329 end: '`', | |
| 330 returnEnd: false, | |
| 331 contains: [ | |
| 332 hljs.BACKSLASH_ESCAPE, | |
| 333 SUBST | |
| 334 ], | |
| 335 subLanguage: 'graphql' | |
| 336 } | |
| 337 }; | |
| 338 const TEMPLATE_STRING = { | |
| 339 className: 'string', | |
| 340 begin: '`', | |
| 341 end: '`', | |
| 342 contains: [ | |
| 343 hljs.BACKSLASH_ESCAPE, | |
| 344 SUBST | |
| 345 ] | |
| 346 }; | |
| 347 const JSDOC_COMMENT = hljs.COMMENT( | |
| 348 /\/\*\*(?!\/)/, | |
| 349 '\\*/', | |
| 350 { | |
| 351 relevance: 0, | |
| 352 contains: [ | |
| 353 { | |
| 354 begin: '(?=@[A-Za-z]+)', | |
| 355 relevance: 0, | |
| 356 contains: [ | |
| 357 { | |
| 358 className: 'doctag', | |
| 359 begin: '@[A-Za-z]+' | |
| 360 }, | |
| 361 { | |
| 362 className: 'type', | |
| 363 begin: '\\{', | |
| 364 end: '\\}', | |
| 365 excludeEnd: true, | |
| 366 excludeBegin: true, | |
| 367 relevance: 0 | |
| 368 }, | |
| 369 { | |
| 370 className: 'variable', | |
| 371 begin: IDENT_RE$1 + '(?=\\s*(-)|$)', | |
| 372 endsParent: true, | |
| 373 relevance: 0 | |
| 374 }, | |
| 375 // eat spaces (not newlines) so we can find | |
| 376 // types or variables | |
| 377 { | |
| 378 begin: /(?=[^\n])\s/, | |
| 379 relevance: 0 | |
| 380 } | |
| 381 ] | |
| 382 } | |
| 383 ] | |
| 384 } | |
| 385 ); | |
| 386 const COMMENT = { | |
| 387 className: "comment", | |
| 388 variants: [ | |
| 389 JSDOC_COMMENT, | |
| 390 hljs.C_BLOCK_COMMENT_MODE, | |
| 391 hljs.C_LINE_COMMENT_MODE | |
| 392 ] | |
| 393 }; | |
| 394 const SUBST_INTERNALS = [ | |
| 395 hljs.APOS_STRING_MODE, | |
| 396 hljs.QUOTE_STRING_MODE, | |
| 397 HTML_TEMPLATE, | |
| 398 CSS_TEMPLATE, | |
| 399 GRAPHQL_TEMPLATE, | |
| 400 TEMPLATE_STRING, | |
| 401 // Skip numbers when they are part of a variable name | |
| 402 { match: /\$\d+/ }, | |
| 403 NUMBER, | |
| 404 // This is intentional: | |
| 405 // See https://github.com/highlightjs/highlight.js/issues/3288 | |
| 406 // hljs.REGEXP_MODE | |
| 407 ]; | |
| 408 SUBST.contains = SUBST_INTERNALS | |
| 409 .concat({ | |
| 410 // we need to pair up {} inside our subst to prevent | |
| 411 // it from ending too early by matching another } | |
| 412 begin: /\{/, | |
| 413 end: /\}/, | |
| 414 keywords: KEYWORDS$1, | |
| 415 contains: [ | |
| 416 "self" | |
| 417 ].concat(SUBST_INTERNALS) | |
| 418 }); | |
| 419 const SUBST_AND_COMMENTS = [].concat(COMMENT, SUBST.contains); | |
| 420 const PARAMS_CONTAINS = SUBST_AND_COMMENTS.concat([ | |
| 421 // eat recursive parens in sub expressions | |
| 422 { | |
| 423 begin: /(\s*)\(/, | |
| 424 end: /\)/, | |
| 425 keywords: KEYWORDS$1, | |
| 426 contains: ["self"].concat(SUBST_AND_COMMENTS) | |
| 427 } | |
| 428 ]); | |
| 429 const PARAMS = { | |
| 430 className: 'params', | |
| 431 // convert this to negative lookbehind in v12 | |
| 432 begin: /(\s*)\(/, // to match the parms with | |
| 433 end: /\)/, | |
| 434 excludeBegin: true, | |
| 435 excludeEnd: true, | |
| 436 keywords: KEYWORDS$1, | |
| 437 contains: PARAMS_CONTAINS | |
| 438 }; | |
| 439 | |
| 440 // ES6 classes | |
| 441 const CLASS_OR_EXTENDS = { | |
| 442 variants: [ | |
| 443 // class Car extends vehicle | |
| 444 { | |
| 445 match: [ | |
| 446 /class/, | |
| 447 /\s+/, | |
| 448 IDENT_RE$1, | |
| 449 /\s+/, | |
| 450 /extends/, | |
| 451 /\s+/, | |
| 452 regex.concat(IDENT_RE$1, "(", regex.concat(/\./, IDENT_RE$1), ")*") | |
| 453 ], | |
| 454 scope: { | |
| 455 1: "keyword", | |
| 456 3: "title.class", | |
| 457 5: "keyword", | |
| 458 7: "title.class.inherited" | |
| 459 } | |
| 460 }, | |
| 461 // class Car | |
| 462 { | |
| 463 match: [ | |
| 464 /class/, | |
| 465 /\s+/, | |
| 466 IDENT_RE$1 | |
| 467 ], | |
| 468 scope: { | |
| 469 1: "keyword", | |
| 470 3: "title.class" | |
| 471 } | |
| 472 }, | |
| 473 | |
| 474 ] | |
| 475 }; | |
| 476 | |
| 477 const CLASS_REFERENCE = { | |
| 478 relevance: 0, | |
| 479 match: | |
| 480 regex.either( | |
| 481 // Hard coded exceptions | |
| 482 /\bJSON/, | |
| 483 // Float32Array, OutT | |
| 484 /\b[A-Z][a-z]+([A-Z][a-z]*|\d)*/, | |
| 485 // CSSFactory, CSSFactoryT | |
| 486 /\b[A-Z]{2,}([A-Z][a-z]+|\d)+([A-Z][a-z]*)*/, | |
| 487 // FPs, FPsT | |
| 488 /\b[A-Z]{2,}[a-z]+([A-Z][a-z]+|\d)*([A-Z][a-z]*)*/, | |
| 489 // P | |
| 490 // single letters are not highlighted | |
| 491 // BLAH | |
| 492 // this will be flagged as a UPPER_CASE_CONSTANT instead | |
| 493 ), | |
| 494 className: "title.class", | |
| 495 keywords: { | |
| 496 _: [ | |
| 497 // se we still get relevance credit for JS library classes | |
| 498 ...TYPES, | |
| 499 ...ERROR_TYPES | |
| 500 ] | |
| 501 } | |
| 502 }; | |
| 503 | |
| 504 const USE_STRICT = { | |
| 505 label: "use_strict", | |
| 506 className: 'meta', | |
| 507 relevance: 10, | |
| 508 begin: /^\s*['"]use (strict|asm)['"]/ | |
| 509 }; | |
| 510 | |
| 511 const FUNCTION_DEFINITION = { | |
| 512 variants: [ | |
| 513 { | |
| 514 match: [ | |
| 515 /function/, | |
| 516 /\s+/, | |
| 517 IDENT_RE$1, | |
| 518 /(?=\s*\()/ | |
| 519 ] | |
| 520 }, | |
| 521 // anonymous function | |
| 522 { | |
| 523 match: [ | |
| 524 /function/, | |
| 525 /\s*(?=\()/ | |
| 526 ] | |
| 527 } | |
| 528 ], | |
| 529 className: { | |
| 530 1: "keyword", | |
| 531 3: "title.function" | |
| 532 }, | |
| 533 label: "func.def", | |
| 534 contains: [ PARAMS ], | |
| 535 illegal: /%/ | |
| 536 }; | |
| 537 | |
| 538 const UPPER_CASE_CONSTANT = { | |
| 539 relevance: 0, | |
| 540 match: /\b[A-Z][A-Z_0-9]+\b/, | |
| 541 className: "variable.constant" | |
| 542 }; | |
| 543 | |
| 544 function noneOf(list) { | |
| 545 return regex.concat("(?!", list.join("|"), ")"); | |
| 546 } | |
| 547 | |
| 548 const FUNCTION_CALL = { | |
| 549 match: regex.concat( | |
| 550 /\b/, | |
| 551 noneOf([ | |
| 552 ...BUILT_IN_GLOBALS, | |
| 553 "super", | |
| 554 "import" | |
| 555 ].map(x => `${x}\\s*\\(`)), | |
| 556 IDENT_RE$1, regex.lookahead(/\s*\(/)), | |
| 557 className: "title.function", | |
| 558 relevance: 0 | |
| 559 }; | |
| 560 | |
| 561 const PROPERTY_ACCESS = { | |
| 562 begin: regex.concat(/\./, regex.lookahead( | |
| 563 regex.concat(IDENT_RE$1, /(?![0-9A-Za-z$_(])/) | |
| 564 )), | |
| 565 end: IDENT_RE$1, | |
| 566 excludeBegin: true, | |
| 567 keywords: "prototype", | |
| 568 className: "property", | |
| 569 relevance: 0 | |
| 570 }; | |
| 571 | |
| 572 const GETTER_OR_SETTER = { | |
| 573 match: [ | |
| 574 /get|set/, | |
| 575 /\s+/, | |
| 576 IDENT_RE$1, | |
| 577 /(?=\()/ | |
| 578 ], | |
| 579 className: { | |
| 580 1: "keyword", | |
| 581 3: "title.function" | |
| 582 }, | |
| 583 contains: [ | |
| 584 { // eat to avoid empty params | |
| 585 begin: /\(\)/ | |
| 586 }, | |
| 587 PARAMS | |
| 588 ] | |
| 589 }; | |
| 590 | |
| 591 const FUNC_LEAD_IN_RE = '(\\(' + | |
| 592 '[^()]*(\\(' + | |
| 593 '[^()]*(\\(' + | |
| 594 '[^()]*' + | |
| 595 '\\)[^()]*)*' + | |
| 596 '\\)[^()]*)*' + | |
| 597 '\\)|' + hljs.UNDERSCORE_IDENT_RE + ')\\s*=>'; | |
| 598 | |
| 599 const FUNCTION_VARIABLE = { | |
| 600 match: [ | |
| 601 /const|var|let/, /\s+/, | |
| 602 IDENT_RE$1, /\s*/, | |
| 603 /=\s*/, | |
| 604 /(async\s*)?/, // async is optional | |
| 605 regex.lookahead(FUNC_LEAD_IN_RE) | |
| 606 ], | |
| 607 keywords: "async", | |
| 608 className: { | |
| 609 1: "keyword", | |
| 610 3: "title.function" | |
| 611 }, | |
| 612 contains: [ | |
| 613 PARAMS | |
| 614 ] | |
| 615 }; | |
| 616 | |
| 617 return { | |
| 618 name: 'JavaScript', | |
| 619 aliases: ['js', 'jsx', 'mjs', 'cjs'], | |
| 620 keywords: KEYWORDS$1, | |
| 621 // this will be extended by TypeScript | |
| 622 exports: { PARAMS_CONTAINS, CLASS_REFERENCE }, | |
| 623 illegal: /#(?![$_A-z])/, | |
| 624 contains: [ | |
| 625 hljs.SHEBANG({ | |
| 626 label: "shebang", | |
| 627 binary: "node", | |
| 628 relevance: 5 | |
| 629 }), | |
| 630 USE_STRICT, | |
| 631 hljs.APOS_STRING_MODE, | |
| 632 hljs.QUOTE_STRING_MODE, | |
| 633 HTML_TEMPLATE, | |
| 634 CSS_TEMPLATE, | |
| 635 GRAPHQL_TEMPLATE, | |
| 636 TEMPLATE_STRING, | |
| 637 COMMENT, | |
| 638 // Skip numbers when they are part of a variable name | |
| 639 { match: /\$\d+/ }, | |
| 640 NUMBER, | |
| 641 CLASS_REFERENCE, | |
| 642 { | |
| 643 scope: 'attr', | |
| 644 match: IDENT_RE$1 + regex.lookahead(':'), | |
| 645 relevance: 0 | |
| 646 }, | |
| 647 FUNCTION_VARIABLE, | |
| 648 { // "value" container | |
| 649 begin: '(' + hljs.RE_STARTERS_RE + '|\\b(case|return|throw)\\b)\\s*', | |
| 650 keywords: 'return throw case', | |
| 651 relevance: 0, | |
| 652 contains: [ | |
| 653 COMMENT, | |
| 654 hljs.REGEXP_MODE, | |
| 655 { | |
| 656 className: 'function', | |
| 657 // we have to count the parens to make sure we actually have the | |
| 658 // correct bounding ( ) before the =>. There could be any number of | |
| 659 // sub-expressions inside also surrounded by parens. | |
| 660 begin: FUNC_LEAD_IN_RE, | |
| 661 returnBegin: true, | |
| 662 end: '\\s*=>', | |
| 663 contains: [ | |
| 664 { | |
| 665 className: 'params', | |
| 666 variants: [ | |
| 667 { | |
| 668 begin: hljs.UNDERSCORE_IDENT_RE, | |
| 669 relevance: 0 | |
| 670 }, | |
| 671 { | |
| 672 className: null, | |
| 673 begin: /\(\s*\)/, | |
| 674 skip: true | |
| 675 }, | |
| 676 { | |
| 677 begin: /(\s*)\(/, | |
| 678 end: /\)/, | |
| 679 excludeBegin: true, | |
| 680 excludeEnd: true, | |
| 681 keywords: KEYWORDS$1, | |
| 682 contains: PARAMS_CONTAINS | |
| 683 } | |
| 684 ] | |
| 685 } | |
| 686 ] | |
| 687 }, | |
| 688 { // could be a comma delimited list of params to a function call | |
| 689 begin: /,/, | |
| 690 relevance: 0 | |
| 691 }, | |
| 692 { | |
| 693 match: /\s+/, | |
| 694 relevance: 0 | |
| 695 }, | |
| 696 { // JSX | |
| 697 variants: [ | |
| 698 { begin: FRAGMENT.begin, end: FRAGMENT.end }, | |
| 699 { match: XML_SELF_CLOSING }, | |
| 700 { | |
| 701 begin: XML_TAG.begin, | |
| 702 // we carefully check the opening tag to see if it truly | |
| 703 // is a tag and not a false positive | |
| 704 'on:begin': XML_TAG.isTrulyOpeningTag, | |
| 705 end: XML_TAG.end | |
| 706 } | |
| 707 ], | |
| 708 subLanguage: 'xml', | |
| 709 contains: [ | |
| 710 { | |
| 711 begin: XML_TAG.begin, | |
| 712 end: XML_TAG.end, | |
| 713 skip: true, | |
| 714 contains: ['self'] | |
| 715 } | |
| 716 ] | |
| 717 } | |
| 718 ], | |
| 719 }, | |
| 720 FUNCTION_DEFINITION, | |
| 721 { | |
| 722 // prevent this from getting swallowed up by function | |
| 723 // since they appear "function like" | |
| 724 beginKeywords: "while if switch catch for" | |
| 725 }, | |
| 726 { | |
| 727 // we have to count the parens to make sure we actually have the correct | |
| 728 // bounding ( ). There could be any number of sub-expressions inside | |
| 729 // also surrounded by parens. | |
| 730 begin: '\\b(?!function)' + hljs.UNDERSCORE_IDENT_RE + | |
| 731 '\\(' + // first parens | |
| 732 '[^()]*(\\(' + | |
| 733 '[^()]*(\\(' + | |
| 734 '[^()]*' + | |
| 735 '\\)[^()]*)*' + | |
| 736 '\\)[^()]*)*' + | |
| 737 '\\)\\s*\\{', // end parens | |
| 738 returnBegin:true, | |
| 739 label: "func.def", | |
| 740 contains: [ | |
| 741 PARAMS, | |
| 742 hljs.inherit(hljs.TITLE_MODE, { begin: IDENT_RE$1, className: "title.function" }) | |
| 743 ] | |
| 744 }, | |
| 745 // catch ... so it won't trigger the property rule below | |
| 746 { | |
| 747 match: /\.\.\./, | |
| 748 relevance: 0 | |
| 749 }, | |
| 750 PROPERTY_ACCESS, | |
| 751 // hack: prevents detection of keywords in some circumstances | |
| 752 // .keyword() | |
| 753 // $keyword = x | |
| 754 { | |
| 755 match: '\\$' + IDENT_RE$1, | |
| 756 relevance: 0 | |
| 757 }, | |
| 758 { | |
| 759 match: [ /\bconstructor(?=\s*\()/ ], | |
| 760 className: { 1: "title.function" }, | |
| 761 contains: [ PARAMS ] | |
| 762 }, | |
| 763 FUNCTION_CALL, | |
| 764 UPPER_CASE_CONSTANT, | |
| 765 CLASS_OR_EXTENDS, | |
| 766 GETTER_OR_SETTER, | |
| 767 { | |
| 768 match: /\$[(.]/ // relevance booster for a pattern common to JS libs: `$(something)` and `$.something` | |
| 769 } | |
| 770 ] | |
| 771 }; | |
| 772 } | |
| 773 | |
| 774 return javascript; | |
| 775 | |
| 776 })(); | |
| 777 | |
| 778 hljs.registerLanguage('javascript', hljsGrammar); | |
| 779 })(); |