javascript.js 17 KB

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