Skip to content

Commit 957286a

Browse files
authored
feat: highlightjs-lines — encase every lines with hljs-line (#305)
feat: `highlightjs-lines` — encase every lines with hljs-line
2 parents 404afbd + 8ac4725 commit 957286a

File tree

4 files changed

+168
-1
lines changed

4 files changed

+168
-1
lines changed

.eleventy.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import dotenv from "dotenv"
44
import { DateTime } from "luxon"
55
import highlight from "highlight.js"
66
import highlightDiff from "highlightjs-code-diff"
7+
import highlightjsLines from "./lib/highlightjs-lines.js"
78
import markdownIt from "markdown-it"
89
import anchor from "markdown-it-anchor"
910
import bracketedSpans from "markdown-it-bracketed-spans"
@@ -17,7 +18,7 @@ dotenv.config()
1718

1819
export default function (eleventyConfig) {
1920
const isDevelopment = process.env.NODE_ENV === "development"
20-
const hljs = highlightDiff(highlight)
21+
const hljs = highlightjsLines(highlightDiff(highlight))
2122
const markdownItConfig = markdownIt({
2223
html: true,
2324
linkify: true,

lib/highlightjs-lines.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* This will convert every lines that is not
3+
* starts with - or + (diff-support) to be encase
4+
* inside a div with the class of hljs-line
5+
*
6+
* @param {*} hljs
7+
* @returns
8+
*/
9+
10+
export default function (hljs) {
11+
function highlight(code, options) {
12+
const result = hljs.highlight(code, { ...options, language: options.language })
13+
const lines = result.value.split('\n')
14+
15+
const processedLines = lines.map(line => {
16+
const hasAddition = line.startsWith(`<span class="hljs-addition">+`)
17+
const hasDeletion = line.startsWith(`<span class="hljs-deletion">-`)
18+
const isEmpty = line === ""
19+
let outputLine = line.replace("+ ", "<span class='hljs-indicator'>+</span>").replace("- ", "<span class='hljs-indicator'>-</span>");
20+
if (!isEmpty && !hasAddition && !hasDeletion) {
21+
outputLine = `<span class="hljs-line">${line}</span>`
22+
}
23+
24+
return outputLine
25+
}).join('\n')
26+
27+
return {
28+
...result,
29+
code,
30+
value: processedLines,
31+
language: options.language
32+
}
33+
}
34+
35+
return {
36+
...hljs,
37+
highlight(codeOrLanguageName, optionsOrCode, ignoreIllegals = false) {
38+
return typeof optionsOrCode === 'string'
39+
? highlight(optionsOrCode, { language: codeOrLanguageName, ignoreIllegals })
40+
: highlight(codeOrLanguageName, optionsOrCode)
41+
}
42+
}
43+
}

lib/highlightjs-lines.test.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import highlight from "highlight.js"
2+
import highlightjsLines from "./highlightjs-lines.js"
3+
import highlightDiff from "highlightjs-code-diff"
4+
import markdownIt from "markdown-it"
5+
import { describe, it } from 'node:test'
6+
import assert from "node:assert"
7+
8+
const hljsLinesWithDiff = highlightjsLines(highlightDiff(highlight))
9+
const hljsLines = highlightjsLines(highlight)
10+
11+
describe('Highlight Lines using Markdown With Diff', () => {
12+
const mIt = markdownIt({
13+
html: true,
14+
linkify: true,
15+
typographer: true,
16+
highlight: function (str, lang) {
17+
if (lang) {
18+
try {
19+
return hljsLinesWithDiff.highlight(str, { language: lang }).value
20+
} catch (__) { }
21+
}
22+
return ""
23+
}
24+
})
25+
it('Test With Diff (Deletion)', () => {
26+
const data = `
27+
\`\`\`diff:js
28+
- setTimeout(() => throw new Error(),0)
29+
\`\`\`
30+
`
31+
const value = mIt.render(data)
32+
assert.strictEqual(value, `<pre><code class="language-diff:js"><span class="hljs-deletion"><span class='hljs-indicator'>-</span><span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(),<span class="hljs-number">0</span>)</span>\n</code></pre>\n`)
33+
})
34+
it('Test With Diff (Addition)', () => {
35+
const data = `
36+
\`\`\`diff:js
37+
+ setTimeout(() => throw new Error(),0)
38+
\`\`\`
39+
`
40+
const value = mIt.render(data)
41+
assert.strictEqual(value, `<pre><code class="language-diff:js"><span class="hljs-addition"><span class='hljs-indicator'>+</span><span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(),<span class="hljs-number">0</span>)</span>\n</code></pre>\n`)
42+
})
43+
it('Normal Test', () => {
44+
const data = `
45+
\`\`\`js
46+
let time = new Date()
47+
\`\`\`
48+
`
49+
const value = mIt.render(data)
50+
assert.strictEqual(value, `<pre><code class="language-js"><span class="hljs-line"><span class="hljs-keyword">let</span> time = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>()</span>\n</code></pre>\n`)
51+
})
52+
})
53+
54+
describe("Highlight Lines with Diff", async (t) => {
55+
it("Test With Diff (Deletion)", () => {
56+
const code = ` function helloWorld () {
57+
- return 'Hello'
58+
}
59+
`
60+
const { value } = hljsLinesWithDiff.highlight(code, { language: 'diff:js' })
61+
assert.strictEqual(value, `<span class="hljs-line"> <span class="hljs-keyword">function</span> <span class="hljs-title function_">helloWorld</span> (<span class="hljs-params"></span>) {</span>
62+
<span class="hljs-deletion"><span class='hljs-indicator'>-</span> <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;Hello&#x27;</span></span>
63+
<span class="hljs-line"> }</span>\n`)
64+
})
65+
it("Test With Diff (Addition)", () => {
66+
const code = ` function helloWorld () {
67+
+ return 'Hello, world!'
68+
}
69+
`
70+
const { value } = hljsLinesWithDiff.highlight(code, { language: 'diff:js' })
71+
assert.strictEqual(value, `<span class="hljs-line"> <span class="hljs-keyword">function</span> <span class="hljs-title function_">helloWorld</span> (<span class="hljs-params"></span>) {</span>
72+
<span class="hljs-addition"><span class='hljs-indicator'>+</span> <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;Hello, world!&#x27;</span></span>
73+
<span class="hljs-line"> }</span>\n`)
74+
})
75+
it("Normal Test", () => {
76+
const code = ` function helloWorld () {
77+
return 'Hello'
78+
return 'Hello, world!'
79+
}
80+
`
81+
const { value } = hljsLinesWithDiff.highlight(code, { language: 'diff:js' })
82+
assert.strictEqual(value, `<span class="hljs-line"> <span class="hljs-keyword">function</span> <span class="hljs-title function_">helloWorld</span> (<span class="hljs-params"></span>) {</span>
83+
<span class="hljs-line"> <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;Hello&#x27;</span></span>
84+
<span class="hljs-line"> <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;Hello, world!&#x27;</span></span>
85+
<span class="hljs-line"> }</span>\n`)
86+
})
87+
})
88+
89+
describe("Highlight Lines", async (t) => {
90+
it("Test With Diff (Deletion)", () => {
91+
const code = ` function helloWorld () {
92+
- return 'Hello'
93+
}
94+
`
95+
const { value } = hljsLines.highlight(code, { language: 'js' })
96+
assert.strictEqual(value, `<span class="hljs-line"> <span class="hljs-keyword">function</span> <span class="hljs-title function_">helloWorld</span> (<span class="hljs-params"></span>) {</span>
97+
<span class="hljs-line">- <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;Hello&#x27;</span></span>
98+
<span class="hljs-line"> }</span>\n`)
99+
})
100+
it("Test With Diff (Addition)", () => {
101+
const code = ` function helloWorld () {
102+
+ return 'Hello, world!'
103+
}
104+
`
105+
const { value } = hljsLines.highlight(code, { language: 'js' })
106+
assert.strictEqual(value, `<span class="hljs-line"> <span class="hljs-keyword">function</span> <span class="hljs-title function_">helloWorld</span> (<span class="hljs-params"></span>) {</span>
107+
<span class="hljs-line">+ <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;Hello, world!&#x27;</span></span>
108+
<span class="hljs-line"> }</span>\n`)
109+
})
110+
it("Normal Test", () => {
111+
const code = ` function helloWorld () {
112+
return 'Hello'
113+
return 'Hello, world!'
114+
}
115+
`
116+
const { value } = hljsLines.highlight(code, { language: 'js' })
117+
assert.strictEqual(value, `<span class="hljs-line"> <span class="hljs-keyword">function</span> <span class="hljs-title function_">helloWorld</span> (<span class="hljs-params"></span>) {</span>
118+
<span class="hljs-line"> <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;Hello&#x27;</span></span>
119+
<span class="hljs-line"> <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;Hello, world!&#x27;</span></span>
120+
<span class="hljs-line"> }</span>\n`)
121+
})
122+
})

src/assets/scss/highlight.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ code.hljs {
109109
Additional styling for diff support
110110
*/
111111

112+
.hljs-line,
112113
.hljs-addition,
113114
.hljs-deletion {
114115
--_distance: 1em;

0 commit comments

Comments
 (0)