Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
"test-markup": "mocha test/markup",
"test-detect": "mocha test/detect",
"test-browser": "mocha test/browser",
"test-parser": "mocha test/parser"
"test-parser": "mocha test/parser",
"types:emit": "tsc -p tsconfig.emit.json"
},
"engines": {
"node": ">=12.0.0"
Expand Down
2 changes: 1 addition & 1 deletion src/core.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import hljs from "highlight.js";
export default hljs;

export type * from "highlight.js";
53 changes: 26 additions & 27 deletions src/highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,20 @@ import HTMLInjectionError from "./lib/html_injection_error.js";


/**
@typedef {import('highlight.js').Mode} Mode
@typedef {import('highlight.js').CompiledMode} CompiledMode
@typedef {import('highlight.js').CompiledScope} CompiledScope
@typedef {import('highlight.js').Language} Language
@typedef {import('highlight.js').HLJSApi} HLJSApi
@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin
@typedef {import('highlight.js').PluginEvent} PluginEvent
@typedef {import('highlight.js').HLJSOptions} HLJSOptions
@typedef {import('highlight.js').LanguageFn} LanguageFn
@typedef {import('highlight.js').HighlightedHTMLElement} HighlightedHTMLElement
@typedef {import('highlight.js').BeforeHighlightContext} BeforeHighlightContext
@typedef {import('highlight.js/private').MatchType} MatchType
@typedef {import('highlight.js/private').KeywordData} KeywordData
@typedef {import('highlight.js/private').EnhancedMatch} EnhancedMatch
@typedef {import('highlight.js/private').AnnotatedError} AnnotatedError
@typedef {import('highlight.js').AutoHighlightResult} AutoHighlightResult
@typedef {import('highlight.js').HighlightOptions} HighlightOptions
@typedef {import('highlight.js').HighlightResult} HighlightResult
@typedef {import('./lib/hljs_types.js').Mode} Mode
@typedef {import('./lib/hljs_types.js').CompiledMode} CompiledMode
@typedef {import('./lib/hljs_types.js').CompiledScope} CompiledScope
@typedef {import('./lib/hljs_types.js').Language} Language
@typedef {import('./lib/hljs_types.js').HLJSApi} HLJSApi
@typedef {import('./lib/hljs_types.js').HLJSPlugin} HLJSPlugin
@typedef {import('./lib/hljs_types.js').PluginEvent} PluginEvent
@typedef {import('./lib/hljs_types.js').HLJSOptions} HLJSOptions
@typedef {import('./lib/hljs_types.js').LanguageFn} LanguageFn
@typedef {import('./lib/hljs_types.js').HighlightedHTMLElement} HighlightedHTMLElement
@typedef {import('./lib/hljs_types.js').BeforeHighlightContext} BeforeHighlightContext
@typedef {import('./lib/hljs_types.js').AutoHighlightResult} AutoHighlightResult
@typedef {import('./lib/hljs_types.js').HighlightOptions} HighlightOptions
@typedef {import('./lib/hljs_types.js').HighlightResult} HighlightResult
*/


Expand Down Expand Up @@ -191,7 +187,7 @@ const HLJS = function(hljs) {
* Return keyword data if a match is a keyword
* @param {CompiledMode} mode - current mode
* @param {string} matchText - the textual match
* @returns {KeywordData | false}
* @returns {import('./lib/hljs_types.js').KeywordData | false}
*/
function keywordData(mode, matchText) {
return mode.keywords[matchText];
Expand Down Expand Up @@ -273,7 +269,7 @@ const HLJS = function(hljs) {
}

/**
* @param {string} text
* @param {string} keyword
* @param {string} scope
*/
function emitKeyword(keyword, scope) {
Expand Down Expand Up @@ -382,7 +378,7 @@ const HLJS = function(hljs) {
/**
* Handle the start of a new potential mode match
*
* @param {EnhancedMatch} match - the current match
* @param {import('./lib/hljs_types.js').EnhancedMatch} match - the current match
* @returns {number} how far to advance the parse cursor
*/
function doBeginMatch(match) {
Expand Down Expand Up @@ -468,14 +464,14 @@ const HLJS = function(hljs) {
list.forEach(item => emitter.openNode(item));
}

/** @type {{type?: MatchType, index?: number, rule?: Mode}}} */
/** @type {{ type?: import('./lib/hljs_types.js').MatchType, index?: number, rule?: CompiledMode }} */
let lastMatch = {};

/**
* Process an individual match
*
* @param {string} textBeforeMatch - text preceding the match (since the last match)
* @param {EnhancedMatch} [match] - the match itself
* @param {import('./lib/hljs_types.js').EnhancedMatch} [match] - the match itself
*/
function processLexeme(textBeforeMatch, match) {
const lexeme = match && match[0];
Expand All @@ -496,7 +492,7 @@ const HLJS = function(hljs) {
// spit the "skipped" character that our regex choked on back into the output sequence
modeBuffer += codeToHighlight.slice(match.index, match.index + 1);
if (!SAFE_MODE) {
/** @type {AnnotatedError} */
/** @type {import('./lib/hljs_types.js').AnnotatedError} */
const err = new Error(`0 width match regex (${languageName})`);
err.languageName = languageName;
err.badRule = lastMatch.rule;
Expand All @@ -510,7 +506,7 @@ const HLJS = function(hljs) {
return doBeginMatch(match);
} else if (match.type === "illegal" && !ignoreIllegals) {
// illegal match, we do not continue processing
/** @type {AnnotatedError} */
/** @type {import('./lib/hljs_types.js').AnnotatedError} */
const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.scope || '<unnamed>') + '"');
err.mode = top;
throw err;
Expand Down Expand Up @@ -975,8 +971,10 @@ const HLJS = function(hljs) {
function fire(event, args) {
const cb = event;
plugins.forEach(function(plugin) {
if (plugin[cb]) {
plugin[cb](args);
/** @type {Record<string, any>} */
const p = plugin;
if (p[cb]) {
p[cb](args);
}
});
}
Expand Down Expand Up @@ -1041,6 +1039,7 @@ const HLJS = function(hljs) {
};

// Other names for the variable may break build script
/** @type {HLJSApi} */
const highlight = HLJS({});

// returns a new instance of the highlighter to be used for extensions
Expand Down
2 changes: 1 addition & 1 deletion src/lib/compile_keywords.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const DEFAULT_KEYWORD_SCOPE = "keyword";
* @param {boolean} caseInsensitive
*/
export function compileKeywords(rawKeywords, caseInsensitive, scopeName = DEFAULT_KEYWORD_SCOPE) {
/** @type {import("highlight.js/private").KeywordDict} */
/** @type {import("./hljs_types.js").KeywordDict} */
const compiledKeywords = Object.create(null);

// input can be a string of keywords, an array of keywords, or a object with
Expand Down
4 changes: 2 additions & 2 deletions src/lib/compiler_extensions.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as regex from './regex.js';

/**
@typedef {import('highlight.js').CallbackResponse} CallbackResponse
@typedef {import('highlight.js').CompilerExt} CompilerExt
@typedef {import('./hljs_types.js').CallbackResponse} CallbackResponse
@typedef {import('./hljs_types.js').CompilerExt} CompilerExt
*/

// Grammar extensions / plugins
Expand Down
19 changes: 10 additions & 9 deletions src/lib/ext/multi_class.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as logger from "../../lib/logger.js";
import * as regex from "../regex.js";

/**
@typedef {import('highlight.js').CompiledMode} CompiledMode
@typedef {import('../hljs_types.js').CompiledMode} CompiledMode
*/

const MultiClassError = new Error();
Expand Down Expand Up @@ -115,18 +115,19 @@ function scopeSugar(mode) {
}

/**
* @param {CompiledMode} mode
* @param {CompiledMode | import('../hljs_types.js').Mode} mode
*/
export function MultiClass(mode) {
scopeSugar(mode);
const m = /** @type {CompiledMode} */ (mode);
scopeSugar(m);

if (typeof mode.beginScope === "string") {
mode.beginScope = { _wrap: mode.beginScope };
if (typeof m.beginScope === "string") {
m.beginScope = { _wrap: m.beginScope };
}
if (typeof mode.endScope === "string") {
mode.endScope = { _wrap: mode.endScope };
if (typeof m.endScope === "string") {
m.endScope = { _wrap: m.endScope };
}

beginMultiClass(mode);
endMultiClass(mode);
beginMultiClass(m);
endMultiClass(m);
}
8 changes: 6 additions & 2 deletions src/lib/exts/before_match.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ import * as regex from "../regex.js";

// allow beforeMatch to act as a "qualifier" for the match
// the full match begin must be [beforeMatch][begin]
/** @type {import('../hljs_types.js').CompilerExt} */
export const beforeMatchExt = (mode, parent) => {
if (!mode.beforeMatch) return;
// starts conflicts with endsParent which we need to make sure the child
// rule is not matched multiple times
if (mode.starts) throw new Error("beforeMatch cannot be used with starts");

const originalMode = Object.assign({}, mode);
Object.keys(mode).forEach((key) => { delete mode[key]; });
Object.keys(mode).forEach((key) => { delete /** @type {any} */ (mode)[key]; });

mode.keywords = originalMode.keywords;
mode.begin = regex.concat(originalMode.beforeMatch, regex.lookahead(originalMode.begin));
mode.begin = regex.concat(
originalMode.beforeMatch,
regex.lookahead(/** @type {string | RegExp} */ (originalMode.begin))
);
mode.starts = {
relevance: 0,
contains: [
Expand Down
Loading