@mui/internal-docs-infra
Version:
MUI Infra - internal documentation creation tools.
126 lines (117 loc) • 3.44 kB
JavaScript
// Example copied from https://github.com/wooorm/starry-night#example-adding-line-numbers
/**
* Counts the number of lines in a HAST tree without mutating it.
* Uses the same logic as starryNightGutter but only returns the count.
* @param tree - The HAST tree to count lines in
* @returns The number of lines in the tree
*/
export function countLines(tree) {
var search = /\r?\n|\r/g;
var index = -1;
var start = 0;
var startTextRemainder = '';
var lineNumber = 0;
while (index + 1 < tree.children.length) {
index += 1;
var child = tree.children[index];
if (child.type === 'text') {
var textStart = 0;
var match = search.exec(child.value);
while (match) {
lineNumber += 1;
start = index + 1;
textStart = match.index + match[0].length;
match = search.exec(child.value);
}
// If we matched, make sure to not drop the text after the last line ending.
if (start === index + 1) {
startTextRemainder = child.value.slice(textStart);
}
}
}
// Check if we have remaining content to process as a line
if (start < tree.children.length || startTextRemainder) {
lineNumber += 1;
}
return lineNumber;
}
export function starryNightGutter(tree) {
/** @type {Array<RootContent>} */
var replacement = [];
var search = /\r?\n|\r/g;
var index = -1;
var start = 0;
var startTextRemainder = '';
var lineNumber = 0;
while (index + 1 < tree.children.length) {
index += 1;
var child = tree.children[index];
if (child.type === 'text') {
var textStart = 0;
var match = search.exec(child.value);
while (match) {
// Nodes in this line.
var _line = tree.children.slice(start, index);
// Prepend text from a partial matched earlier text.
if (startTextRemainder) {
_line.unshift({
type: 'text',
value: startTextRemainder
});
startTextRemainder = '';
}
// Append text from this text.
if (match.index > textStart) {
_line.push({
type: 'text',
value: child.value.slice(textStart, match.index)
});
}
// Add a line, and the eol.
lineNumber += 1;
replacement.push(createLine(_line, lineNumber), {
type: 'text',
value: match[0]
});
start = index + 1;
textStart = match.index + match[0].length;
match = search.exec(child.value);
}
// If we matched, make sure to not drop the text after the last line ending.
if (start === index + 1) {
startTextRemainder = child.value.slice(textStart);
}
}
}
var line = tree.children.slice(start);
// Prepend text from a partial matched earlier text.
if (startTextRemainder) {
line.unshift({
type: 'text',
value: startTextRemainder
});
startTextRemainder = '';
}
if (line.length > 0) {
lineNumber += 1;
replacement.push(createLine(line, lineNumber));
}
// Replace children with new array.
tree.children = replacement;
// Add total line count to root data
if (!tree.data) {
tree.data = {};
}
tree.data.totalLines = lineNumber;
}
function createLine(children, line) {
return {
type: 'element',
tagName: 'span',
properties: {
className: 'line',
dataLineNumber: line
},
children: children
};
}