yoctomarkdown 0.0.1 → 0.0.3
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 +31 -0
- package/README.md +2 -0
- package/package.json +10 -2
- package/src/index.ts +46 -8
- package/tests/index.test.ts +38 -4
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Create a new tagged npm release (patch/minor/major)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Create a new npm release for this repo. The bump type is: $1 (default to "patch" if not provided).
|
|
6
|
+
|
|
7
|
+
Steps to follow exactly:
|
|
8
|
+
|
|
9
|
+
1. Normalize bump type to one of `patch|minor|major`; if empty, use `patch`.
|
|
10
|
+
2. Verify git state before doing anything:
|
|
11
|
+
- current branch must be `main`
|
|
12
|
+
- working tree must be clean
|
|
13
|
+
- run `git fetch origin --tags` and ensure `HEAD` equals `origin/main`
|
|
14
|
+
If any check fails, stop and report.
|
|
15
|
+
3. Run the full repo check suit — stop and report failures.
|
|
16
|
+
4. Read `package.json` and capture both `name` and current `version`.
|
|
17
|
+
5. Compute the next semver version by bumping the selected part.
|
|
18
|
+
6. Guardrails before mutating files:
|
|
19
|
+
- ensure git tag `v<new-version>` does not exist locally or on origin
|
|
20
|
+
- ensure npm version does not already exist: `npm view <package-name>@<new-version> version`
|
|
21
|
+
If either exists, stop and report.
|
|
22
|
+
7. Update the `version` field in `package.json` to `<new-version>`.
|
|
23
|
+
8. Run `bun run build`.
|
|
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 "<new-version>\n<small-changelog>"`.
|
|
26
|
+
11. Push explicitly to main and the exact tag:
|
|
27
|
+
- `git push origin main`
|
|
28
|
+
- `git push origin v<new-version>`
|
|
29
|
+
12. Post-push verification: run `npm view <package-name>@<new-version> version`.
|
|
30
|
+
- If it already exists, report that publish already happened and do **not** ask user to publish again.
|
|
31
|
+
- If it does not exist, run `npm publish`.
|
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yoctomarkdown",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"module": "src/index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"devDependencies": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"yoctocolors": "^2.1.2"
|
|
19
19
|
},
|
|
20
20
|
"bin": {
|
|
21
|
-
"yoctomarkdown": "
|
|
21
|
+
"yoctomarkdown": "src/cli.ts"
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
24
|
"typecheck": "tsc --noEmit",
|
|
@@ -30,5 +30,13 @@
|
|
|
30
30
|
"format": "prettier --write .",
|
|
31
31
|
"format:check": "prettier --check .",
|
|
32
32
|
"test": "bun test"
|
|
33
|
+
},
|
|
34
|
+
"types": "./src/index.ts",
|
|
35
|
+
"exports": {
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./src/index.ts",
|
|
38
|
+
"import": "./src/index.ts",
|
|
39
|
+
"default": "./src/index.ts"
|
|
40
|
+
}
|
|
33
41
|
}
|
|
34
42
|
}
|
package/src/index.ts
CHANGED
|
@@ -83,17 +83,17 @@ export function createHighlighter(options?: Options): Highlighter {
|
|
|
83
83
|
return result;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
function parseLine(line: string,
|
|
86
|
+
function parseLine(line: string, isPartial: boolean): string {
|
|
87
87
|
if (inCodeBlock) {
|
|
88
88
|
if (line.trim().startsWith("```")) {
|
|
89
|
-
inCodeBlock = false;
|
|
89
|
+
if (!isPartial) inCodeBlock = false;
|
|
90
90
|
return theme.codeBlock(line);
|
|
91
91
|
}
|
|
92
92
|
return theme.codeBlock(line);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
if (line.trim().startsWith("```")) {
|
|
96
|
-
inCodeBlock = true;
|
|
96
|
+
if (!isPartial) inCodeBlock = true;
|
|
97
97
|
return theme.codeBlock(line);
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -127,6 +127,9 @@ export function createHighlighter(options?: Options): Highlighter {
|
|
|
127
127
|
return parseInline(line);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
let hasPartial = false;
|
|
131
|
+
let partialLength = 0;
|
|
132
|
+
|
|
130
133
|
return {
|
|
131
134
|
write(chunk: string | Uint8Array): string {
|
|
132
135
|
const text =
|
|
@@ -136,15 +139,50 @@ export function createHighlighter(options?: Options): Highlighter {
|
|
|
136
139
|
const lines = buffer.split("\n");
|
|
137
140
|
buffer = lines.pop() ?? "";
|
|
138
141
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
+
}
|
|
154
|
+
|
|
155
|
+
if (lines.length > 0) {
|
|
156
|
+
out += `${lines.map((line) => parseLine(line, false)).join("\n")}\n`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (buffer.length > 0) {
|
|
160
|
+
out += parseLine(buffer, true);
|
|
161
|
+
hasPartial = true;
|
|
162
|
+
partialLength = buffer.length;
|
|
163
|
+
} else {
|
|
164
|
+
hasPartial = false;
|
|
165
|
+
partialLength = 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return out;
|
|
143
169
|
},
|
|
144
170
|
end(): string {
|
|
145
171
|
if (buffer.length > 0) {
|
|
146
|
-
const out = parseLine(buffer,
|
|
172
|
+
const out = parseLine(buffer, false);
|
|
147
173
|
buffer = "";
|
|
174
|
+
if (hasPartial) {
|
|
175
|
+
const columns =
|
|
176
|
+
typeof process !== "undefined" && process.stdout?.columns
|
|
177
|
+
? process.stdout.columns
|
|
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;
|
|
185
|
+
}
|
|
148
186
|
return out;
|
|
149
187
|
}
|
|
150
188
|
return "";
|
package/tests/index.test.ts
CHANGED
|
@@ -32,6 +32,12 @@ describe("Programmatic Usage: highlightSync", () => {
|
|
|
32
32
|
});
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
+
function expectStreamMatch(res: string, markdown: string) {
|
|
36
|
+
const expected = highlightSync(markdown, { theme: "none" });
|
|
37
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: clear line ansi escape
|
|
38
|
+
expect(res.replace(/[^\n]*\x1b\[2K\r/g, "")).toBe(expected);
|
|
39
|
+
}
|
|
40
|
+
|
|
35
41
|
describe("Programmatic Usage: createHighlighter (Streaming)", () => {
|
|
36
42
|
test("should handle chunks without breaking output", () => {
|
|
37
43
|
const highlighter = createHighlighter({ theme: "none" });
|
|
@@ -55,8 +61,7 @@ describe("Programmatic Usage: createHighlighter (Streaming)", () => {
|
|
|
55
61
|
}
|
|
56
62
|
res += highlighter.end();
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
expect(res).toBe(expected);
|
|
64
|
+
expectStreamMatch(res, markdown);
|
|
60
65
|
});
|
|
61
66
|
|
|
62
67
|
test("should handle random chunk sizes", () => {
|
|
@@ -74,7 +79,36 @@ describe("Programmatic Usage: createHighlighter (Streaming)", () => {
|
|
|
74
79
|
}
|
|
75
80
|
res += highlighter.end();
|
|
76
81
|
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
expectStreamMatch(res, markdown);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("should clear multiple lines when wrapped", () => {
|
|
86
|
+
// Mock columns
|
|
87
|
+
const originalColumns = process.stdout.columns;
|
|
88
|
+
Object.defineProperty(process.stdout, "columns", {
|
|
89
|
+
value: 10,
|
|
90
|
+
configurable: true,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const highlighter = createHighlighter({ theme: "none" });
|
|
94
|
+
// 25 chars, columns = 10, so it takes 3 visual lines
|
|
95
|
+
const chunk1 = "1234567890123456789012345";
|
|
96
|
+
const chunk2 = "67890\n";
|
|
97
|
+
|
|
98
|
+
let res = highlighter.write(chunk1);
|
|
99
|
+
res += highlighter.write(chunk2);
|
|
100
|
+
res += highlighter.end();
|
|
101
|
+
|
|
102
|
+
// The first chunk is written, then cleared. Since it takes 3 lines,
|
|
103
|
+
// clear sequence should have \x1b[1A\x1b[2K repeated twice.
|
|
104
|
+
expect(res).toContain("\x1b[1A\x1b[2K\x1b[1A\x1b[2K");
|
|
105
|
+
|
|
106
|
+
// Restore
|
|
107
|
+
if (originalColumns !== undefined) {
|
|
108
|
+
Object.defineProperty(process.stdout, "columns", {
|
|
109
|
+
value: originalColumns,
|
|
110
|
+
configurable: true,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
79
113
|
});
|
|
80
114
|
});
|