-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.ts
More file actions
79 lines (72 loc) · 1.93 KB
/
index.ts
File metadata and controls
79 lines (72 loc) · 1.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import flatten, {
FlatElement,
FlatNode,
FlatNodes,
FlatText,
} from "@suin/refractor-flatten";
import type { RefractorNode } from "refractor";
function groupByLines(nodes: RefractorNode[]): Array<LineElement> {
return group(flatten(nodes));
}
export default groupByLines;
export type LineElement = {
type: "element";
tagName: "span";
properties: {
className: ["line"];
["data-line-number"]: number;
};
children: FlatNodes;
};
export { FlatNodes, FlatNode, FlatElement, FlatText };
function group(nodes: FlatNodes): Array<LineElement> {
const lineElements: Array<LineElement> = [];
let currentLine = createLineElement(1);
for (const node of nodes) {
const lines = splitByLines(node);
const last = lines.length - 1;
lines.forEach((line, index) => {
if (line.type !== "text" || line.value !== "") {
currentLine.children.push(line);
}
if (index !== last) {
lineElements.push(currentLine);
currentLine = createLineElement(lineElements.length + 1);
}
});
}
if (currentLine.children.length > 0) {
lineElements.push(currentLine);
}
return lineElements;
}
function createLineElement(lineNumber: number): LineElement {
return {
type: "element",
tagName: "span",
properties: {
className: ["line"],
["data-line-number"]: lineNumber,
},
children: [],
};
}
function splitByLines(node: FlatNode): FlatNodes {
if (node.type === "text") {
return splitTextByLines(node);
} else {
const texts = splitTextByLines(node.children[0]);
return texts.map<FlatElement>((text) => ({ ...node, children: [text] }));
}
}
function splitTextByLines(text: FlatText): Array<FlatText> {
if (text.value.length === 0) {
return [text];
}
const values = text.value.split("\n");
const last = values.length - 1;
return values.map<FlatText>((value, index) => ({
type: "text",
value: value + (index === last ? "" : "\n"),
}));
}