Press n or j to go to the next uncovered block, b, p or k for the previous block.
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 90 91 92 93 94 95 96 97 98 99 | 39x 39x 16x 1x 25x 15x 15x 8x 15x 7x 7x 9x 9x 9x 9x 11x 7x 7x 7x 9x 24x 24x 24x 2x 2x 22x 14x 4x 4x 3x 11x 8x 8x 21x 7x 7x 7x 3x 4x 4x 9x 9x 7x 7x 21x 7x 1x 7x 3x 3x 3x 3x 1x 3x 7x 4x 7x | /** Check whether the (trimmed) line is at least 3 chars wide and only dashes. */ export function lineIsDashes(rawLine: string): boolean { const line = rawLine.trim(); return line.length >= 3 && line.match(/[^-]/) === null; } export function processBuf(buf: string[]): string[] { if (buf.length === 0) { return buf; } const lines = buf.map((line) => (lineIsDashes(line) ? line.substr(1) : line)); const lastLine = lines[lines.length - 1]; if (lastLine[lastLine.length - 1] === "\n") { // trim newline at the end of the last line. lines[lines.length - 1] = lastLine.substr(0, lastLine.length - 1); } return lines; } function trimTabsAndSpaces(str: string): string { const match = str.match(/^[\t ]*(.*?)[\t ]*$/m); return match ? match[1] : ""; } export function tokenize(lines: string[]): [string, string[]][] { let key: string | null = null; let buf: string[] = []; let wantNewline = false; const rv: [string, string[]][] = []; function flushItem() { if (key !== null) { rv.push([key, processBuf(buf)]); key = null; buf = []; } } for (let i = 0; i < lines.length; i++) { const match = lines[i].match(/^(.*?)(\r?\n)*$/m); const line = match ? `${match[1]}\n` : "\n"; if (line.trimRight() === "---") { wantNewline = false; flushItem(); } else if (key !== null) { if (wantNewline) { wantNewline = false; if (line.match(/^\s*$/)) { continue; } } buf.push(line); } else { const bits = line.split(":"); if (bits.length >= 2) { const [rawKey, ...rest] = bits; key = rawKey.trim(); const firstBit = trimTabsAndSpaces(rest.join(":")); if (!firstBit.match(/^\s*$/)) { buf = [firstBit]; } else { buf = []; wantNewline = true; } } } } flushItem(); return rv; } export function serialize(blocks: [string, string][]): string[] { const rv: string[] = []; blocks.forEach((item, idx) => { const [key, value] = item; if (idx > 0) { rv.push("---\n"); } if (value.match(/([\r\n]|(^[\t ])|([\t ]$))/m)) { rv.push(key + ":\n"); rv.push("\n"); const lines = value.split(/\n/); if (lines[lines.length - 1] === "") { lines.pop(); } lines.forEach((line) => { rv.push(lineIsDashes(line) ? `-${line}\n` : `${line}\n`); }); } else { rv.push(key + ": " + value + "\n"); } }); return rv; } |