@11ty/eleventy-plugin-syntaxhighlight
Advanced tools
Comparing version 4.0.0 to 4.1.0
{ | ||
"name": "@11ty/eleventy-plugin-syntaxhighlight", | ||
"version": "4.0.0", | ||
"version": "4.1.0", | ||
"description": "Prism.js based syntax highlighting for Markdown, Liquid, Nunjucks, and 11ty.js templates.", | ||
@@ -5,0 +5,0 @@ "publishConfig": { |
@@ -1,3 +0,5 @@ | ||
# eleventy-plugin-syntaxhighlight | ||
<p align="center"><img src="https://www.11ty.dev/img/logo-github.svg" width="200" height="200" alt="eleventy Logo"></p> | ||
# eleventy-plugin-syntaxhighlight 🕚⚡️🎈🐀 | ||
A pack of [Eleventy](https://github.com/11ty/eleventy) plugins for syntax highlighting. No browser/client JavaScript here, these highlight transformations are all done at build-time. | ||
@@ -4,0 +6,0 @@ |
@@ -1,6 +0,13 @@ | ||
function attributeEntryToString([key, value]) { | ||
if (typeof value !== "string" && typeof value !== "number") | ||
function attributeEntryToString(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 a value of type string or number not "${typeof value}".` | ||
`Attribute "${key}" must have, or evaluate to, a value of type string or number, not "${typeof value}".` | ||
); | ||
} | ||
@@ -18,3 +25,3 @@ return `${key}="${value}"`; | ||
tabindex: 0, | ||
'data-language': 'JavaScript', | ||
'data-language': function (context) { return context.language; }, | ||
'data-otherStuff': 'value' | ||
@@ -25,11 +32,27 @@ }) // => ' 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 getAttributes(attributes) { | ||
function getAttributes(attributes, context = {}) { | ||
let langClass = context.language ? `language-${context.language}` : ""; | ||
if (!attributes) { | ||
return ""; | ||
return langClass ? ` class="${langClass}"` : ""; | ||
} else if (typeof attributes === "object") { | ||
if(!("class" in attributes) && langClass) { | ||
// class attribute should be first in order | ||
let tempAttrs = { class: langClass }; | ||
for(let key in attributes) { | ||
tempAttrs[key] = attributes[key]; | ||
} | ||
attributes = tempAttrs; | ||
} | ||
const formattedAttributes = Object.entries(attributes).map( | ||
attributeEntryToString | ||
entry => attributeEntryToString(entry, context) | ||
); | ||
return formattedAttributes.length ? ` ${formattedAttributes.join(" ")}` : ""; | ||
@@ -36,0 +59,0 @@ } else if (typeof attributes === "string") { |
@@ -7,5 +7,2 @@ const Prism = require("prismjs"); | ||
module.exports = function (content, language, highlightNumbers, options = {}) { | ||
const preAttributes = getAttributes(options.preAttributes); | ||
const codeAttributes = getAttributes(options.codeAttributes); | ||
// default to on | ||
@@ -24,3 +21,3 @@ if(options.trim === undefined || options.trim === true) { | ||
let group = new HighlightLinesGroup(highlightNumbers); | ||
let lines = highlightedContent.split("\n"); | ||
let lines = highlightedContent.split(/\r?\n/); | ||
lines = lines.map(function(line, j) { | ||
@@ -34,3 +31,7 @@ if(options.alwaysWrapLineHighlights || highlightNumbers) { | ||
return `<pre class="language-${language}"${preAttributes}><code class="language-${language}"${codeAttributes}>` + lines.join(options.lineSeparator || "<br>") + "</code></pre>"; | ||
const context = { content: content, language: language, options: options }; | ||
const preAttributes = getAttributes(options.preAttributes, context); | ||
const codeAttributes = getAttributes(options.codeAttributes, context); | ||
return `<pre${preAttributes}><code${codeAttributes}>` + lines.join(options.lineSeparator || "<br>") + "</code></pre>"; | ||
}; |
@@ -7,5 +7,2 @@ const Prism = require("prismjs"); | ||
module.exports = function (options = {}) { | ||
const preAttributes = getAttributes(options.preAttributes); | ||
const codeAttributes = getAttributes(options.codeAttributes); | ||
return function(str, language) { | ||
@@ -17,2 +14,3 @@ if(!language) { | ||
let split = language.split("/"); | ||
@@ -42,4 +40,8 @@ if( split.length ) { | ||
return `<pre class="language-${language}"${preAttributes}><code class="language-${language}"${codeAttributes}>${lines.join(options.lineSeparator || "<br>")}</code></pre>`; | ||
const context = { content: str, language: language, options: options }; | ||
const preAttributes = getAttributes(options.preAttributes, context); | ||
const codeAttributes = getAttributes(options.codeAttributes, context); | ||
return `<pre${preAttributes}><code${codeAttributes}>${lines.join(options.lineSeparator || "<br>")}</code></pre>`; | ||
}; | ||
}; |
const Prism = require("prismjs"); | ||
const HARDCODED_ALIASES = { | ||
njk: "jinja2", | ||
nunjucks: "jinja2", | ||
}; | ||
// This was added to make `ts` resolve to `typescript` correctly. | ||
@@ -12,2 +17,7 @@ // The Prism loader doesn’t seem to always handle aliasing correctly. | ||
// Manual override | ||
if(HARDCODED_ALIASES[language]) { | ||
language = HARDCODED_ALIASES[language]; | ||
} | ||
if(langs[ language ]) { | ||
@@ -14,0 +24,0 @@ return language; |
@@ -18,2 +18,38 @@ const test = require("ava"); | ||
t.is(ga({ hi: 1, bye: 2 }), ' hi="1" bye="2"'); | ||
t.is(ga({ class: "my-class", bye: 2 }), ' class="my-class" bye="2"'); | ||
t.is(ga({ hi: function(ctx) { return '1'; }, bye: 2 }), ' hi="1" bye="2"'); | ||
}); | ||
test("Function callback", t => { | ||
t.is(ga({ "data-lang": ({language}) => language }, { | ||
language: "html" | ||
}), ' class="language-html" data-lang="html"'); | ||
}); | ||
test("Function callback with class attribute (override)", t => { | ||
t.is(ga({ | ||
class: ({language}) => "my-custom-"+language | ||
}, { | ||
language: "html" | ||
}), ' class="my-custom-html"'); | ||
}); | ||
test("Function callback must return string or integer", t => { | ||
t.throws(() => { | ||
ga({ "data-lang": ({language}) => undefined }, { | ||
language: "html" | ||
}) | ||
}); | ||
t.throws(() => { | ||
ga({ "data-lang": ({language}) => {} }, { | ||
language: "html" | ||
}) | ||
}); | ||
t.throws(() => { | ||
ga({ "data-lang": ({language}) => false }, { | ||
language: "html" | ||
}) | ||
}); | ||
}); |
@@ -9,2 +9,22 @@ const test = require("ava"); | ||
test("Base with LF EOL, always wrap highlights", async t => { | ||
t.is(await HighlightPairedShortcode('alert();\nalert();', | ||
"js", "", { alwaysWrapLineHighlights: true }), `<pre class="language-js"><code class="language-js"><span class="highlight-line"><span class="token function">alert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line"><span class="token function">alert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span></code></pre>`); | ||
}); | ||
test("Base with LF EOL, no wrap highlights", async t => { | ||
t.is(await HighlightPairedShortcode('alert();\nalert();', | ||
"js", "", { alwaysWrapLineHighlights: false }), `<pre class="language-js"><code class="language-js"><span class="token function">alert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token function">alert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>`); | ||
}); | ||
test("Base with CRLF EOL, always wrap highlights", async t => { | ||
t.is(await HighlightPairedShortcode('alert();\r\nalert();', | ||
"js", "", { alwaysWrapLineHighlights: true }), `<pre class="language-js"><code class="language-js"><span class="highlight-line"><span class="token function">alert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br><span class="highlight-line"><span class="token function">alert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span></code></pre>`); | ||
}); | ||
test("Base with CRLF EOL, no wrap highlights", async t => { | ||
t.is(await HighlightPairedShortcode('alert();\r\nalert();', | ||
"js", "", { alwaysWrapLineHighlights: false }), `<pre class="language-js"><code class="language-js"><span class="token function">alert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br><span class="token function">alert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>`); | ||
}); | ||
test("Base with custom attributes", async t => { | ||
@@ -11,0 +31,0 @@ t.is(await HighlightPairedShortcode(`alert(); |
const test = require("ava"); | ||
const Eleventy = require('@11ty/eleventy'); | ||
test("Test Highlight JavaScript Function Render", async t => { | ||
test("JavaScript Function", async t => { | ||
let elev = new Eleventy("./test/11tyjs-test/", "./test/11tyjs-test/_site/", { | ||
@@ -14,1 +14,12 @@ configPath: "./test/11tyjs-test/.eleventy.js" | ||
}); | ||
test("JavaScript Function Diff", async t => { | ||
let elev = new Eleventy("./test/11tyjs-diff/", "./test/11tyjs-diff/_site/", { | ||
configPath: "./test/11tyjs-diff/.eleventy.js" | ||
}); | ||
let json = await elev.toJSON(); | ||
t.is(json.length, 1); | ||
let rendered = json[0].content; | ||
t.is(`<pre class="language-diff-js"><code class="language-diff-js"><span class="token deleted-sign deleted language-js"><span class="token prefix deleted">-</span><span class="token keyword">var</span> test<span class="token punctuation">;</span></span></code></pre>`, rendered); | ||
}); |
@@ -26,1 +26,19 @@ const test = require("ava"); | ||
}); | ||
test("Njk Alias", async t => { | ||
let engine = new Liquid(); | ||
let tag = new LiquidHighlightTag(engine); | ||
engine.registerTag("highlight", tag.getObject()); | ||
let rendered = await renderLiquid("{% highlight njk %}{% raw %}hello{% endraw %}{% endhighlight %}", {}, engine); | ||
t.is(`<pre class="language-njk"><code class="language-njk"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">raw</span> <span class="token operator">%</span><span class="token punctuation">}</span><span class="token variable">hello</span><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">endraw</span> <span class="token delimiter punctuation">%}</span></code></pre>`, rendered); | ||
}); | ||
test("Nunjucks alias", async t => { | ||
let engine = new Liquid(); | ||
let tag = new LiquidHighlightTag(engine); | ||
engine.registerTag("highlight", tag.getObject()); | ||
let rendered = await renderLiquid("{% highlight nunjucks %}{% raw %}hello{% endraw %}{% endhighlight %}", {}, engine); | ||
t.is(`<pre class="language-nunjucks"><code class="language-nunjucks"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">raw</span> <span class="token operator">%</span><span class="token punctuation">}</span><span class="token variable">hello</span><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">endraw</span> <span class="token delimiter punctuation">%}</span></code></pre>`, rendered); | ||
}); |
@@ -25,3 +25,39 @@ const test = require("ava"); | ||
test("Markdown with `preAttributes`", t => { | ||
let mdLib = md(); | ||
mdLib.set({ | ||
highlight: markdownPrismJsOptions({ | ||
alwaysWrapLineHighlights: true, | ||
preAttributes: { | ||
// will override class="language-js" | ||
class: ({language}) => "not-a-lang-" + language | ||
} | ||
}) | ||
}); | ||
t.is(mdLib.render(`\`\`\`js | ||
alert(); | ||
\`\`\``).trim(), `<pre class="not-a-lang-js"><code class="language-js"><span class="highlight-line"><span class="token function">alert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span></code></pre>`); | ||
}); | ||
test("Test Njk Alias", t => { | ||
let mdLib = md(); | ||
mdLib.set({ | ||
highlight: markdownPrismJsOptions() | ||
}); | ||
t.is(mdLib.render(`\`\`\`njk | ||
{% raw %}hello{% endraw %} | ||
\`\`\``).trim(), `<pre class="language-njk"><code class="language-njk"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">raw</span> <span class="token operator">%</span><span class="token punctuation">}</span><span class="token variable">hello</span><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">endraw</span> <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>`); | ||
}); | ||
test("Test Nunjucks Alias", t => { | ||
let mdLib = md(); | ||
mdLib.set({ | ||
highlight: markdownPrismJsOptions() | ||
}); | ||
t.is(mdLib.render(`\`\`\`nunjucks | ||
{% raw %}hello{% endraw %} | ||
\`\`\``).trim(), `<pre class="language-nunjucks"><code class="language-nunjucks"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">raw</span> <span class="token operator">%</span><span class="token punctuation">}</span><span class="token variable">hello</span><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token variable">endraw</span> <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>`); | ||
}); | ||
// test("Test Markdown Highlighter Block Comment", t => { | ||
@@ -28,0 +64,0 @@ // let mdLib = md(); |
Sorry, the diff of this file is not supported yet
74063
42
1261
9