Skip to content

abdk-consulting/highlightjs-split-lines

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

highlightjs-split-lines

npm version CI License: MIT

Split Highlight.js highlighted HTML into individually-sanitized lines — each line is a self-contained HTML fragment with all <span> tags properly opened and closed.

Getting per-line highlighted HTML from Highlight.js is surprisingly tricky:

Option 1 — highlight first, then split. Highlight.js wraps tokens in <span> tags that can start on one line and end on another (e.g. a multi-line string or block comment). Splitting the raw .value output on newlines leaves those spans unclosed on some lines and unopened on others, producing invalid HTML that browsers will render incorrectly.

Option 2 — split first, then highlight each line. Highlight.js is a stateful parser: it carries context (open block comments, string continuations, indentation-sensitive modes) from one line into the next. Highlighting each line in isolation breaks that context, so tokens that span multiple lines are misclassified and the result is wrong highlighting.

This package takes the only correct approach: highlight the whole input at once and then post-process the resulting HTML, re-balancing <span> tags at every line boundary so that each line can be rendered independently.


Installation

npm install highlightjs-split-lines

Usage

CommonJS / Node.js

const hljs = require("highlight.js");
const hljsSplitLines = require("highlightjs-split-lines");

const code = `function greet(name) {
  console.log("Hello, " + name);
}`;

const highlighted = hljs.highlight(code, { language: "javascript" }).value;
const lines = hljsSplitLines.default(highlighted);

lines.forEach((line, i) => {
  console.log(`<div class="line">${line}</div>`);
});

ES Modules

import hljs from "highlight.js";
import hljsSplitLines, { hljsSanitizeLines } from "highlightjs-split-lines";

const highlighted = hljs.highlight(code, { language: "javascript" }).value;

// Split and sanitize in one step:
const lines = hljsSplitLines(highlighted);

// Or sanitize a pre-split array:
const rawLines = highlighted.split("\n");
const sanitizedLines = hljsSanitizeLines(rawLines);

API

hljsSplitLines(highlightedCode: string): string[]

The default export. Splits highlightedCode (the .value string returned by hljs.highlight() or hljs.highlightAuto()) on any line-ending sequence (\n, \r\n, \r, or \n\r) and returns an array of HTML strings where every <span> tag is balanced within its line.

const lines = hljsSplitLines(hljs.highlight(code, { language: "js" }).value);
// lines[0] → '<span class="hljs-keyword">function</span> <span class="hljs-title function_">greet</span>...'
// lines[1] → '  <span class="hljs-variable language_">console</span>...'

hljsSanitizeLines(lines: string[]): string[]

A named export for when you've already split the code yourself. Takes an array of raw HTML strings (which may have unbalanced <span> tags) and returns a new array where every element is a balanced HTML fragment.

Each line is prefixed with the opening tags still active from preceding lines and suffixed with the matching closing tags.

const rawLines = highlighted.split("\n");
const sanitized = hljsSanitizeLines(rawLines);

Example

Given this JavaScript:

function greet(name) {
  return `Hello, ${name}!`;
}

hljs.highlight() may produce output like:

<span class="hljs-keyword">function</span> <span class="hljs-title function_">greet</span>(<span class="hljs-params">name</span>) {
  <span class="hljs-keyword">return</span> <span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>;
}

Notice the hljs-string span opens on line 2 and the inner hljs-subst span is also nested inside it. Splitting on \n would leave these spans unclosed on some lines. hljsSplitLines ensures every line can stand alone:

<!-- line 1 -->
<span class="hljs-keyword">function</span> <span class="hljs-title function_">greet</span>(<span class="hljs-params">name</span>) {
<!-- line 2 -->
  <span class="hljs-keyword">return</span> <span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>;
<!-- line 3 -->
}

Compatibility

This package processes the HTML string output of Highlight.js and has no runtime dependency on it. Any version of Highlight.js that produces <span>-based HTML output is supported.

Node.js highlightjs-split-lines
≥ 18

License

MIT © ABDK Consulting

About

Split code, highlighted by Highlight.js, into lines, preserving highlighting

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors