yoctomarkdown 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/commands/release.md +1 -1
- package/package.json +1 -1
- package/src/index.ts +13 -26
- package/tests/index.test.ts +110 -26
|
@@ -22,7 +22,7 @@ Steps to follow exactly:
|
|
|
22
22
|
7. Update the `version` field in `package.json` to `<new-version>`.
|
|
23
23
|
8. Run `bun run build`.
|
|
24
24
|
9. Commit all staged and unstaged changes with message: `chore: release v<new-version>`.
|
|
25
|
-
10. Create annotated tag: `git tag -a v<new-version> -m "<
|
|
25
|
+
10. Create annotated tag: `git tag -a v<new-version> -m "<small-changelog>"`.
|
|
26
26
|
11. Push explicitly to main and the exact tag:
|
|
27
27
|
- `git push origin main`
|
|
28
28
|
- `git push origin v<new-version>`
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -128,7 +128,14 @@ export function createHighlighter(options?: Options): Highlighter {
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
let hasPartial = false;
|
|
131
|
-
|
|
131
|
+
|
|
132
|
+
function redrawPartialPrefix(): string {
|
|
133
|
+
return hasPartial ? "\x1b8\x1b[J" : "";
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function renderPartial(line: string, isPartial: boolean): string {
|
|
137
|
+
return `\x1b7${parseLine(line, isPartial)}`;
|
|
138
|
+
}
|
|
132
139
|
|
|
133
140
|
return {
|
|
134
141
|
write(chunk: string | Uint8Array): string {
|
|
@@ -139,30 +146,17 @@ export function createHighlighter(options?: Options): Highlighter {
|
|
|
139
146
|
const lines = buffer.split("\n");
|
|
140
147
|
buffer = lines.pop() ?? "";
|
|
141
148
|
|
|
142
|
-
let out =
|
|
143
|
-
if (hasPartial) {
|
|
144
|
-
const columns =
|
|
145
|
-
typeof process !== "undefined" && process.stdout?.columns
|
|
146
|
-
? process.stdout.columns
|
|
147
|
-
: 80;
|
|
148
|
-
const linesToClear = Math.ceil(partialLength / columns) || 1;
|
|
149
|
-
out += "\x1b[2K\r";
|
|
150
|
-
if (linesToClear > 1) {
|
|
151
|
-
out += "\x1b[1A\x1b[2K".repeat(linesToClear - 1);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
149
|
+
let out = redrawPartialPrefix();
|
|
154
150
|
|
|
155
151
|
if (lines.length > 0) {
|
|
156
152
|
out += `${lines.map((line) => parseLine(line, false)).join("\n")}\n`;
|
|
157
153
|
}
|
|
158
154
|
|
|
159
155
|
if (buffer.length > 0) {
|
|
160
|
-
out +=
|
|
156
|
+
out += renderPartial(buffer, true);
|
|
161
157
|
hasPartial = true;
|
|
162
|
-
partialLength = buffer.length;
|
|
163
158
|
} else {
|
|
164
159
|
hasPartial = false;
|
|
165
|
-
partialLength = 0;
|
|
166
160
|
}
|
|
167
161
|
|
|
168
162
|
return out;
|
|
@@ -172,16 +166,9 @@ export function createHighlighter(options?: Options): Highlighter {
|
|
|
172
166
|
const out = parseLine(buffer, false);
|
|
173
167
|
buffer = "";
|
|
174
168
|
if (hasPartial) {
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
: 80;
|
|
179
|
-
const linesToClear = Math.ceil(partialLength / columns) || 1;
|
|
180
|
-
let clearSeq = "\x1b[2K\r";
|
|
181
|
-
if (linesToClear > 1) {
|
|
182
|
-
clearSeq += "\x1b[1A\x1b[2K".repeat(linesToClear - 1);
|
|
183
|
-
}
|
|
184
|
-
return clearSeq + out;
|
|
169
|
+
const redrawPrefix = redrawPartialPrefix();
|
|
170
|
+
hasPartial = false;
|
|
171
|
+
return redrawPrefix + out;
|
|
185
172
|
}
|
|
186
173
|
return out;
|
|
187
174
|
}
|
package/tests/index.test.ts
CHANGED
|
@@ -32,10 +32,107 @@ describe("Programmatic Usage: highlightSync", () => {
|
|
|
32
32
|
});
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
+
function renderTerminalOutput(
|
|
36
|
+
output: string,
|
|
37
|
+
columns = Number.POSITIVE_INFINITY,
|
|
38
|
+
) {
|
|
39
|
+
const screen: string[][] = [[]];
|
|
40
|
+
let row = 0;
|
|
41
|
+
let column = 0;
|
|
42
|
+
let savedCursor: { row: number; column: number } | null = null;
|
|
43
|
+
|
|
44
|
+
function ensureRow(targetRow: number) {
|
|
45
|
+
while (screen.length <= targetRow) {
|
|
46
|
+
screen.push([]);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function writeChar(char: string) {
|
|
51
|
+
if (column >= columns) {
|
|
52
|
+
row += 1;
|
|
53
|
+
column = 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
ensureRow(row);
|
|
57
|
+
if (!screen[row]) {
|
|
58
|
+
screen[row] = [];
|
|
59
|
+
}
|
|
60
|
+
const currentLine = screen[row];
|
|
61
|
+
if (!currentLine) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
currentLine[column] = char;
|
|
65
|
+
column += 1;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
for (let i = 0; i < output.length; i += 1) {
|
|
69
|
+
const rest = output.slice(i);
|
|
70
|
+
|
|
71
|
+
if (rest.startsWith("\x1b7")) {
|
|
72
|
+
savedCursor = { row, column };
|
|
73
|
+
i += 1;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (rest.startsWith("\x1b8")) {
|
|
78
|
+
if (savedCursor) {
|
|
79
|
+
row = savedCursor.row;
|
|
80
|
+
column = savedCursor.column;
|
|
81
|
+
}
|
|
82
|
+
i += 1;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (rest.startsWith("\x1b[J")) {
|
|
87
|
+
ensureRow(row);
|
|
88
|
+
screen[row] = (screen[row] ?? []).slice(0, column);
|
|
89
|
+
for (let clearRow = row + 1; clearRow < screen.length; clearRow += 1) {
|
|
90
|
+
screen[clearRow] = [];
|
|
91
|
+
}
|
|
92
|
+
i += 2;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (rest.startsWith("\x1b[2K")) {
|
|
97
|
+
ensureRow(row);
|
|
98
|
+
screen[row] = [];
|
|
99
|
+
i += 3;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (rest.startsWith("\x1b[1A")) {
|
|
104
|
+
row = Math.max(0, row - 1);
|
|
105
|
+
i += 3;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const char = output[i];
|
|
110
|
+
if (char === "\n") {
|
|
111
|
+
row += 1;
|
|
112
|
+
column = 0;
|
|
113
|
+
ensureRow(row);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (char === "\r") {
|
|
118
|
+
column = 0;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (char !== undefined && char !== "\x1b") {
|
|
123
|
+
writeChar(char);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return screen
|
|
128
|
+
.map((line) => line.join("").replace(/\s+$/u, ""))
|
|
129
|
+
.join("\n")
|
|
130
|
+
.replace(/\n+$/u, "");
|
|
131
|
+
}
|
|
132
|
+
|
|
35
133
|
function expectStreamMatch(res: string, markdown: string) {
|
|
36
134
|
const expected = highlightSync(markdown, { theme: "none" });
|
|
37
|
-
|
|
38
|
-
expect(res.replace(/[^\n]*\x1b\[2K\r/g, "")).toBe(expected);
|
|
135
|
+
expect(renderTerminalOutput(res)).toBe(renderTerminalOutput(expected));
|
|
39
136
|
}
|
|
40
137
|
|
|
41
138
|
describe("Programmatic Usage: createHighlighter (Streaming)", () => {
|
|
@@ -82,33 +179,20 @@ describe("Programmatic Usage: createHighlighter (Streaming)", () => {
|
|
|
82
179
|
expectStreamMatch(res, markdown);
|
|
83
180
|
});
|
|
84
181
|
|
|
85
|
-
test("should
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
configurable: true,
|
|
91
|
-
});
|
|
182
|
+
test("should redraw wrapped partial lines after an external prefix", () => {
|
|
183
|
+
const prefix = "◆ ";
|
|
184
|
+
const markdown =
|
|
185
|
+
"No `\\x1b[2K` or `\\r` sequences in the streamed text. The ANSI colour codes remain (intentional — those are static style codes from yoctocolors, not cursor-control sequences).\n";
|
|
186
|
+
const splitAt = 134;
|
|
92
187
|
|
|
93
188
|
const highlighter = createHighlighter({ theme: "none" });
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
let res = highlighter.write(chunk1);
|
|
99
|
-
res += highlighter.write(chunk2);
|
|
189
|
+
let res = prefix;
|
|
190
|
+
res += highlighter.write(markdown.slice(0, splitAt));
|
|
191
|
+
res += highlighter.write(markdown.slice(splitAt));
|
|
100
192
|
res += highlighter.end();
|
|
101
193
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// Restore
|
|
107
|
-
if (originalColumns !== undefined) {
|
|
108
|
-
Object.defineProperty(process.stdout, "columns", {
|
|
109
|
-
value: originalColumns,
|
|
110
|
-
configurable: true,
|
|
111
|
-
});
|
|
112
|
-
}
|
|
194
|
+
expect(renderTerminalOutput(res, 120)).toBe(
|
|
195
|
+
renderTerminalOutput(`${prefix}${markdown}`, 120),
|
|
196
|
+
);
|
|
113
197
|
});
|
|
114
198
|
});
|