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