cutline 0.0.1

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/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # Cutline
2
+
3
+ Generate Markdown API reference snippets from a TypeScript entry module.
4
+
5
+ `cutline` reads the public surface exported from an entry module (default
6
+ `src/index.ts`) and turns each exported symbol into Markdown that a docs site
7
+ can transclude with [pymdownx snippets](https://facelessuser.github.io/pymdown-extensions/extensions/snippets/)
8
+ (`--8<-- "generated/api/Name.md"`), so the signatures shown in the docs are
9
+ always the ones in source. Two flavours are emitted per symbol:
10
+
11
+ - `Name.md` — a parsed datasheet block (lead prose + a member list with each
12
+ member's kind, name, type, and docs) as raw HTML.
13
+ - `Name.bare.md` — the bare declaration in a fenced code block, for an
14
+ at-a-glance "shape" inline in the guides.
15
+
16
+ ## Usage
17
+
18
+ ```sh
19
+ cutline [options]
20
+ ```
21
+
22
+ | Option | Default | Description |
23
+ | --- | --- | --- |
24
+ | `--tsconfig <path>` | `tsconfig.json` | tsconfig to load |
25
+ | `--entry <path>` | `src/index.ts` | entry module whose exports define the public surface |
26
+ | `--out <dir>` | `generated/api` | output directory |
27
+ | `--fence <lang>` | `ts` | bare code fence language |
28
+ | `--bare` / `--no-bare` | `--bare` | also emit a fenced `.bare.md` shape copy |
29
+ | `--unwrap-links` / `--no-unwrap-links` | `--unwrap-links` | unwrap `{@link X}` references into plain `X` |
30
+ | `--clean` / `--no-clean` | `--clean` | clear the output directory first |
31
+
32
+ ## Library
33
+
34
+ The pipeline is split so it can be exercised without touching disk:
35
+
36
+ ```ts
37
+ import { ApiDocGenerator } from "cutline";
38
+
39
+ const generator = new ApiDocGenerator({ entryFile: "src/public.ts" });
40
+ const symbols = generator.describe(sourceFile); // ApiSymbol[]
41
+ const snippet = generator.render(symbols[0]); // Snippet
42
+ generator.run(); // read tsconfig, render all, write files
43
+ ```
44
+
45
+ ## Development
46
+
47
+ ```sh
48
+ pnpm install
49
+ pnpm test
50
+ pnpm run start -- --entry src/index.ts --out generated/api
51
+ ```
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { type ApiDocsConfig } from "./index.js";
3
+ export declare function parseCliConfig(argv?: string[]): Partial<ApiDocsConfig>;
package/dist/cli.js ADDED
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Command-line front end for {@link ApiDocGenerator}. Reads the entry module's
4
+ * public surface and writes the Markdown snippets, with every setting overridable:
5
+ * tsx src/cli.ts --entry src/public.ts --out docs/api --fence typescript --no-bare
6
+ */
7
+ import { fileURLToPath } from "node:url";
8
+ import { ApiDocGenerator, DEFAULT_CONFIG } from "./index.js";
9
+ export function parseCliConfig(argv = process.argv.slice(2)) {
10
+ const overrides = {};
11
+ const value = (i) => {
12
+ const v = argv[i + 1];
13
+ if (v === undefined || v.startsWith("--"))
14
+ throw new Error(`Missing value for ${argv[i]}`);
15
+ return v;
16
+ };
17
+ for (let i = 0; i < argv.length; i++) {
18
+ switch (argv[i]) {
19
+ case "--tsconfig":
20
+ overrides.tsConfigFilePath = value(i++);
21
+ break;
22
+ case "--entry":
23
+ overrides.entryFile = value(i++);
24
+ break;
25
+ case "--out":
26
+ overrides.outDir = value(i++);
27
+ break;
28
+ case "--fence":
29
+ overrides.fenceLanguage = value(i++);
30
+ break;
31
+ case "--bare":
32
+ overrides.emitBare = true;
33
+ break;
34
+ case "--no-bare":
35
+ overrides.emitBare = false;
36
+ break;
37
+ case "--unwrap-links":
38
+ overrides.unwrapLinks = true;
39
+ break;
40
+ case "--no-unwrap-links":
41
+ overrides.unwrapLinks = false;
42
+ break;
43
+ case "--clean":
44
+ overrides.cleanOutDir = true;
45
+ break;
46
+ case "--no-clean":
47
+ overrides.cleanOutDir = false;
48
+ break;
49
+ case "-h":
50
+ case "--help":
51
+ printHelp();
52
+ process.exit(0);
53
+ break;
54
+ default:
55
+ throw new Error(`Unknown argument: ${argv[i]}`);
56
+ }
57
+ }
58
+ return overrides;
59
+ }
60
+ function printHelp() {
61
+ console.log(`cutline — generate Markdown API snippets from a TypeScript entry module
62
+
63
+ Usage: cutline [options]
64
+
65
+ Options:
66
+ --tsconfig <path> tsconfig to load (default: ${DEFAULT_CONFIG.tsConfigFilePath})
67
+ --entry <path> entry module (default: ${DEFAULT_CONFIG.entryFile})
68
+ --out <dir> output directory (default: ${DEFAULT_CONFIG.outDir})
69
+ --fence <lang> bare code fence language (default: ${DEFAULT_CONFIG.fenceLanguage})
70
+ --bare | --no-bare emit fenced shape copy (default: ${DEFAULT_CONFIG.emitBare})
71
+ --unwrap-links | --no-unwrap-links unwrap {@link X} (default: ${DEFAULT_CONFIG.unwrapLinks})
72
+ --clean | --no-clean clear out dir first (default: ${DEFAULT_CONFIG.cleanOutDir})
73
+ -h, --help show this help`);
74
+ }
75
+ function main() {
76
+ const names = new ApiDocGenerator(parseCliConfig()).run();
77
+ console.log(`Generated ${names.length} API snippets: ${names.sort().join(", ")}`);
78
+ }
79
+ // Run only when executed directly, not when imported (e.g. by tests).
80
+ if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
81
+ main();
82
+ }
83
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ import { type SourceFile } from "ts-morph";
2
+ export interface ApiDocsConfig {
3
+ /** tsconfig used to load the project. */
4
+ tsConfigFilePath: string;
5
+ /** Entry module whose exported declarations define the public surface. */
6
+ entryFile: string;
7
+ /** Directory snippets are written to. */
8
+ outDir: string;
9
+ /** Fence info-string for the bare code blocks (e.g. "ts", "typescript"). */
10
+ fenceLanguage: string;
11
+ /** Also emit a `.bare.md` (fenced declaration) variant of every snippet. */
12
+ emitBare: boolean;
13
+ /** Unwrap `{@link X}` references into plain `X`. */
14
+ unwrapLinks: boolean;
15
+ /** Remove the output directory before writing (fresh run). */
16
+ cleanOutDir: boolean;
17
+ }
18
+ export declare const DEFAULT_CONFIG: ApiDocsConfig;
19
+ /** A documented `@param` of a function or method. */
20
+ export interface ParamDoc {
21
+ name: string;
22
+ doc: string;
23
+ }
24
+ /** What a member is, which the reference shows as a tag in the gutter. */
25
+ export type FieldKind = "property" | "method" | "accessor" | "function" | "const";
26
+ /** One member of an interface or namespace. Text fields are raw (unescaped). */
27
+ export interface Field {
28
+ name: string;
29
+ kind: FieldKind;
30
+ /** `Type` for a value, or `(params): Return` for a callable. Empty when the field is a nested object. */
31
+ type: string;
32
+ optional: boolean;
33
+ readonly: boolean;
34
+ doc: string;
35
+ params: ParamDoc[];
36
+ /** Members of an inline object type, so nested shapes keep their hierarchy. */
37
+ children: Field[];
38
+ }
39
+ /** An exported symbol reduced to what the reference renders. */
40
+ export interface ApiSymbol {
41
+ /** The symbol's name (e.g. `Action`, `simulator`). */
42
+ name: string;
43
+ /** Output basename, sans extension (e.g. `Action`, `simulator.ns`). */
44
+ file: string;
45
+ kind: "interface" | "namespace";
46
+ doc: string;
47
+ fields: Field[];
48
+ /** The bare declaration body (pre-fence): real TS for the `.bare.md` variant. */
49
+ bare: string;
50
+ }
51
+ /** The Markdown rendered for one symbol. */
52
+ export interface Snippet {
53
+ name: string;
54
+ file: string;
55
+ /** `<file>.md` — the parsed datasheet block. */
56
+ full: string;
57
+ /** `<file>.bare.md` — the fenced bare declaration. */
58
+ bare: string;
59
+ }
60
+ /** Remove the common leading indentation a nested declaration carries. */
61
+ export declare function dedentBlock(code: string): string;
62
+ export declare class ApiDocGenerator {
63
+ private readonly config;
64
+ constructor(config?: Partial<ApiDocsConfig>);
65
+ /** Read the configured tsconfig, render every export, write the files, and return the names. */
66
+ run(): string[];
67
+ /** Render every exported symbol of an entry module to its Markdown snippet(s). */
68
+ generate(index: SourceFile): Snippet[];
69
+ /** Reduce every exported symbol of an entry module to the parsed model (no rendering). */
70
+ describe(index: SourceFile): ApiSymbol[];
71
+ private describeSymbol;
72
+ private describeInterface;
73
+ private describeNamespace;
74
+ private fieldsFrom;
75
+ private fieldFromProperty;
76
+ private fieldFromMethod;
77
+ private fieldFromGetter;
78
+ private fieldFromFunction;
79
+ private fieldFromConst;
80
+ /** A `(params): Return` call signature with the body stripped. */
81
+ private signature;
82
+ private paramsFrom;
83
+ /** Unwrap `{@link X}` and collapse whitespace. Escaping happens at render time. */
84
+ private text;
85
+ /** Render one symbol to its `.md` (datasheet) and `.bare.md` (fenced) snippets. */
86
+ render(symbol: ApiSymbol): Snippet;
87
+ /**
88
+ * The datasheet body as one raw-HTML block. It uses only `<div>`/`<span>` (never
89
+ * `<p>`) and no blank lines, so a host page can keep its markdown `### heading`
90
+ * (for the anchor and TOC entry) without Markdown's paragraph rules reflowing
91
+ * this raw HTML into stray paragraphs.
92
+ */
93
+ private renderBody;
94
+ private renderFields;
95
+ private renderField;
96
+ private renderParams;
97
+ /** A declaration with its JSDoc removed, dedented, and the leading `export ` dropped. */
98
+ private bareDeclaration;
99
+ /** A namespace's bare shape: one signature per member, no JSDoc. */
100
+ private bareNamespace;
101
+ private fence;
102
+ private prepareOutDir;
103
+ private writeSnippet;
104
+ }
package/dist/index.js ADDED
@@ -0,0 +1,301 @@
1
+ /**
2
+ * API signature codegen.
3
+ *
4
+ * Reads the public surface exported from an entry module (default `src/index.ts`)
5
+ * and turns each exported symbol into Markdown the docs transclude with pymdownx
6
+ * snippets (`--8<-- "generated/api/Name.md"`), so the signatures shown are always
7
+ * the ones in source. Two flavours per symbol:
8
+ * - `Name.md` a parsed datasheet block (lead prose + a member list with
9
+ * each member's kind, name, type, and docs) as raw HTML.
10
+ * - `Name.bare.md` the bare declaration in a fenced code block, for an
11
+ * at-a-glance "shape" inline in the guides.
12
+ *
13
+ * The pipeline is split so it can be exercised without touching disk:
14
+ * describe(sourceFile) -> ApiSymbol[] the parsed model
15
+ * render(symbol) -> Snippet the Markdown for one symbol
16
+ * run() read tsconfig, render all, write files
17
+ */
18
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
19
+ import { join } from "node:path";
20
+ import { Node, Project, } from "ts-morph";
21
+ export const DEFAULT_CONFIG = {
22
+ tsConfigFilePath: "tsconfig.json",
23
+ entryFile: "src/index.ts",
24
+ outDir: "generated/api",
25
+ fenceLanguage: "ts",
26
+ emitBare: true,
27
+ unwrapLinks: true,
28
+ cleanOutDir: true,
29
+ };
30
+ /* ----------------------------------------------------------- text helpers */
31
+ /** Remove the common leading indentation a nested declaration carries. */
32
+ export function dedentBlock(code) {
33
+ const lines = code.split("\n");
34
+ const indents = lines
35
+ .slice(1)
36
+ .filter((l) => l.trim().length > 0)
37
+ .map((l) => l.match(/^[ \t]*/)?.[0].length ?? 0);
38
+ const common = indents.length ? Math.min(...indents) : 0;
39
+ if (common === 0)
40
+ return code;
41
+ return [lines[0], ...lines.slice(1).map((l) => l.slice(common))].join("\n");
42
+ }
43
+ function escapeHtml(text) {
44
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
45
+ }
46
+ /** Pull the description and any `@param` docs off a node's leading JSDoc. */
47
+ function docOf(node) {
48
+ if (!Node.isJSDocable(node))
49
+ return { doc: "", params: [] };
50
+ const jsDoc = node.getJsDocs().at(0);
51
+ if (!jsDoc)
52
+ return { doc: "", params: [] };
53
+ const params = jsDoc
54
+ .getTags()
55
+ .filter(Node.isJSDocParameterTag)
56
+ // TSDoc allows a hyphen between the name and its description (`@param x - text`).
57
+ .map((tag) => ({ name: tag.getName(), doc: (tag.getCommentText() ?? "").trim().replace(/^-\s*/, "") }));
58
+ return { doc: jsDoc.getDescription().trim(), params };
59
+ }
60
+ /* ------------------------------------------------------------- generator */
61
+ export class ApiDocGenerator {
62
+ config;
63
+ constructor(config = {}) {
64
+ this.config = { ...DEFAULT_CONFIG, ...config };
65
+ }
66
+ /** Read the configured tsconfig, render every export, write the files, and return the names. */
67
+ run() {
68
+ const project = new Project({ tsConfigFilePath: this.config.tsConfigFilePath });
69
+ const index = project.getSourceFileOrThrow(this.config.entryFile);
70
+ this.prepareOutDir();
71
+ const snippets = this.generate(index);
72
+ for (const snippet of snippets)
73
+ this.writeSnippet(snippet);
74
+ return snippets.map((s) => s.name);
75
+ }
76
+ /** Render every exported symbol of an entry module to its Markdown snippet(s). */
77
+ generate(index) {
78
+ return this.describe(index).map((symbol) => this.render(symbol));
79
+ }
80
+ /** Reduce every exported symbol of an entry module to the parsed model (no rendering). */
81
+ describe(index) {
82
+ const symbols = [];
83
+ for (const [name, declarations] of index.getExportedDeclarations()) {
84
+ symbols.push(...this.describeSymbol(name, declarations[0]));
85
+ }
86
+ return symbols;
87
+ }
88
+ /* ---- extraction ---- */
89
+ describeSymbol(name, decl) {
90
+ if (Node.isInterfaceDeclaration(decl)) {
91
+ return [this.describeInterface(name, decl.getMembers(), decl)];
92
+ }
93
+ if (Node.isTypeAliasDeclaration(decl)) {
94
+ const typeNode = decl.getTypeNode();
95
+ const members = typeNode && Node.isTypeLiteral(typeNode) ? typeNode.getMembers() : [];
96
+ return [this.describeInterface(name, members, decl)];
97
+ }
98
+ if (Node.isModuleDeclaration(decl)) {
99
+ return this.describeNamespace(name, decl);
100
+ }
101
+ return [];
102
+ }
103
+ describeInterface(name, members, decl) {
104
+ return {
105
+ name,
106
+ file: name,
107
+ kind: "interface",
108
+ doc: this.text(docOf(decl).doc),
109
+ fields: this.fieldsFrom(members),
110
+ bare: this.bareDeclaration(decl.getText()),
111
+ };
112
+ }
113
+ describeNamespace(name, decl) {
114
+ const fields = [
115
+ ...decl.getVariableDeclarations().map((v) => this.fieldFromConst(v, name)),
116
+ ...decl.getFunctions().map((fn) => this.fieldFromFunction(fn, name)),
117
+ ];
118
+ const namespace = {
119
+ name,
120
+ // `.ns` suffix avoids colliding with a same-named interface on a
121
+ // case-insensitive filesystem (e.g. `simulator` vs `Simulator`).
122
+ file: `${name}.ns`,
123
+ kind: "namespace",
124
+ doc: this.text(docOf(decl).doc),
125
+ fields,
126
+ bare: this.bareNamespace(fields),
127
+ };
128
+ // Interfaces declared inside the namespace are referenced by its signatures
129
+ // but aren't top-level exports, so describe them too.
130
+ const interfaces = decl
131
+ .getInterfaces()
132
+ .map((iface) => this.describeInterface(iface.getName(), iface.getMembers(), iface));
133
+ return [namespace, ...interfaces];
134
+ }
135
+ fieldsFrom(members) {
136
+ const fields = [];
137
+ for (const member of members) {
138
+ if (Node.isPropertySignature(member))
139
+ fields.push(this.fieldFromProperty(member));
140
+ else if (Node.isMethodSignature(member))
141
+ fields.push(this.fieldFromMethod(member));
142
+ else if (Node.isGetAccessorDeclaration(member))
143
+ fields.push(this.fieldFromGetter(member));
144
+ }
145
+ return fields;
146
+ }
147
+ fieldFromProperty(prop) {
148
+ const { doc, params } = docOf(prop);
149
+ const typeNode = prop.getTypeNode();
150
+ const children = typeNode && Node.isTypeLiteral(typeNode) ? this.fieldsFrom(typeNode.getMembers()) : [];
151
+ const type = children.length ? "" : this.text(typeNode?.getText() ?? prop.getType().getText());
152
+ return {
153
+ name: prop.getName(),
154
+ kind: "property",
155
+ type,
156
+ optional: prop.hasQuestionToken(),
157
+ readonly: prop.isReadonly(),
158
+ doc: this.text(doc),
159
+ params: this.paramsFrom(params),
160
+ children,
161
+ };
162
+ }
163
+ fieldFromMethod(method) {
164
+ const { doc, params } = docOf(method);
165
+ return {
166
+ name: method.getName(),
167
+ kind: "method",
168
+ type: this.signature(method),
169
+ optional: method.hasQuestionToken(),
170
+ readonly: false,
171
+ doc: this.text(doc),
172
+ params: this.paramsFrom(params),
173
+ children: [],
174
+ };
175
+ }
176
+ fieldFromGetter(getter) {
177
+ const ret = getter.getReturnTypeNode()?.getText() ?? getter.getReturnType().getText();
178
+ return {
179
+ name: getter.getName(),
180
+ kind: "accessor",
181
+ type: this.text(ret),
182
+ optional: false,
183
+ readonly: false,
184
+ doc: this.text(docOf(getter).doc),
185
+ params: [],
186
+ children: [],
187
+ };
188
+ }
189
+ fieldFromFunction(fn, namespace) {
190
+ const { doc, params } = docOf(fn);
191
+ return {
192
+ name: `${namespace}.${fn.getName()}`,
193
+ kind: "function",
194
+ type: this.signature(fn),
195
+ optional: false,
196
+ readonly: false,
197
+ doc: this.text(doc),
198
+ params: this.paramsFrom(params),
199
+ children: [],
200
+ };
201
+ }
202
+ fieldFromConst(decl, namespace) {
203
+ const type = decl.getTypeNode()?.getText() ?? decl.getType().getText();
204
+ const statement = decl.getVariableStatement();
205
+ return {
206
+ name: `${namespace}.${decl.getName()}`,
207
+ kind: "const",
208
+ type: this.text(type),
209
+ optional: false,
210
+ readonly: false,
211
+ doc: this.text(statement ? docOf(statement).doc : ""),
212
+ params: [],
213
+ children: [],
214
+ };
215
+ }
216
+ /** A `(params): Return` call signature with the body stripped. */
217
+ signature(fn) {
218
+ const params = fn
219
+ .getParameters()
220
+ .map((p) => p.getText())
221
+ .join(", ");
222
+ const ret = fn.getReturnTypeNode()?.getText() ?? fn.getReturnType().getText();
223
+ return this.text(`(${params}): ${ret}`);
224
+ }
225
+ paramsFrom(params) {
226
+ return params.map((p) => ({ name: p.name, doc: this.text(p.doc) }));
227
+ }
228
+ /** Unwrap `{@link X}` and collapse whitespace. Escaping happens at render time. */
229
+ text(raw) {
230
+ const unwrapped = this.config.unwrapLinks ? raw.replace(/\{@link\s+([^}|]+)(\|[^}]+)?\}/g, "$1") : raw;
231
+ return unwrapped.replace(/\s+/g, " ").trim();
232
+ }
233
+ /* ---- rendering ---- */
234
+ /** Render one symbol to its `.md` (datasheet) and `.bare.md` (fenced) snippets. */
235
+ render(symbol) {
236
+ return { name: symbol.name, file: symbol.file, full: this.renderBody(symbol), bare: this.fence(symbol.bare) };
237
+ }
238
+ /**
239
+ * The datasheet body as one raw-HTML block. It uses only `<div>`/`<span>` (never
240
+ * `<p>`) and no blank lines, so a host page can keep its markdown `### heading`
241
+ * (for the anchor and TOC entry) without Markdown's paragraph rules reflowing
242
+ * this raw HTML into stray paragraphs.
243
+ */
244
+ renderBody(symbol) {
245
+ const lead = symbol.doc ? `<div class="api-lead">${escapeHtml(symbol.doc)}</div>` : "";
246
+ const fields = symbol.fields.length ? this.renderFields(symbol.fields) : "";
247
+ return `<div class="api-body">${lead}${fields}</div>\n`;
248
+ }
249
+ renderFields(fields) {
250
+ return `<div class="api-fields">${fields.map((f) => this.renderField(f)).join("")}</div>`;
251
+ }
252
+ renderField(field) {
253
+ const tag = `<span class="api-kind k-${field.kind}"></span>`;
254
+ const readonly = field.readonly ? `<span class="api-readonly">readonly</span>` : "";
255
+ const optional = field.optional ? `<span class="api-opt">?</span>` : "";
256
+ const type = field.type ? `<span class="api-type">${escapeHtml(field.type)}</span>` : "";
257
+ const head = `<div class="api-field-head">${readonly}<span class="api-name">${escapeHtml(field.name)}</span>${optional}${type}</div>`;
258
+ const doc = field.doc ? `<div class="api-field-doc">${escapeHtml(field.doc)}</div>` : "";
259
+ const params = field.params.length ? this.renderParams(field.params) : "";
260
+ const children = field.children.length ? this.renderFields(field.children) : "";
261
+ return `<div class="api-field f-${field.kind}">${tag}${head}${doc}${params}${children}</div>`;
262
+ }
263
+ renderParams(params) {
264
+ const rows = params
265
+ .map((p) => {
266
+ const doc = p.doc ? `<span class="api-param-doc">${escapeHtml(p.doc)}</span>` : "";
267
+ return `<div class="api-param"><span class="api-name">${escapeHtml(p.name)}</span>${doc}</div>`;
268
+ })
269
+ .join("");
270
+ return `<div class="api-params"><div class="api-params-label">Parameters</div>${rows}</div>`;
271
+ }
272
+ /* ---- bare (fenced) variant ---- */
273
+ /** A declaration with its JSDoc removed, dedented, and the leading `export ` dropped. */
274
+ bareDeclaration(code) {
275
+ return dedentBlock(code)
276
+ .replace(/(^|\n)export\s+/g, "$1")
277
+ .replace(/[ \t]*\/\*\*[\s\S]*?\*\/\n?/g, "")
278
+ .replace(/\n{3,}/g, "\n\n")
279
+ .trim();
280
+ }
281
+ /** A namespace's bare shape: one signature per member, no JSDoc. */
282
+ bareNamespace(fields) {
283
+ return fields.map((f) => (f.type.startsWith("(") ? `${f.name}${f.type}` : `${f.name}: ${f.type}`)).join("\n");
284
+ }
285
+ fence(body) {
286
+ return `\`\`\`${this.config.fenceLanguage}\n${body}\n\`\`\`\n`;
287
+ }
288
+ /* ---- disk ---- */
289
+ prepareOutDir() {
290
+ if (this.config.cleanOutDir)
291
+ rmSync(this.config.outDir, { recursive: true, force: true });
292
+ mkdirSync(this.config.outDir, { recursive: true });
293
+ }
294
+ writeSnippet(snippet) {
295
+ writeFileSync(join(this.config.outDir, `${snippet.file}.md`), snippet.full);
296
+ if (this.config.emitBare) {
297
+ writeFileSync(join(this.config.outDir, `${snippet.file}.bare.md`), snippet.bare);
298
+ }
299
+ }
300
+ }
301
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "cutline",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "description": "Generate Markdown API reference snippets from a TypeScript entry module.",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "cutline": "dist/cli.js"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "dependencies": {
15
+ "ts-morph": "^28.0.0"
16
+ },
17
+ "devDependencies": {
18
+ "@biomejs/biome": "^2.4.16",
19
+ "@types/node": "^25.9.1",
20
+ "lefthook": "^2.1.9",
21
+ "tsx": "^4.22.4",
22
+ "typescript": "^6.0.3",
23
+ "vitest": "^4.1.8"
24
+ },
25
+ "scripts": {
26
+ "start": "tsx src/cli.ts",
27
+ "build": "tsc -p tsconfig.build.json",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest",
30
+ "lint": "biome check .",
31
+ "lint:fix": "biome check --write .",
32
+ "format": "biome format --write .",
33
+ "typecheck": "tsc --noEmit"
34
+ }
35
+ }