Refactors Liquid syntax highlighters to add line highlights.
Usage (ranges are space separated): {% highlight js 1,4-6 %} One range Adds `highlight-line-active` to lines 1,4,5,6 {% highlight js 3-4 -1 %} Two ranges (add/remove), remove is N/A Adds `highlight-line-add` to lines 3,4 {% highlight js -1 3-4 %} Two ranges (add/remove), add is N/A Adds `highlight-line-remove` to lines 3,4 {% highlight js 3-4 5,8-10 %} Two ranges, both are used Adds `highlight-line-add` to lines 3-4 Adds `highlight-line-remove` to lines 5,8,9,10
This commit is contained in:
parent
e408e2fe50
commit
963b5d46e6
@ -1,5 +1,5 @@
|
|||||||
const { DateTime } = require("luxon");
|
const { DateTime } = require("luxon");
|
||||||
const liquidjsSyntaxHighlighter = require("./_src/eleventy-liquidjs-tag-highlight-prismjs");
|
const highlighters = require("./_src/eleventy-liquidjs-tag-highlight");
|
||||||
|
|
||||||
function dateToISO(dateObj) {
|
function dateToISO(dateObj) {
|
||||||
return DateTime.fromJSDate(dateObj).toISO({ includeOffset: true, suppressMilliseconds: true });
|
return DateTime.fromJSDate(dateObj).toISO({ includeOffset: true, suppressMilliseconds: true });
|
||||||
@ -25,7 +25,7 @@ module.exports = function(eleventyConfig) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// compatibility with existing {% highlight js %} and others
|
// compatibility with existing {% highlight js %} and others
|
||||||
eleventyConfig.addLiquidTag("highlight", liquidjsSyntaxHighlighter);
|
eleventyConfig.addLiquidTag("highlight", highlighters.prismjs);
|
||||||
|
|
||||||
// only content in the `posts/` directory
|
// only content in the `posts/` directory
|
||||||
eleventyConfig.addCollection("posts", function(collection) {
|
eleventyConfig.addCollection("posts", function(collection) {
|
||||||
|
33
_src/HighlightLines.js
Normal file
33
_src/HighlightLines.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
class HighlightLines {
|
||||||
|
constructor(rangeStr) {
|
||||||
|
this.highlights = this.convertRangeToHash(rangeStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
convertRangeToHash(rangeStr) {
|
||||||
|
let hash = {};
|
||||||
|
if( !rangeStr ) {
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ranges = rangeStr.split(",").map(function(range) {
|
||||||
|
return range.trim();
|
||||||
|
});
|
||||||
|
|
||||||
|
for(let range of ranges) {
|
||||||
|
let startFinish = range.split('-');
|
||||||
|
let start = parseInt(startFinish[0], 10);
|
||||||
|
let end = parseInt(startFinish[1] || start, 10);
|
||||||
|
|
||||||
|
for( let j = start, k = end; j<=k; j++ ) {
|
||||||
|
hash[j] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
isHighlighted(lineNumber) {
|
||||||
|
return !!this.highlights[lineNumber]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = HighlightLines;
|
83
_src/LiquidHighlight.js
Normal file
83
_src/LiquidHighlight.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
const HighlightLines = require('./HighlightLines');
|
||||||
|
|
||||||
|
class LiquidHighlight {
|
||||||
|
constructor(liquidEngine) {
|
||||||
|
this.liquidEngine = liquidEngine;
|
||||||
|
this.hooks = [];
|
||||||
|
this.classHooks = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
addHook(hookFunction) {
|
||||||
|
this.hooks.push(hookFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
addClassHook(hookFunction) {
|
||||||
|
this.classHooks.push(hookFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
getObject() {
|
||||||
|
let ret = function(highlighter) {
|
||||||
|
return {
|
||||||
|
parse: function(tagToken, remainTokens) {
|
||||||
|
let split = tagToken.args.split(" ");
|
||||||
|
|
||||||
|
this.language = split[0];
|
||||||
|
this.highlights = new HighlightLines(split.length === 2 ? split[1] : "");
|
||||||
|
this.highlightsAdd = new HighlightLines(split.length === 3 ? split[1] : "");
|
||||||
|
this.highlightsRemove = new HighlightLines(split.length === 3 ? split[2] : "");
|
||||||
|
|
||||||
|
this.tokens = [];
|
||||||
|
|
||||||
|
var stream = highlighter.liquidEngine.parser.parseStream(remainTokens);
|
||||||
|
|
||||||
|
stream
|
||||||
|
.on('token', token => {
|
||||||
|
if (token.name === 'endhighlight') {
|
||||||
|
stream.stop();
|
||||||
|
} else {
|
||||||
|
this.tokens.push(token);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('end', x => {
|
||||||
|
throw new Error("tag highlight not closed");
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.start();
|
||||||
|
},
|
||||||
|
render: function(scope, hash) {
|
||||||
|
let tokens = this.tokens.map(token => token.raw);
|
||||||
|
let tokenStr = tokens.join('').trim();
|
||||||
|
|
||||||
|
for( let hook of highlighter.hooks ) {
|
||||||
|
tokenStr = hook.call(this, this.language, tokenStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
let lines = tokenStr.split("\n").map(function(line, j) {
|
||||||
|
let classHookClasses = [];
|
||||||
|
for( let classHook of highlighter.classHooks ) {
|
||||||
|
let ret = classHook(this.language, line, j);
|
||||||
|
if( ret ) {
|
||||||
|
classHookClasses.push(ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<div class="highlight-line' +
|
||||||
|
(this.highlights.isHighlighted(j) ? ' highlight-line-active' : '') +
|
||||||
|
(this.highlightsAdd.isHighlighted(j) ? ' highlight-line-add' : '') +
|
||||||
|
(this.highlightsRemove.isHighlighted(j) ? ' highlight-line-remove' : '') +
|
||||||
|
(classHookClasses.length ? " " + classHookClasses.join(" ") : "") +
|
||||||
|
'">' +
|
||||||
|
line +
|
||||||
|
'</div>';
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return Promise.resolve(`<pre class="language-${this.language}"><code class="language-${this.language}">` + lines.join("") + "</code></pre>");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = LiquidHighlight;
|
@ -1,32 +0,0 @@
|
|||||||
module.exports = function(liquidEngine) {
|
|
||||||
|
|
||||||
return {
|
|
||||||
parse: function(tagToken, remainTokens) {
|
|
||||||
this.language = tagToken.args;
|
|
||||||
this.tokens = [];
|
|
||||||
|
|
||||||
var stream = liquidEngine.parser.parseStream(remainTokens);
|
|
||||||
|
|
||||||
stream
|
|
||||||
.on('token', token => {
|
|
||||||
if (token.name === 'endhighlight') {
|
|
||||||
stream.stop();
|
|
||||||
} else {
|
|
||||||
this.tokens.push(token);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.on('end', x => {
|
|
||||||
throw new Error("tag highlight not closed");
|
|
||||||
});
|
|
||||||
|
|
||||||
stream.start();
|
|
||||||
},
|
|
||||||
render: function(scope, hash) {
|
|
||||||
var tokens = this.tokens.map(token => {
|
|
||||||
return token.raw.trim();
|
|
||||||
}).join('').trim();
|
|
||||||
|
|
||||||
return Promise.resolve(`<pre class="language-${this.language}"><code class="language-${this.language}">\n` + tokens + "\n</code></pre>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,37 +0,0 @@
|
|||||||
const Prism = require('prismjs');
|
|
||||||
|
|
||||||
module.exports = function(liquidEngine) {
|
|
||||||
let langMap = {
|
|
||||||
"css": "css",
|
|
||||||
"html": "markup",
|
|
||||||
"js": "javascript"
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
parse: function(tagToken, remainTokens) {
|
|
||||||
this.language = langMap[ tagToken.args ] || tagToken.args;
|
|
||||||
this.tokens = [];
|
|
||||||
|
|
||||||
var stream = liquidEngine.parser.parseStream(remainTokens);
|
|
||||||
|
|
||||||
stream
|
|
||||||
.on('token', token => {
|
|
||||||
if (token.name === 'endhighlight') {
|
|
||||||
stream.stop();
|
|
||||||
} else {
|
|
||||||
this.tokens.push(token);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.on('end', x => {
|
|
||||||
throw new Error("tag highlight not closed");
|
|
||||||
});
|
|
||||||
|
|
||||||
stream.start()
|
|
||||||
},
|
|
||||||
render: function(scope, hash) {
|
|
||||||
var tokens = this.tokens.map(token => token.raw).join('').trim();
|
|
||||||
var html = Prism.highlight(tokens, Prism.languages[ this.language ]);
|
|
||||||
return Promise.resolve(`<pre class="language-${this.language}"><code class="language-${this.language}">` + html + "</code></pre>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
28
_src/eleventy-liquidjs-tag-highlight.js
Normal file
28
_src/eleventy-liquidjs-tag-highlight.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
const Prism = require('prismjs');
|
||||||
|
const LiquidHighlight = require( "./LiquidHighlight" );
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
plain: function(liquidEngine) {
|
||||||
|
let highlight = new LiquidHighlight(liquidEngine);
|
||||||
|
|
||||||
|
highlight.addClassHook(function(language, line) {
|
||||||
|
if( language === "dir" ) {
|
||||||
|
// has trailing slash
|
||||||
|
if( line.match(/\/$/) !== null ) {
|
||||||
|
return "highlight-line-isdir";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return highlight.getObject();
|
||||||
|
},
|
||||||
|
prismjs: function(liquidEngine) {
|
||||||
|
let highlight = new LiquidHighlight(liquidEngine);
|
||||||
|
|
||||||
|
highlight.addHook(function(language, htmlStr, lines) {
|
||||||
|
return Prism.highlight(htmlStr, Prism.languages[ language ]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return highlight.getObject();
|
||||||
|
}
|
||||||
|
};
|
@ -73,6 +73,23 @@ pre {
|
|||||||
margin: .5em 0;
|
margin: .5em 0;
|
||||||
background-color: #f6f6f6;
|
background-color: #f6f6f6;
|
||||||
}
|
}
|
||||||
|
.highlight-line {
|
||||||
|
padding: 0.125em 1em; /* 2px 16px /16 */
|
||||||
|
}
|
||||||
|
.highlight-line-isdir {
|
||||||
|
color: #b0b0b0;
|
||||||
|
background-color: #222;
|
||||||
|
}
|
||||||
|
.highlight-line-active {
|
||||||
|
background-color: #444;
|
||||||
|
background-color: hsla(0, 0%, 27%, .8);
|
||||||
|
}
|
||||||
|
.highlight-line-add {
|
||||||
|
background-color: #45844b;
|
||||||
|
}
|
||||||
|
.highlight-line-remove {
|
||||||
|
background-color: #902f2f;
|
||||||
|
}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
.home {
|
.home {
|
||||||
|
@ -17,7 +17,7 @@ code[class*="language-"], pre[class*="language-"] {
|
|||||||
color: #f8f8f2;
|
color: #f8f8f2;
|
||||||
}
|
}
|
||||||
pre[class*="language-"] {
|
pre[class*="language-"] {
|
||||||
padding: 1em;
|
padding: 1.5em 0;
|
||||||
margin: .5em 0;
|
margin: .5em 0;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user