diff --git a/CHANGES.md b/CHANGES.md
index a6abc3b73b..46b94d82b0 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -35,6 +35,11 @@ Language grammar improvements:
Deprecations:
+- `highlight(languageName, code, ignoreIllegals, continuation)` deprecated as of 10.7
+ - Please use the newer API which takes `code` and then accepts options as an object
+ - IE: `highlight(code, {language, ignoreIllegals})`
+ - `continuation` is for internal use only and no longer supported
+
- `highlightBlock(el)` deprecated as of 10.7.
- Please use `highlightElement(el)` instead.
- Plugin callbacks renamed `before/after:highlightBlock` => `before/after:highlightElement`
diff --git a/README.md b/README.md
index d76bcfbf76..7eeadceb36 100644
--- a/README.md
+++ b/README.md
@@ -211,7 +211,7 @@ const hljs = require('highlight.js/lib/core'); // require only the core library
// separately require languages
hljs.registerLanguage('xml', require('highlight.js/lib/languages/xml'));
-const highlightedCode = hljs.highlight('xml', 'Hello World!').value
+const highlightedCode = hljs.highlight('Hello World!', {language: 'xml'}).value
```
diff --git a/docs/api.rst b/docs/api.rst
index 3c2936b0d4..c3f28cb13e 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -4,15 +4,12 @@ Library API
Highlight.js exports a few functions as methods of the ``hljs`` object.
-``highlight(languageName, code, ignore_illegals, continuation)``
-----------------------------------------------------------------
+``highlight(languageName, code, ignoreIllegals, continuation)`` (deprecated with 10.7)
+--------------------------------------------------------------------------------------
-Core highlighting function.
-Accepts a language name, or an alias, and a string with the code to highlight.
-The ``ignore_illegals`` parameter, when present and evaluates to a true value,
-forces highlighting to finish even in case of detecting illegal syntax for the
-language instead of throwing an exception.
-The ``continuation`` is an optional mode stack representing unfinished parsing.
+**This is the old API, please see the new API immediately below.**
+
+``continuation`` is an optional mode stack representing unfinished parsing.
When present, the function will restart parsing from this state instead of
initializing a new one. This is used internally for `sublanguage` support.
@@ -21,6 +18,18 @@ because there is no requirement that a grammar handle linebreaks in any special
way. It's quite possible for a grammar to have a single mode/regex that matches
MANY lines at once. This is not discouraged and entirely up to the grammar.
+
+
+``highlight(code, {language, ignoreIllegals})``
+--------------------------------------------------------------------------------------
+
+Core highlighting function. Accepts the code to highlight (string) and a list of options (object).
+The ``language`` parameter must be present and specify the language name or alias
+of the grammar to be used for highlighting.
+The ``ignoreIllegals`` is an optional parameter than when true forces highlighting
+to finish even in case of detecting illegal syntax for the
+language instead of throwing an exception.
+
Returns an object with the following properties:
* ``language``: language name, same as the name passed in ``languageName``, returned for consistency with ``highlightAuto``
diff --git a/src/highlight.js b/src/highlight.js
index 1073166a83..c1544b7ac8 100644
--- a/src/highlight.js
+++ b/src/highlight.js
@@ -93,8 +93,14 @@ const HLJS = function(hljs) {
/**
* Core highlighting function.
*
- * @param {string} languageName - the language to use for highlighting
- * @param {string} code - the code to highlight
+ * OLD API
+ * highlight(lang, code, ignoreIllegals, continuation)
+ *
+ * NEW API
+ * highlight(code, {lang, ignoreIllegals})
+ *
+ * @param {string} codeOrlanguageName - the language to use for highlighting
+ * @param {string | HighlightOptions} optionsOrCode - the code to highlight
* @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail
* @param {CompiledMode} [continuation] - current continuation mode, if any
*
@@ -106,7 +112,24 @@ const HLJS = function(hljs) {
* @property {CompiledMode} top - top of the current mode stack
* @property {boolean} illegal - indicates whether any illegal matches were found
*/
- function highlight(languageName, code, ignoreIllegals, continuation) {
+ function highlight(codeOrlanguageName, optionsOrCode, ignoreIllegals, continuation) {
+ let code = "";
+ let languageName = "";
+ if (typeof optionsOrCode === "object") {
+ code = codeOrlanguageName;
+ ignoreIllegals = optionsOrCode.ignoreIllegals;
+ languageName = optionsOrCode.language;
+ // continuation not supported at all via the new API
+ // eslint-disable-next-line no-undefined
+ continuation = undefined;
+ } else {
+ // old API
+ logger.deprecated("10.7.0", "highlight(lang, code, ...args) has been deprecated.");
+ logger.deprecated("10.7.0", "Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277");
+ languageName = codeOrlanguageName;
+ code = optionsOrCode;
+ }
+
/** @type {BeforeHighlightContext} */
const context = {
code,
@@ -133,14 +156,12 @@ const HLJS = function(hljs) {
* private highlight that's used internally and does not fire callbacks
*
* @param {string} languageName - the language to use for highlighting
- * @param {string} code - the code to highlight
- * @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail
- * @param {CompiledMode} [continuation] - current continuation mode, if any
+ * @param {string} codeToHighlight - the code to highlight
+ * @param {boolean?} [ignoreIllegals] - whether to ignore illegal matches, default is to bail
+ * @param {CompiledMode?} [continuation] - current continuation mode, if any
* @returns {HighlightResult} - result of the highlight operation
*/
- function _highlight(languageName, code, ignoreIllegals, continuation) {
- const codeToHighlight = code;
-
+ function _highlight(languageName, codeToHighlight, ignoreIllegals, continuation) {
/**
* Return keyword data if a match is a keyword
* @param {CompiledMode} mode - current mode
@@ -708,7 +729,7 @@ const HLJS = function(hljs) {
node = element;
const text = node.textContent;
- const result = language ? highlight(language, text, true) : highlightAuto(text);
+ const result = language ? highlight(text, { language, ignoreIllegals: true }) : highlightAuto(text);
// support for v10 API
fire("after:highlightElement", { el: element, result, text });
diff --git a/test/api/beginKeywords.js b/test/api/beginKeywords.js
index 53bf85b796..407f830db6 100644
--- a/test/api/beginKeywords.js
+++ b/test/api/beginKeywords.js
@@ -27,25 +27,25 @@ describe('beginKeywords', () => {
it("should allow subsequence matches to still succeed", () => {
let content = "A.class = self";
- let res = hljs.highlight("has-followup", content);
+ let res = hljs.highlight(content, {language: "has-followup"});
res.value.should.equal('A.class = self');
});
it("should ignore a preceeding .", () => {
let content = "A.class = self";
- let res = hljs.highlight("test", content);
+ let res = hljs.highlight(content, { language: "test" });
res.value.should.equal('A.class = self');
});
it("should ignore a trailing .", () => {
let content = "class.config = true";
- let res = hljs.highlight("test", content);
+ let res = hljs.highlight(content, { language: "test" });
res.value.should.equal('class.config = true');
});
it('should detect keywords', () => {
let content = "I have a class yes I do.";
- let res = hljs.highlight("test", content);
+ let res = hljs.highlight(content, { language: "test" });
res.value.should.equal('I have a class yes I do.');
});
});
diff --git a/test/api/highlight.js b/test/api/highlight.js
index 962c36e175..043dc499ad 100644
--- a/test/api/highlight.js
+++ b/test/api/highlight.js
@@ -4,9 +4,47 @@ const hljs = require('../../build');
const should = require('should');
describe('.highlight()', () => {
+ it('should support ignoreIllegals (old API)', () => {
+ let code = "float # float";
+ let result = hljs.highlight("java", code, true);
+ result.value.should.equal(`float # float`);
+
+ code = "float # float";
+ result = hljs.highlight("java", code, false);
+ result.value.should.equal("float # float");
+ result.illegal.should.equal(true);
+ });
+ it('should support ignoreIllegals (new API)', () => {
+ let code = "float # float";
+ let result = hljs.highlight(code, { language: "java", ignoreIllegals: true });
+ result.value.should.equal(`float # float`);
+
+ code = "float # float";
+ result = hljs.highlight(code, { language: "java", ignoreIllegals: false });
+ result.value.should.equal("float # float");
+ result.illegal.should.equal(true);
+
+ // defaults to false
+ code = "float # float";
+ result = hljs.highlight(code, { language: "java" });
+ result.value.should.equal("float # float");
+ result.illegal.should.equal(true);
+ });
+ it('should use new API with options', () => {
+ const code = "public void moveTo(int x, int y, int z);";
+ const result = hljs.highlight(code, { language: "java" });
+
+ result.value.should.equal(
+ 'public ' +
+ 'void moveTo' +
+ '(int x, ' +
+ 'int y, ' +
+ 'int z);'
+ );
+ });
it('should works without continuation', () => {
- const code = "public void moveTo(int x, int y, int z);";
- const result = hljs.highlight('java', code, false, false);
+ const code = "public void moveTo(int x, int y, int z);";
+ const result = hljs.highlight(code, { language: 'java' });
result.value.should.equal(
'public ' +
diff --git a/test/api/keywords.js b/test/api/keywords.js
index f72a212c08..de1c466a3b 100644
--- a/test/api/keywords.js
+++ b/test/api/keywords.js
@@ -13,7 +13,7 @@ describe('computing the relevance score of a language', () => {
}
const code = "farmer and of river weeds";
hljs.registerLanguage("test", grammar)
- const result = hljs.highlight('test', code, false, false);
+ const result = hljs.highlight(code, { language: 'test' });
result.relevance.should.equal(3)
});
@@ -27,7 +27,7 @@ describe('computing the relevance score of a language', () => {
}
const code = "farmer and of river weeds";
hljs.registerLanguage("test", grammar)
- const result = hljs.highlight('test', code, false, false);
+ const result = hljs.highlight(code, { language: 'test' });
result.relevance.should.equal(13)
});
@@ -41,7 +41,7 @@ describe('computing the relevance score of a language', () => {
}
const code = "farmer and of river weeds";
hljs.registerLanguage("test", grammar)
- const result = hljs.highlight('test', code, false, false);
+ const result = hljs.highlight(code, { language: 'test' });
result.relevance.should.equal(4)
});
diff --git a/test/browser/plain.js b/test/browser/plain.js
index 0416e94d3f..ca6ef222fb 100644
--- a/test/browser/plain.js
+++ b/test/browser/plain.js
@@ -16,7 +16,7 @@ describe('plain browser', function() {
it('should return relevance key', async function() {
await buildFakeDOM.bind(this, defaultCase)();
- var out = this.hljs.highlight("javascript","");
+ var out = this.hljs.highlight("", { language: "javascript" });
out.relevance.should.equal(0);
});
diff --git a/test/browser/worker.js b/test/browser/worker.js
index c1e99ca64e..af8dcc2f0d 100644
--- a/test/browser/worker.js
+++ b/test/browser/worker.js
@@ -13,7 +13,7 @@ describe('web worker', function() {
importScripts(event.data.script);
postMessage(1);
} else {
- var result = hljs.highlight('javascript', event.data);
+ var result = hljs.highlight(event.data, { language: 'javascript' });
postMessage(result.value);
}
};
diff --git a/test/detect/index.js b/test/detect/index.js
index b51adb10b3..cc317e2e9f 100644
--- a/test/detect/index.js
+++ b/test/detect/index.js
@@ -56,6 +56,6 @@ describe('hljs.highlightAuto()', () => {
it("compiling the grammars", async function() {
const languages = hljs.listLanguages();
- languages.forEach(l => hljs.highlight(l, ""))
+ languages.forEach(lang => hljs.highlight("", { language: lang} ))
}); // this is also required for the dynamic test generation above to work
});
diff --git a/test/markup/index.js b/test/markup/index.js
index 28138ffa6b..f653976082 100644
--- a/test/markup/index.js
+++ b/test/markup/index.js
@@ -27,7 +27,7 @@ function testLanguage(language, {testDir}) {
const expectedFile = fs.readFile(filename, 'utf-8');
Promise.all([sourceFile, expectedFile]).then(function([source, expected]) {
- const actual = hljs.highlight(language, source).value;
+ const actual = hljs.highlight(source, { language }).value;
// Uncomment this for major changes that rewrite the test expectations
// which will then need to be manually compared by hand of course
diff --git a/test/parser/compiler-extensions.js b/test/parser/compiler-extensions.js
index 90b1d0f37e..7ba26e0199 100644
--- a/test/parser/compiler-extensions.js
+++ b/test/parser/compiler-extensions.js
@@ -28,7 +28,7 @@ describe.skip("compiler extension plugins", function() {
hljs.addPlugin(plugin);
// stub highlight to make sure the language gets compiled
// since we have no API point to make that happen
- hljs.highlight("extension_test", "");
+ hljs.highlight("", { language: "extension_test" });
const [first, second] = hljs.getLanguage("extension_test").contains;
this.first = first;
this.second = second;
diff --git a/test/parser/look-ahead-end-matchers.js b/test/parser/look-ahead-end-matchers.js
index 241e1fd0f6..5d96e1d8ef 100644
--- a/test/parser/look-ahead-end-matchers.js
+++ b/test/parser/look-ahead-end-matchers.js
@@ -20,7 +20,7 @@ describe("parser specifics", function () {
};
});
- hljs.highlight('test-language', 'ABC123 is the secret. XYZ123. End of string: ABC123').value
+ hljs.highlight('ABC123 is the secret. XYZ123. End of string: ABC123', {language: 'test-language'}).value
.should.equal(
// one full match at beginning, other match begins with XYZ but then never terminates,
// so the end of the parsing finally closes the span tag
diff --git a/test/parser/resume-scan.js b/test/parser/resume-scan.js
index fb50a47f37..2e4d6c208a 100644
--- a/test/parser/resume-scan.js
+++ b/test/parser/resume-scan.js
@@ -6,7 +6,7 @@ hljs.debugMode(); // tests run in debug mode so errors are raised
describe("bugs", function() {
describe("resume scan when a match is ignored", () => {
it("should continue to highlight later matches", () => {
- const result = hljs.highlight('java', 'ImmutablePair.of(Stuff.class, "bar")');
+ const result = hljs.highlight('ImmutablePair.of(Stuff.class, "bar")', {language: 'java'});
result.value.should.equal(
'ImmutablePair.of(Stuff.class, "bar")'
);
@@ -16,7 +16,7 @@ describe("bugs", function() {
// rule we really only want to skip searching for THAT rule at that same location, we
// do not want to stop searching for ALL the prior rules at that location...
it("BUT should not skip ahead too far", () => {
- const result = hljs.highlight('java', 'ImmutablePair.of(Stuff.class, "bar");\n23');
+ const result = hljs.highlight('ImmutablePair.of(Stuff.class, "bar");\n23', {language: 'java'});
result.value.should.equal(
'ImmutablePair.of(Stuff.class, "bar");\n' +
'23'
diff --git a/test/parser/reuse-endsWithParent.js b/test/parser/reuse-endsWithParent.js
index 7a4d2fe9dc..d8b8f8e621 100644
--- a/test/parser/reuse-endsWithParent.js
+++ b/test/parser/reuse-endsWithParent.js
@@ -16,7 +16,7 @@ describe("bugs", function () {
};
});
- hljs.highlight('test-language', '(abc 123) [abc 123] (abc 123)').value
+ hljs.highlight('(abc 123) [abc 123] (abc 123)', {language: 'test-language'}).value
.should.equal(
'(abc 123) ' +
'[abc 123] ' +
diff --git a/test/parser/should-not-destroyData.js b/test/parser/should-not-destroyData.js
index e12a571ed0..d5688112ee 100644
--- a/test/parser/should-not-destroyData.js
+++ b/test/parser/should-not-destroyData.js
@@ -19,19 +19,19 @@ describe("parser/should not destroy data", function () {
};
});
- hljs.highlight('test-language', 'The number is 123_longint yes.').value
+ hljs.highlight('The number is 123_longint yes.', {language: 'test-language' }).value
.should.equal(
- // The whole number isn't highlighted (the rule doesn't handle the _type)
- // But the key thing is the "1" is registered as a match for the rule
- // instead of disappearing from the output completely, which is what
- // would happen previously.
- 'The number is 123_longint yes.'
- // Incorrect prior output:
- // 'The number is 23_longint yes.'
- )
+ // The whole number isn't highlighted (the rule doesn't handle the _type)
+ // But the key thing is the "1" is registered as a match for the rule
+ // instead of disappearing from the output completely, which is what
+ // would happen previously.
+ 'The number is 123_longint yes.'
+ // Incorrect prior output:
+ // 'The number is 23_longint yes.'
+ );
hljs.debugMode();
should(() => {
- hljs.highlight('test-language', 'The number is 123_longint yes.').value
+ hljs.highlight('The number is 123_longint yes.', {language: 'test-language'}).value
}).throw(Error, {
message: "0 width match regex",
languageName: "test-language"})
diff --git a/test/regex/index.js b/test/regex/index.js
index 426568ba4f..29c29f0d22 100644
--- a/test/regex/index.js
+++ b/test/regex/index.js
@@ -25,7 +25,7 @@ const polyBacktrackingCache = {};
function retrieveRules(language, { name }) {
// first we need to get the language compiled so we have
// access to the raw regex
- hljs.highlight(name, "");
+ hljs.highlight("", {language: name});
return regexFor(language, { context: name, depth: 0 });
}
diff --git a/types/index.d.ts b/types/index.d.ts
index 6e948954dc..89208c0131 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -112,6 +112,11 @@ interface EmitterConstructor {
new (opts: any): Emitter
}
+interface HighlightOptions {
+ language: string
+ ignoreIllegals?: boolean
+}
+
interface HLJSOptions {
noHighlightRe: RegExp
languageDetectRe: RegExp