Compare commits
No commits in common. "5f3d7238d9ee8b16fc67994ca4b0d5786c465bfc" and "91e57182f373f3b84f348e5adb94da2ea70abc3e" have entirely different histories.
5f3d7238d9
...
91e57182f3
|
@ -3,9 +3,10 @@ const hasTemplateFormat = require("./src/hasTemplateFormat");
|
|||
const HighlightPairedShortcode = require("./src/HighlightPairedShortcode");
|
||||
const LiquidHighlightTag = require("./src/LiquidHighlightTag");
|
||||
// const CharacterWrap = require("./src/CharacterWrap");
|
||||
const markdownChroma = require("./src/markdownSyntaxHighlightOptions");
|
||||
const markdownPrismJs = require("./src/markdownSyntaxHighlightOptions");
|
||||
|
||||
module.exports = {
|
||||
// initArguments: { Prism },
|
||||
configFunction: function (eleventyConfig, options = {}) {
|
||||
try {
|
||||
eleventyConfig.versionCheck(pkg["11ty"].compatibility);
|
||||
|
@ -20,9 +21,9 @@ module.exports = {
|
|||
theme: "onedark",
|
||||
lineNumbers: false,
|
||||
/* lineNumbersStyle: "table",*/ /* "table" or "inline" */
|
||||
//alwaysWrapLineHighlights: false,
|
||||
alwaysWrapLineHighlights: false,
|
||||
// eligible to change the default to \n in a new major version.
|
||||
//lineSeparator: "<br>",
|
||||
lineSeparator: "<br>",
|
||||
preAttributes: {},
|
||||
codeAttributes: {
|
||||
theme: "onedark",
|
||||
|
@ -51,7 +52,7 @@ module.exports = {
|
|||
|
||||
if (hasTemplateFormat(options.templateFormats, "md")) {
|
||||
// ```js/0,2-3
|
||||
eleventyConfig.addMarkdownHighlighter(markdownChroma(options));
|
||||
eleventyConfig.addMarkdownHighlighter(markdownPrismJs(options));
|
||||
}
|
||||
|
||||
// if (hasTemplateFormat(options.templateFormats, "11ty.js")) {
|
||||
|
|
62
README.md
62
README.md
|
@ -41,65 +41,3 @@ 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.
|
||||
- `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)
|
|
@ -5,6 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title></title>
|
||||
<link rel="stylesheet" href="../test.css">
|
||||
<link rel="stylesheet" href="../prism-theme.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -56,7 +57,7 @@ this is the last line
|
|||
|
||||
Swift + show lineNumbers + highlight 1 & 3
|
||||
|
||||
{% highlight swift lineNumbers 2:3 table %}
|
||||
{% highlight swift lineNumbers 1,3 table %}
|
||||
let multilineString = `
|
||||
this is the first line
|
||||
this is the middle line
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title></title>
|
||||
<link rel="stylesheet" href="../test.css">
|
||||
<!-- <link rel="stylesheet" href="../prism-theme.css"> -->
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title></title>
|
||||
<link rel="stylesheet" href="../test.css">
|
||||
<link rel="stylesheet" href="../prism-theme.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 63 KiB |
Binary file not shown.
Before Width: | Height: | Size: 49 KiB |
Binary file not shown.
Before Width: | Height: | Size: 25 KiB |
|
@ -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;
|
|
@ -0,0 +1,68 @@
|
|||
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 can’t 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;
|
|
@ -12,7 +12,13 @@ class LiquidHighlightTag {
|
|||
let ret = function (highlighter) {
|
||||
return {
|
||||
parse: function (tagToken, remainTokens) {
|
||||
this.args = tagToken.args;
|
||||
console.log(">>LIQIUD");
|
||||
console.log(tagToken.args);
|
||||
console.log("<<LIQIUD");
|
||||
let split = tagToken.args.split(" ");
|
||||
|
||||
this.language = split.shift();
|
||||
this.highlightLines = split.join(" ");
|
||||
|
||||
this.tokens = [];
|
||||
|
||||
|
@ -38,9 +44,13 @@ class LiquidHighlightTag {
|
|||
return token.raw || token.getText();
|
||||
});
|
||||
let tokenStr = tokens.join("").trim();
|
||||
console.log(this.args);
|
||||
return Promise.resolve(
|
||||
HighlightPairedShortcode(tokenStr, this.args, options)
|
||||
HighlightPairedShortcode(
|
||||
tokenStr,
|
||||
this.language,
|
||||
this.highlightLines,
|
||||
options
|
||||
)
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
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 ];
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
const Prism = require("prismjs");
|
||||
|
||||
const HARDCODED_ALIASES = {
|
||||
njk: "jinja2",
|
||||
nunjucks: "jinja2",
|
||||
};
|
||||
|
||||
// This was added to make `ts` resolve to `typescript` correctly.
|
||||
// The Prism loader doesn’t 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) {
|
||||
// Couldn’t find the components file, aliases may not resolve correctly
|
||||
// See https://github.com/11ty/eleventy-plugin-syntaxhighlight/issues/19
|
||||
}
|
||||
|
||||
return language;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
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;
|
Loading…
Reference in New Issue