Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
[Highlight.js + line number] This snippet adds line number support to Highlight.js. Besides, special css trick is applied to stop the line numbers from being selected and copied. #tags: highlight, lepton
import HighlightJS from 'highlight.js'
createHighlightedCodeBlock (content, language) {
let lineNumber = 0
const highlightedContent = HighlightJS.highlightAuto(content, [language]).value
/* Highlight.js wraps comment blocks inside <span class="hljs-comment"></span>.
However, when the multi-line comment block is broken down into diffirent
table rows, only the first row, which is appended by the <span> tag, is
highlighted. The following code fixes it by appending <span> to each line
of the comment block. */
const commentPattern = /<span class="hljs-comment">(.|\n)*?<\/span>/g
const adaptedHighlightedContent = highlightedContent.replace(commentPattern, data => {
return data.replace(/\r?\n/g, () => {
return '\n<span class="hljs-comment">'
})
})
const contentTable = adaptedHighlightedContent.split(/\r?\n/).map(lineContent => {
return `<tr>
<td class='line-number' data-pseudo-content=${++lineNumber}></td>
<td>${lineContent}</td>
</tr>`
}).join('')
return `<pre><code><table class='code-table'>${contentTable}</table></code></pre>`
}
/*
* Transform the snippet from plain text to html markup which includes line number
* support. This method returns an object that can be consumed by a React component.
* @content plain text for snippet
* @language the language for the snippet
*/
createMarkup (content, language) {
return { __html: this.createHighlightedCodeBlock(content, language) }
}
// Consumed by React
// <div dangerouslySetInnerHTML={ this.createMarkup(content, language) }/>
.line-number {
text-align: right;
padding-right: 20px;
display: inline-block;
color: rgba(0,0,0,0.2);
width: 40px;
font-size: 11px;
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
/* Technique to disable line numbers from being selected and copied.
Checkout this post for more details http://codepen.io/danoc/pen/ByGKZv */
[data-pseudo-content]::before,
[data-pseudo-content--before]::before,
[data-pseudo-content--after]::after {
content: attr(data-pseudo-content);
}
@mberneti
Copy link

mberneti commented Apr 10, 2020

well done

@arenn23
Copy link

arenn23 commented Jul 1, 2021

Very well done. Thank you so much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment