Added pre/code attribute support

Added pre/code attribute support. Simplified code so `markdownSyntaxHighlightOptions` is used for Liquid files. Updated readme, including information about performance. Added "bench" and "debug" to package.json
This commit is contained in:
Robert McGovern 2023-02-06 14:45:32 +00:00
parent 0f05a6abeb
commit ad0c998819
10 changed files with 1145 additions and 101 deletions

View File

@ -17,7 +17,7 @@ module.exports = {
options = Object.assign( options = Object.assign(
{ {
theme: "onedark", theme: "monokai",
lineNumbers: false, lineNumbers: false,
/* lineNumbersStyle: "table",*/ /* "table" or "inline" */ /* lineNumbersStyle: "table",*/ /* "table" or "inline" */
//alwaysWrapLineHighlights: false, //alwaysWrapLineHighlights: false,

1061
README.md

File diff suppressed because it is too large Load Diff

View File

@ -2,12 +2,20 @@ const syntaxHighlight = require("../.eleventy.js");
module.exports = function (eleventyConfig) { module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(syntaxHighlight, { eleventyConfig.addPlugin(syntaxHighlight, {
// alwaysWrapLineHighlights: true theme: "monokai",
lineNumbers: false,
lexerOverrides: { lexerOverrides: {
njk: "vue", njk: "vue",
liquid: "swift", liquid: "vue",
}, },
preAttributes: { tabindex: 0 }, preAttributes: {
tabindex: 0,
testing: "ZX Spectrum Forever",
blargh: "Grrr Argh",
style: "border: purple 5px dashed",
},
codeAttributes: { test: "123" },
}); });
eleventyConfig.setTemplateFormats("njk,liquid,md,css"); eleventyConfig.setTemplateFormats("njk,liquid,md,css");

View File

@ -34,6 +34,16 @@ this is the last line
`; `;
{% endhighlight %} {% endhighlight %}
JS + Linehighlight with /
{% highlight js/1,3 %}
let multilineString = `
this is the first line
this is the middle line
this is the last line
`;
{% endhighlight %}
Swift + show lineNumbers Swift + show lineNumbers
{% highlight swift lineNumbers %} {% highlight swift lineNumbers %}

View File

@ -16,6 +16,14 @@ function myFunction() {
} }
``` ```
Text
```text
function myFunction() {
return true;
}
```
Langs Langs
```ts ```ts
function myFunction() { function myFunction() {

View File

@ -60,6 +60,16 @@ ${collections.post.map((post) => `<li>${ post.data.title }</li>`).join("\n")}
}; };
{% endhighlight %} {% endhighlight %}
Highlight lines 1 & 3
{% highlight "js/1,3" %}
module.exports = function({collections}) {
return `<ul>
${collections.post.map((post) => `<li>${ post.data.title }</li>`).join("\n")}
</ul>`;
};
{% endhighlight %}
{% highlight "typescript" %} {% highlight "typescript" %}
function myFunction() { function myFunction() {
return true; return true;

View File

@ -9,7 +9,9 @@
"scripts": { "scripts": {
"test": "npx ava", "test": "npx ava",
"demo": "npx @11ty/eleventy --input=demo --output=demo/_site --config=demo/eleventy-config.js", "demo": "npx @11ty/eleventy --input=demo --output=demo/_site --config=demo/eleventy-config.js",
"start": "npx @11ty/eleventy --input=demo --output=demo/_site --config=demo/eleventy-config.js --serve" "start": "npx @11ty/eleventy --input=demo --output=demo/_site --config=demo/eleventy-config.js --serve",
"debug": "DEBUG=Eleventy* npx @11ty/eleventy --input=demo --output=demo/_site --config=demo/eleventy-config.js",
"bench": "DEBUG=Eleventy:Benchmark* npx @11ty/eleventy --input=demo --output=demo/_site --config=demo/eleventy-config.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -40,6 +42,7 @@
}, },
"dependencies": { "dependencies": {
"chroma-highlight": "^2.4.2", "chroma-highlight": "^2.4.2",
"jsdom": "^21.1.0",
"linkedom": "^0.14.19" "linkedom": "^0.14.19"
}, },
"ava": { "ava": {
@ -49,4 +52,4 @@
"./test/*.js" "./test/*.js"
] ]
} }
} }

View File

@ -1,7 +1,4 @@
const HighlightPairedShortcode = require("./HighlightPairedShortcode"); const markdownChroma = require("./markdownSyntaxHighlightOptions");
const Chroma = require("chroma-highlight");
const parseSyntaxArguments = require("./parseSyntaxArguments");
const getAttributes = require("./getAttributes");
class LiquidHighlightTag { class LiquidHighlightTag {
constructor(liquidEngine) { constructor(liquidEngine) {
@ -9,6 +6,8 @@ class LiquidHighlightTag {
} }
getObject(options = {}) { getObject(options = {}) {
let mc = markdownChroma(options);
let ret = function (highlighter) { let ret = function (highlighter) {
return { return {
parse: function (tagToken, remainTokens) { parse: function (tagToken, remainTokens) {
@ -39,9 +38,7 @@ class LiquidHighlightTag {
}); });
let tokenStr = tokens.join("").trim(); let tokenStr = tokens.join("").trim();
return Promise.resolve( return Promise.resolve(mc(tokenStr, this.args));
HighlightPairedShortcode(tokenStr, this.args, options)
);
}, },
}; };
}; };

View File

@ -1,5 +1,8 @@
const Chroma = require("chroma-highlight"); const Chroma = require("chroma-highlight");
const parseSyntaxArguments = require("./parseSyntaxArguments"); const parseSyntaxArguments = require("./parseSyntaxArguments");
// const getAttributes = require("./getAttributes");
const jsdom = require("jsdom");
module.exports = function (options = {}) { module.exports = function (options = {}) {
return function (str, args) { return function (str, args) {
@ -10,16 +13,49 @@ module.exports = function (options = {}) {
let html; let html;
if (args === "text") { const parsedArgs = parseSyntaxArguments(args, options);
html = str;
} else {
const parsedArgs = parseSyntaxArguments(args, options);
let opts = `--formatter html --html-only --html-inline-styles ${parsedArgs} `; let opts = `--formatter html --html-only --html-inline-styles ${parsedArgs} `;
html = Chroma.highlight(str, opts); html = Chroma.highlight(str, opts);
}
return html; const dom = new jsdom.JSDOM(html);
addAttributesToHtmlElements(
dom.window.document.getElementsByTagName("pre"),
options.preAttributes
);
addAttributesToHtmlElements(
dom.window.document.getElementsByTagName("code"),
options.codeAttributes
);
return dom.window.document.body.innerHTML;
}; };
}; };
function addAttributesToHtmlElements(elements, attributes) {
if (typeof attributes === "object") {
for (let index = 0; index < elements.length; index++) {
Object.entries(attributes).map((entry) => {
if (typeof elements[index] === "object") {
if (entry[0] === "style") {
// check if style already set
let style = elements[index].getAttribute("style");
if (style != null) {
elements[index].setAttribute(entry[0], style + entry[1]);
} else {
elements[index].setAttribute(entry[0], entry[1]);
}
} else {
elements[index].setAttribute(entry[0], entry[1]);
}
} else {
console.error("Can't set attribute on " + typeof elements[index]);
}
});
}
}
}

View File

@ -1,56 +1,7 @@
// const { split } = require("liquidjs/dist/builtin/filters");
const getAttributes = require("./getAttributes");
function attributeEntryToString2(attribute, context) {
let [key, value] = attribute;
if (typeof value === "function") {
// Callback must return a string or a number
value = value(context); // Run the provided callback and store the result
}
if (typeof value !== "string" && typeof value !== "number") {
throw new Error(
`Attribute "${key}" must have, or evaluate to, a value of type string or number, not "${typeof value}".`
);
}
return `${key}="${value}"`;
}
/**
* ## Usage
* The function `getAttributes` is used to convert an object, `attributes`, with HTML attributes as keys and the values as the corresponding HTML attribute's values.
* If it is falsey, an empty string will be returned.
*
* ```js
getAttributes({
tabindex: 0,
'data-language': function (context) { return context.language; },
'data-otherStuff': 'value'
}) // => ' tabindex="0" data-language="JavaScript" data-otherStuff="value"'
```
*
* @param {{[s: string]: string | number}} attributes An object with key-value pairs that represent attributes.
* @param {object} context An object with the current context.
* @param {string} context.content The code to parse and highlight.
* @param {string} context.language The language for the current instance.
* @param {object} context.options The options passed to the syntax highlighter.
* @returns {string} A string containing the above HTML attributes preceded by a single space.
*/
function parseSyntaxArguments(args, context = {}) { function parseSyntaxArguments(args, context = {}) {
// console.log(">>pSA");
// console.log(args);
// console.log(">>>>>> context");
// console.log(context);
const preAttributes = getAttributes(context.preAttributes);
const codeAttributes = getAttributes(context.codeAttributes);
const lineNumbersRegex = const lineNumbersRegex =
/[0-9]{1,},[0-9]{1,}[:-][0-9]{1,}|[0-9]{1,},[0-9]{1,}|[0-9]{1,}/; /[0-9]{1,},[0-9]{1,}[:-][0-9]{1,}|[0-9]{1,},[0-9]{1,}|[0-9]{1,}/;
// console.log("<<pSA");
let splitArgs; let splitArgs;
if (args.includes("/")) { if (args.includes("/")) {
@ -66,7 +17,7 @@ function parseSyntaxArguments(args, context = {}) {
// Remove the lang from the arguments // Remove the lang from the arguments
let lang = splitArgs.shift(); let lang = splitArgs.shift();
if (context.lexerOverrides[lang]) { if (context.lexerOverrides && context.lexerOverrides[lang]) {
lang = context.lexerOverrides[lang]; lang = context.lexerOverrides[lang];
} }
@ -83,13 +34,15 @@ function parseSyntaxArguments(args, context = {}) {
// console.log("Replacing - with : " + arg); // console.log("Replacing - with : " + arg);
} }
opts = opts + `--html-highlight=${arg} `; opts = opts + `--html-highlight=${arg} `;
} else if (context["lineNumbers"] || args.includes("lineNumbers")) {
opts = opts + "--html-lines ";
} else if (
context["lineNumbersStyle"] == "table" ||
args.includes("table")
) {
opts = opts + "--html-lines-table ";
} }
// console.log(arg);
}); });
// for (arg in splitArgs) {
// console.log(arg);
// }
} }
if (context["theme"]) { if (context["theme"]) {
opts = opts + `--style ${context["theme"]} `; opts = opts + `--style ${context["theme"]} `;
@ -97,14 +50,6 @@ function parseSyntaxArguments(args, context = {}) {
opts = opts + "--style xcode-dark "; opts = opts + "--style xcode-dark ";
} }
if (context["lineNumbers"] || args.includes("lineNumbers")) {
opts = opts + "--html-lines ";
}
if (context["lineNumbersStyle"] == "table" || args.includes("table")) {
opts = opts + "--html-lines-table ";
}
return opts; return opts;
} }