import * as ECMAScript from "./lib/ecmascript.js";
import javascript from "./javascript.js";
export default function(hljs) {
const tsLanguage = javascript(hljs);
const IDENT_RE = ECMAScript.IDENT_RE;
const TYPES = [
"any",
"void",
"number",
"boolean",
"string",
"object",
"never",
"symbol",
"bigint",
"unknown"
];
const NAMESPACE = {
beginKeywords: 'namespace',
end: /\{/,
excludeEnd: true,
contains: [ tsLanguage.exports.CLASS_REFERENCE ]
};
const INTERFACE = {
beginKeywords: 'interface',
end: /\{/,
excludeEnd: true,
keywords: {
keyword: 'interface extends',
built_in: TYPES
},
contains: [ tsLanguage.exports.CLASS_REFERENCE ]
};
const USE_STRICT = {
className: 'meta',
relevance: 10,
begin: /^\s*['"]use strict['"]/
};
const TS_SPECIFIC_KEYWORDS = [
"type",
"namespace",
"interface",
"public",
"private",
"protected",
"implements",
"declare",
"abstract",
"readonly",
"enum",
"override"
];
const KEYWORDS = {
$pattern: ECMAScript.IDENT_RE,
keyword: ECMAScript.KEYWORDS.concat(TS_SPECIFIC_KEYWORDS),
literal: ECMAScript.LITERALS,
built_in: ECMAScript.BUILT_INS.concat(TYPES),
"variable.language": ECMAScript.BUILT_IN_VARIABLES
};
const DECORATOR = {
className: 'meta',
begin: '@' + IDENT_RE,
};
const swapMode = (mode, label, replacement) => {
const indx = mode.contains.findIndex(m => m.label === label);
if (indx === -1) { throw new Error("can not find mode to replace"); }
mode.contains.splice(indx, 1, replacement);
};
Object.assign(tsLanguage.keywords, KEYWORDS);
tsLanguage.exports.PARAMS_CONTAINS.push(DECORATOR);
tsLanguage.contains = tsLanguage.contains.concat([
DECORATOR,
NAMESPACE,
INTERFACE,
]);
swapMode(tsLanguage, "shebang", hljs.SHEBANG());
swapMode(tsLanguage, "use_strict", USE_STRICT);
const functionDeclaration = tsLanguage.contains.find(m => m.label === "func.def");
functionDeclaration.relevance = 0;
Object.assign(tsLanguage, {
name: 'TypeScript',
aliases: [
'ts',
'tsx'
]
});
return tsLanguage;
}