-
Notifications
You must be signed in to change notification settings - Fork 4
/
rewrapper.mjs
89 lines (73 loc) · 2.28 KB
/
rewrapper.mjs
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
80
81
82
83
84
85
86
87
88
89
export default function (text, columnLength) {
const lines = text.split("\n");
const unwrapped = smooshOverwrappedLines(lines);
const rewrapped = wrapLines(unwrapped, columnLength);
return rewrapped.join("\n");
}
function smooshOverwrappedLines(lines) {
const smooshedLines = [];
let lastLineIsSmushable = false;
for (const line of lines) {
const trimmedLine = line.trim();
if (isStandaloneLine(trimmedLine)) {
smooshedLines.push(line);
lastLineIsSmushable = false;
} else {
if (lastLineIsSmushable && !mustBreakBefore(trimmedLine)) {
smooshedLines[smooshedLines.length - 1] += " " + trimmedLine;
} else {
smooshedLines.push(line.trimRight());
}
lastLineIsSmushable = !mustBreakAfter(trimmedLine);
}
}
return smooshedLines;
}
function wrapLines(lines, columnLength) {
const linesRewrapped = [];
for (const line of lines) {
if (line.length <= columnLength || !shouldRewrap(line)) {
linesRewrapped.push(line);
} else {
linesRewrapped.push(...wrapLine(line, columnLength));
}
}
return linesRewrapped;
}
function wrapLine(line, columnLength) {
const leadingIndent = getLeadingIndent(line, columnLength);
line = line.trimLeft();
const brokenLines = [];
let currentLine = leadingIndent;
let spaceBefore = "";
for (const word of line.split(" ")) {
if (currentLine.length + spaceBefore.length + word.length <= columnLength) {
currentLine += spaceBefore + word;
} else {
if (currentLine !== leadingIndent)
brokenLines.push(currentLine);
currentLine = leadingIndent + word;
}
spaceBefore = " ";
}
brokenLines.push(currentLine);
return brokenLines;
}
function shouldRewrap(line) {
const trimmedLine = line.trim();
return !/^<(dt|th|td)(?:[a-z- "=]+)?>/.test(trimmedLine);
}
function mustBreakAfter(trimmedLine) {
return trimmedLine.endsWith("</dt>") || trimmedLine.endsWith("</li>");
}
function mustBreakBefore(trimmedLine) {
return trimmedLine.startsWith("<td") || trimmedLine.startsWith("<th");
}
function isStandaloneLine(trimmedLine) {
return trimmedLine.length === 0 ||
/^<\/?[a-z- "=]+>$/i.test(trimmedLine) ||
/^<!--.*-->$/.test(trimmedLine);
}
function getLeadingIndent(line) {
return /^(\s*)/.exec(line)[1];
}