Compare commits

..

3 Commits

14 changed files with 92 additions and 291 deletions

View File

@ -3,10 +3,9 @@ const hasTemplateFormat = require("./src/hasTemplateFormat");
const HighlightPairedShortcode = require("./src/HighlightPairedShortcode"); const HighlightPairedShortcode = require("./src/HighlightPairedShortcode");
const LiquidHighlightTag = require("./src/LiquidHighlightTag"); const LiquidHighlightTag = require("./src/LiquidHighlightTag");
// const CharacterWrap = require("./src/CharacterWrap"); // const CharacterWrap = require("./src/CharacterWrap");
const markdownPrismJs = require("./src/markdownSyntaxHighlightOptions"); const markdownChroma = require("./src/markdownSyntaxHighlightOptions");
module.exports = { module.exports = {
// initArguments: { Prism },
configFunction: function (eleventyConfig, options = {}) { configFunction: function (eleventyConfig, options = {}) {
try { try {
eleventyConfig.versionCheck(pkg["11ty"].compatibility); eleventyConfig.versionCheck(pkg["11ty"].compatibility);
@ -21,9 +20,9 @@ module.exports = {
theme: "onedark", theme: "onedark",
lineNumbers: false, lineNumbers: false,
/* lineNumbersStyle: "table",*/ /* "table" or "inline" */ /* lineNumbersStyle: "table",*/ /* "table" or "inline" */
alwaysWrapLineHighlights: false, //alwaysWrapLineHighlights: false,
// eligible to change the default to \n in a new major version. // eligible to change the default to \n in a new major version.
lineSeparator: "<br>", //lineSeparator: "<br>",
preAttributes: {}, preAttributes: {},
codeAttributes: { codeAttributes: {
theme: "onedark", theme: "onedark",
@ -52,7 +51,7 @@ module.exports = {
if (hasTemplateFormat(options.templateFormats, "md")) { if (hasTemplateFormat(options.templateFormats, "md")) {
// ```js/0,2-3 // ```js/0,2-3
eleventyConfig.addMarkdownHighlighter(markdownPrismJs(options)); eleventyConfig.addMarkdownHighlighter(markdownChroma(options));
} }
// if (hasTemplateFormat(options.templateFormats, "11ty.js")) { // if (hasTemplateFormat(options.templateFormats, "11ty.js")) {

View File

@ -41,3 +41,65 @@ Theme can be set to one of these [themes](https://xyproto.github.io/splash/docs/
- `lineNumbers` will add line numbers starting from 1 for each code block. - `lineNumbers` will add line numbers starting from 1 for each code block.
- `lineNumbersStyle` if `table` is used, then code block will use a table to make it easier to drag and select the code. - `lineNumbersStyle` if `table` is used, then code block will use a table to make it easier to drag and select the code.
## TO DO
- [✅] Support `.liquid` files
- [] Add passed in `code` and `pre` atributes into returned html from chroma
- [] Add testing
- [] Add improve regex for line numbers
- [] Add other arguments that chroma can take (`--html-tab-width`, `--html-highlight-style`, maybe `--html-linkable-lines`)
## Example output
Highlight line 1 and 3
````
```js
let multilineString = `
this is the first line
this is the middle line
this is the last line
`;
```
````
![](./images/hightlight-first-and-third-lines.png)
Line numbers shown and highlighting range of lines 3 through 6
````
```js/3:6/lineNumbers
let multilineString = `
this is the first line
this is the second line
this is the third line
this is the fourth line
this is the fifth line
this is the sixth line
this is the seventh line
this is the eighth line
`;
```
````
![](./images/highlight-range-with-line-numbers.png)
Line numbers shown, line numbers set to start at 200, and highlighting range of lines 202 through 204
````
```js/202:204/lineNumbers/table/lineNumbersStart=200
let multilineString = `
this is the first line
this is the second line
this is the third line
this is the fourth line
this is the fifth line
this is the sixth line
this is the seventh line
this is the eighth line
`;
```
````
![](./images/highlight-range-with-line-numbers-arbitary-start-number.png)

View File

@ -5,63 +5,62 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title> <title></title>
<link rel="stylesheet" href="../test.css"> <link rel="stylesheet" href="../test.css">
<link rel="stylesheet" href="../prism-theme.css">
</head> </head>
<body> <body>
Just JS Just JS
{% highlight js %} {% highlight js %}
function myFunction() { function myFunction() {
return true; return true;
} }
{% endhighlight %} {% endhighlight %}
Just JS multiline Just JS multiline
{% highlight js %} {% highlight js %}
let multilineString = ` let multilineString = `
this is the first line this is the first line
this is the middle line this is the middle line
this is the last line this is the last line
`; `;
{% endhighlight %} {% endhighlight %}
JS + Linehighlight JS + Linehighlight
{% highlight js 1,3 %} {% highlight js 1,3 %}
let multilineString = ` let multilineString = `
this is the first line this is the first line
this is the middle line this is the middle line
this is the last line this is the last line
`; `;
{% endhighlight %} {% endhighlight %}
Swift + show lineNumbers Swift + show lineNumbers
{% highlight swift lineNumbers %} {% highlight swift lineNumbers %}
let multilineString = ` let multilineString = `
this is the first line this is the first line
this is the middle line this is the middle line
this is the last line this is the last line
`; `;
{% endhighlight %} {% endhighlight %}
Swift + show lineNumbers + highlight 1 & 3 Swift + show lineNumbers + highlight 1 & 3
{% highlight swift lineNumbers 1,3 %} {% highlight swift lineNumbers 1,3 %}
let multilineString = ` let multilineString = `
this is the first line this is the first line
this is the middle line this is the middle line
this is the last line this is the last line
`; `;
{% endhighlight %} {% endhighlight %}
Swift + show lineNumbers + highlight 1 & 3 Swift + show lineNumbers + highlight 1 & 3
{% highlight swift lineNumbers 1,3 table %} {% highlight swift lineNumbers 2:3 table %}
let multilineString = ` let multilineString = `
this is the first line this is the first line
this is the middle line this is the middle line
this is the last line this is the last line
`; `;
{% endhighlight %} {% endhighlight %}

View File

@ -4,7 +4,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title> <title></title>
<link rel="stylesheet" href="../test.css"> <link rel="stylesheet" href="../test.css">
<!-- <link rel="stylesheet" href="../prism-theme.css"> -->
</head> </head>
<body> <body>

View File

@ -5,7 +5,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title> <title></title>
<link rel="stylesheet" href="../test.css"> <link rel="stylesheet" href="../test.css">
<link rel="stylesheet" href="../prism-theme.css">
</head> </head>
<body> <body>

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,33 +0,0 @@
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;

View File

@ -1,68 +0,0 @@
const HighlightLines = require("./HighlightLines");
class HighlightLinesGroup {
constructor(str, delimiter) {
this.init(str, delimiter);
}
init(str = "", delimiter = " ") {
this.str = str;
this.delimiter = delimiter;
let split = str.split(this.delimiter);
this.highlights = new HighlightLines(split.length === 1 ? split[0] : "");
this.highlightsAdd = new HighlightLines(split.length === 2 ? split[0] : "");
this.highlightsRemove = new HighlightLines(split.length === 2 ? split[1] : "");
}
isHighlighted(lineNumber) {
return this.highlights.isHighlighted(lineNumber);
}
isHighlightedAdd(lineNumber) {
return this.highlightsAdd.isHighlighted(lineNumber);
}
isHighlightedRemove(lineNumber) {
return this.highlightsRemove.isHighlighted(lineNumber);
}
hasTagMismatch(line) {
let startCount = line.split("<span").length;
let endCount = line.split("</span").length;
if( startCount !== endCount ) {
return true;
}
return false;
}
splitLineMarkup(line, before, after) {
// skip line highlighting if there is an uneven number of <span> or </span> on the line.
// for example, we cant wrap <span> with <span><span></span>
if(this.hasTagMismatch(line)) {
return line;
}
return before + line + after;
}
getLineMarkup(lineNumber, line, extraClasses = []) {
let extraClassesStr = (extraClasses.length ? " " + extraClasses.join(" ") : "");
if (this.isHighlighted(lineNumber)) {
return this.splitLineMarkup(line, `<mark class="highlight-line highlight-line-active${extraClassesStr}">`, `</mark>`);
}
if (this.isHighlightedAdd(lineNumber)) {
return this.splitLineMarkup(line, `<ins class="highlight-line highlight-line-add${extraClassesStr}">`, `</ins>`);
}
if (this.isHighlightedRemove(lineNumber)) {
return this.splitLineMarkup(line, `<del class="highlight-line highlight-line-remove${extraClassesStr}">`, `</del>`);
}
return this.splitLineMarkup( line, `<span class="highlight-line${extraClassesStr}">`, `</span>`);
}
}
module.exports = HighlightLinesGroup;

View File

@ -12,13 +12,7 @@ class LiquidHighlightTag {
let ret = function (highlighter) { let ret = function (highlighter) {
return { return {
parse: function (tagToken, remainTokens) { parse: function (tagToken, remainTokens) {
console.log(">>LIQIUD"); this.args = tagToken.args;
console.log(tagToken.args);
console.log("<<LIQIUD");
let split = tagToken.args.split(" ");
this.language = split.shift();
this.highlightLines = split.join(" ");
this.tokens = []; this.tokens = [];
@ -44,13 +38,9 @@ class LiquidHighlightTag {
return token.raw || token.getText(); return token.raw || token.getText();
}); });
let tokenStr = tokens.join("").trim(); let tokenStr = tokens.join("").trim();
console.log(this.args);
return Promise.resolve( return Promise.resolve(
HighlightPairedShortcode( HighlightPairedShortcode(tokenStr, this.args, options)
tokenStr,
this.language,
this.highlightLines,
options
)
); );
}, },
}; };

View File

@ -1,42 +0,0 @@
const Prism = require("prismjs");
const PrismLoader = require("prismjs/components/index.js");
// Avoid "Language does not exist: " console logs
PrismLoader.silent = true;
const PrismAlias = require("./PrismNormalizeAlias");
module.exports = function(language) {
let diffRemovedRawName = language;
if(language.startsWith("diff-")) {
diffRemovedRawName = language.substr("diff-".length);
}
// aliasing should ignore diff-
let aliasedName = PrismAlias(diffRemovedRawName);
if(!Prism.languages[ aliasedName ]) {
PrismLoader(aliasedName);
}
if(!Prism.languages[ aliasedName ]) {
throw new Error(`"${language}" is not a valid Prism.js language for eleventy-plugin-syntaxhighlight`);
}
if(!language.startsWith("diff-")) {
return Prism.languages[ aliasedName ];
}
// language has diff- prefix
let fullLanguageName = `diff-${aliasedName}`;
if(!Prism.languages.diff) {
PrismLoader("diff");
// Bundled Plugin
require("prismjs/plugins/diff-highlight/prism-diff-highlight");
}
// Store into with aliased keys
// ts -> diff-typescript
// js -> diff-javascript
Prism.languages[ fullLanguageName ] = Prism.languages.diff;
return Prism.languages[ fullLanguageName ];
};

View File

@ -1,42 +0,0 @@
const Prism = require("prismjs");
const HARDCODED_ALIASES = {
njk: "jinja2",
nunjucks: "jinja2",
};
// This was added to make `ts` resolve to `typescript` correctly.
// The Prism loader doesnt seem to always handle aliasing correctly.
module.exports = function(language) {
try {
// Careful this is not public API stuff:
// https://github.com/PrismJS/prism/issues/2146
const PrismComponents = require("prismjs/components.json");
let langs = PrismComponents.languages;
// Manual override
if(HARDCODED_ALIASES[language]) {
language = HARDCODED_ALIASES[language];
}
if(langs[ language ]) {
return language;
}
for(let langName in langs) {
if(Array.isArray(langs[langName].alias)) {
for(let alias of langs[langName].alias) {
if(alias === language) {
return langName;
}
}
} else if(langs[langName].alias === language) {
return langName;
}
}
} catch(e) {
// Couldnt find the components file, aliases may not resolve correctly
// See https://github.com/11ty/eleventy-plugin-syntaxhighlight/issues/19
}
return language;
}

View File

@ -1,62 +0,0 @@
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, 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 getAttributes(attributes, context = {}) {
let langClass = context.language ? `language-${context.language}` : "";
if (!attributes) {
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(
entry => attributeEntryToString(entry, context)
);
return formattedAttributes.length ? ` ${formattedAttributes.join(" ")}` : "";
} else if (typeof attributes === "string") {
throw new Error("Syntax highlighter plugin custom attributes on <pre> and <code> must be an object. Received: " + JSON.stringify(attributes));
}
}
module.exports = getAttributes;