@versatiles/release-tool 1.0.0

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/LICENSE.md ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to [unlicense.org](https://unlicense.org/)
package/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # VersaTiles Release Tools
2
+
3
+ Tools used internally for:
4
+
5
+ * creating Markdown documentation of TypeScript libraries: [`vrt ts2md`](#subcommand-vrt-ts2md)
6
+ * creating Markdown documentation of executables: [`vrt cmd2md`](#subcommand-vrt-cmd2md)
7
+ * inserting Markdown into documents: [`vrt insertmd`](#subcommand-vrt-insertmd)
8
+ * updating "Table of Content" in Markdown files: [`vrt inserttoc`](#subcommand-vrt-inserttoc)
9
+
10
+ # Command `vrt`
11
+
12
+ <!--- This chapter is generated automatically --->
13
+
14
+ ```console
15
+ $ vrt
16
+ Usage: vrt [options] [command]
17
+
18
+ versatiles release and documentaion tool
19
+
20
+ Options:
21
+ -h, --help display help for command
22
+
23
+ Commands:
24
+ ts2md <typescript> <tsconfig> documents a TypeScript file and outputs it to stdout
25
+ cmd2md <command> documents a runnable command and outputs it to stdout
26
+ insertmd <readme> [heading] [foldable] takes Markdown from stdin and insert it into a Markdown file
27
+ inserttoc <readme> [heading] updates the TOC in a Markdown file
28
+ help [command] display help for command
29
+ ```
30
+
31
+ ## Subcommand: `vrt ts2md`
32
+
33
+ ```console
34
+ $ vrt ts2md
35
+ Usage: vrt ts2md [options] <typescript> <tsconfig>
36
+
37
+ documents a TypeScript file and outputs it to stdout
38
+
39
+ Arguments:
40
+ typescript Filename of the TypeScript file
41
+ tsconfig Filename of tsconfig.json
42
+
43
+ Options:
44
+ -h, --help display help for command
45
+ ```
46
+
47
+ ## Subcommand: `vrt cmd2md`
48
+
49
+ ```console
50
+ $ vrt cmd2md
51
+ Usage: vrt cmd2md [options] <command>
52
+
53
+ documents a runnable command and outputs it to stdout
54
+
55
+ Arguments:
56
+ command command to run
57
+
58
+ Options:
59
+ -h, --help display help for command
60
+ ```
61
+
62
+ ## Subcommand: `vrt insertmd`
63
+
64
+ ```console
65
+ $ vrt insertmd
66
+ Usage: vrt insertmd [options] <readme> [heading] [foldable]
67
+
68
+ takes Markdown from stdin and insert it into a Markdown file
69
+
70
+ Arguments:
71
+ readme Markdown file, like a readme.md
72
+ heading Heading in the Markdown file (default: "# API")
73
+ foldable Make content foldable (default: false)
74
+
75
+ Options:
76
+ -h, --help display help for command
77
+ ```
78
+
79
+ ## Subcommand: `vrt inserttoc`
80
+
81
+ ```console
82
+ $ vrt inserttoc
83
+ Usage: vrt inserttoc [options] <readme> [heading]
84
+
85
+ updates the TOC in a Markdown file
86
+
87
+ Arguments:
88
+ readme Markdown file, like a readme.md
89
+ heading Heading in the Markdown file (default: "# Table of Content")
90
+
91
+ Options:
92
+ -h, --help display help for command
93
+ ```
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node --enable-source-maps
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node --enable-source-maps
2
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ import { generateMarkdownDocumentation } from './lib/typedoc.js';
5
+ import { injectMarkdown, updateTOC } from './lib/markdown.js';
6
+ import { Command, InvalidArgumentError } from 'commander';
7
+ import { cwd } from 'node:process';
8
+ import { generateCommandDocumentation } from './lib/command.js';
9
+ const program = new Command();
10
+ program
11
+ .name('vrt')
12
+ .description('versatiles release and documentaion tool');
13
+ program.command('ts2md')
14
+ .description('documents a TypeScript file and outputs it to stdout')
15
+ .argument('<typescript>', 'Filename of the TypeScript file', checkFilename)
16
+ .argument('<tsconfig>', 'Filename of tsconfig.json', checkFilename)
17
+ .action(async (tsFilename, tsConfig) => {
18
+ const mdDocumentation = await generateMarkdownDocumentation([tsFilename], tsConfig);
19
+ process.stdout.write(mdDocumentation);
20
+ });
21
+ program.command('cmd2md')
22
+ .description('documents a runnable command and outputs it to stdout')
23
+ .argument('<command>', 'command to run')
24
+ .action((command) => {
25
+ const mdDocumentation = generateCommandDocumentation(command);
26
+ process.stdout.write(mdDocumentation);
27
+ });
28
+ program.command('insertmd')
29
+ .description('takes Markdown from stdin and insert it into a Markdown file')
30
+ .argument('<readme>', 'Markdown file, like a readme.md', checkFilename)
31
+ .argument('[heading]', 'Heading in the Markdown file', '# API')
32
+ .argument('[foldable]', 'Make content foldable', false)
33
+ .action(async (mdFilename, heading, foldable) => {
34
+ const buffers = [];
35
+ for await (const data of process.stdin)
36
+ buffers.push(data);
37
+ const mdContent = '<!--- This chapter is generated automatically --->\n' + Buffer.concat(buffers).toString();
38
+ let mdFile = readFileSync(mdFilename, 'utf8');
39
+ mdFile = injectMarkdown(mdFile, mdContent, heading, foldable);
40
+ writeFileSync(mdFilename, mdFile);
41
+ });
42
+ program.command('inserttoc')
43
+ .description('updates the TOC in a Markdown file')
44
+ .argument('<readme>', 'Markdown file, like a readme.md', checkFilename)
45
+ .argument('[heading]', 'Heading in the Markdown file', '# Table of Content')
46
+ .action((mdFilename, heading) => {
47
+ let mdFile = readFileSync(mdFilename, 'utf8');
48
+ mdFile = updateTOC(mdFile, heading);
49
+ writeFileSync(mdFilename, mdFile);
50
+ });
51
+ program.parse();
52
+ function checkFilename(filename) {
53
+ const fullname = resolve(cwd(), filename);
54
+ if (!existsSync(fullname)) {
55
+ throw new InvalidArgumentError('file not found');
56
+ }
57
+ return fullname;
58
+ }
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ export declare function generateCommandDocumentation(command: string): string;
@@ -0,0 +1,42 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ export function generateCommandDocumentation(command) {
3
+ const result = getCommandResults(command);
4
+ let { markdown } = result;
5
+ const { subcommands } = result;
6
+ for (const subcommand of subcommands) {
7
+ const subResult = getCommandResults(command + ' ' + subcommand);
8
+ markdown += `\n# Subcommand: \`${command} ${subcommand}\`\n\n${subResult.markdown}`;
9
+ }
10
+ return markdown;
11
+ }
12
+ function getCommandResults(command) {
13
+ const cp = spawnSync('npx', [...command.split(' '), '--help']);
14
+ if (cp.error)
15
+ throw Error(cp.error.toString());
16
+ const result = cp.stdout.toString().trim();
17
+ const subcommands = result
18
+ .replace(/.*\nCommands:/msgi, '')
19
+ .replace(/\n[a-z]+:.*/msi, '')
20
+ .split('\n')
21
+ .flatMap((line) => {
22
+ const extract = /^ ([^ ]{2,})/.exec(line);
23
+ if (!extract)
24
+ return [];
25
+ // eslint-disable-next-line @typescript-eslint/prefer-destructuring
26
+ const subcommand = extract[1];
27
+ if (subcommand === 'help')
28
+ return [];
29
+ return [subcommand];
30
+ });
31
+ return {
32
+ markdown: [
33
+ '```console',
34
+ '$ ' + command,
35
+ result,
36
+ '```',
37
+ '',
38
+ ].join('\n'),
39
+ subcommands,
40
+ };
41
+ }
42
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1,2 @@
1
+ export declare function injectMarkdown(document: string, segment: string, heading: string, foldable?: boolean): string;
2
+ export declare function updateTOC(main: string, heading: string): string;
@@ -0,0 +1,193 @@
1
+ import { remark } from 'remark';
2
+ // eslint-disable-next-line @typescript-eslint/max-params
3
+ export function injectMarkdown(document, segment, heading, foldable) {
4
+ const documentAst = remark().parse(document);
5
+ const segmentAst = remark().parse(segment);
6
+ const headingAst = remark().parse(heading);
7
+ let startIndex;
8
+ try {
9
+ startIndex = findSegmentStart(documentAst, headingAst);
10
+ }
11
+ catch (error) {
12
+ console.error(`While searching for segment "${heading}" …`);
13
+ throw error;
14
+ }
15
+ const depth = getHeadingDepth(documentAst, startIndex);
16
+ const endIndex = findNextHeading(documentAst, startIndex + 1, depth);
17
+ indentChapter(segmentAst, depth);
18
+ if (foldable ?? false)
19
+ makeFoldable(segmentAst);
20
+ spliceAst(documentAst, segmentAst, startIndex + 1, endIndex);
21
+ return remark().stringify(documentAst);
22
+ }
23
+ export function updateTOC(main, heading) {
24
+ const mainAst = remark().parse(main);
25
+ const headingText = getMDText(remark().parse(heading));
26
+ const toc = mainAst.children
27
+ .flatMap(c => {
28
+ if (c.type !== 'heading')
29
+ return [];
30
+ const text = getMDText(c);
31
+ if (text === headingText)
32
+ return [];
33
+ const indention = ' '.repeat((c.depth - 1) * 2);
34
+ const anchor = getMDAnchor(c);
35
+ return `${indention}* [${text}](#${anchor})\n`;
36
+ })
37
+ .join('');
38
+ return injectMarkdown(main, toc, heading);
39
+ }
40
+ function findSegmentStart(mainAst, headingAst) {
41
+ if (headingAst.children.length !== 1)
42
+ throw Error();
43
+ if (headingAst.children[0].type !== 'heading')
44
+ throw Error();
45
+ const sectionDepth = headingAst.children[0].depth;
46
+ const sectionText = getMDText(headingAst);
47
+ const indexes = mainAst.children.flatMap((c, index) => {
48
+ if ((c.type === 'heading') && (c.depth === sectionDepth) && getMDText(c).startsWith(sectionText)) {
49
+ return [index];
50
+ }
51
+ return [];
52
+ });
53
+ if (indexes.length < 1)
54
+ throw Error('section not found');
55
+ if (indexes.length > 1)
56
+ throw Error('too many sections found');
57
+ return indexes[0];
58
+ }
59
+ function findNextHeading(mainAst, startIndex, depth) {
60
+ for (let i = startIndex; i < mainAst.children.length; i++) {
61
+ const child = mainAst.children[i];
62
+ if (child.type !== 'heading')
63
+ continue;
64
+ if (child.depth !== depth)
65
+ continue;
66
+ return i;
67
+ }
68
+ return mainAst.children.length;
69
+ }
70
+ function getHeadingDepth(mainAst, index) {
71
+ const node = mainAst.children[index];
72
+ if (node.type !== 'heading')
73
+ throw Error();
74
+ return node.depth;
75
+ }
76
+ function indentChapter(segmentAst, depth) {
77
+ segmentAst.children.forEach(node => {
78
+ switch (node.type) {
79
+ case 'code':
80
+ case 'html':
81
+ case 'list':
82
+ case 'listItem':
83
+ case 'paragraph':
84
+ case 'text':
85
+ return;
86
+ case 'heading':
87
+ return node.depth += depth;
88
+ default:
89
+ console.log(node);
90
+ throw Error('unknown type: ' + node.type);
91
+ }
92
+ });
93
+ }
94
+ // eslint-disable-next-line @typescript-eslint/max-params
95
+ function spliceAst(mainAst, segmentAst, startIndex, endIndex) {
96
+ mainAst.children.splice(startIndex, endIndex - startIndex, ...segmentAst.children);
97
+ }
98
+ function getMDText(node) {
99
+ switch (node.type) {
100
+ case 'inlineCode':
101
+ case 'text':
102
+ return node.value;
103
+ case 'heading':
104
+ case 'root':
105
+ return node.children.map(getMDText).join('');
106
+ case 'html':
107
+ return '';
108
+ default:
109
+ console.log(node);
110
+ throw Error('unknown type: ' + node.type);
111
+ }
112
+ }
113
+ function getMDAnchor(node) {
114
+ let text = '';
115
+ for (const c of node.children) {
116
+ switch (c.type) {
117
+ case 'html':
118
+ const match = /<a\s.*id\s*=\s*['"]([^'"]+)/i.exec(c.value);
119
+ if (match)
120
+ return match[1];
121
+ break;
122
+ case 'text':
123
+ case 'inlineCode':
124
+ text += c.value;
125
+ break;
126
+ default:
127
+ console.log(c);
128
+ throw Error('unknown type: ' + c.type);
129
+ }
130
+ }
131
+ text = text.toLowerCase()
132
+ .replace(/[()]+/g, '')
133
+ .replace(/[^a-z0-9]+/g, '-')
134
+ .replace(/^\-+|\-+$/g, '');
135
+ return text;
136
+ }
137
+ function makeFoldable(ast) {
138
+ const openDetails = [];
139
+ const children = [];
140
+ ast.children.forEach((c) => {
141
+ switch (c.type) {
142
+ case 'html':
143
+ case 'list':
144
+ case 'paragraph':
145
+ children.push(c);
146
+ break;
147
+ case 'heading':
148
+ closeDetails(c.depth);
149
+ children.push({ type: 'html', value: '<details>' });
150
+ children.push({ type: 'html', value: `<summary>${lineToHtml(c)}</summary>` });
151
+ openDetails.unshift(c.depth);
152
+ break;
153
+ default:
154
+ throw Error(`unknown type "${c.type}"`);
155
+ }
156
+ });
157
+ closeDetails(0);
158
+ ast.children = children;
159
+ function closeDetails(depth) {
160
+ while ((openDetails.length > 0) && (openDetails[0] >= depth)) {
161
+ children.push({ type: 'html', value: '</details>' });
162
+ openDetails.shift();
163
+ }
164
+ }
165
+ }
166
+ function lineToHtml(child) {
167
+ const html = child.children.map(c => {
168
+ switch (c.type) {
169
+ case 'html': return c.value;
170
+ case 'text': return c.value;
171
+ case 'inlineCode': return `<code>${textToHtml(c.value)}</code>`;
172
+ //case "break": { throw new Error('Not implemented yet: "break" case') }
173
+ //case "delete": { throw new Error('Not implemented yet: "delete" case') }
174
+ //case "emphasis": { throw new Error('Not implemented yet: "emphasis" case') }
175
+ //case "footnoteReference": { throw new Error('Not implemented yet: "footnoteReference" case') }
176
+ //case "image": { throw new Error('Not implemented yet: "image" case') }
177
+ //case "imageReference": { throw new Error('Not implemented yet: "imageReference" case') }
178
+ //case "inlineCode": { throw new Error('Not implemented yet: "inlineCode" case') }
179
+ //case "link": { throw new Error('Not implemented yet: "link" case') }
180
+ //case "linkReference": { throw new Error('Not implemented yet: "linkReference" case') }
181
+ //case "strong": { throw new Error('Not implemented yet: "strong" case') }
182
+ //case "text": { throw new Error('Not implemented yet: "text" case') }
183
+ default:
184
+ console.log(c);
185
+ throw Error(`unknown type "${c.type}"`);
186
+ }
187
+ });
188
+ return `<h${child.depth}>${html.join('')}</h${child.depth}>`;
189
+ }
190
+ function textToHtml(text) {
191
+ return text.replace(/[^a-z0-9 ,.-:_?@äöüß]/gi, c => `&#${c.charCodeAt(0)};`);
192
+ }
193
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Generate markdown documentation from TypeScript files.
3
+ * @param entryPoints - Array of absolute TypeScript file paths.
4
+ * @param tsconfig - Absolute file path of tsconfig.json.
5
+ */
6
+ export declare function generateMarkdownDocumentation(entryPoints: string[], tsconfig: string): Promise<string>;
@@ -0,0 +1,204 @@
1
+ import { Application, ReflectionKind, } from 'typedoc';
2
+ /**
3
+ * Generate markdown documentation from TypeScript files.
4
+ * @param entryPoints - Array of absolute TypeScript file paths.
5
+ * @param tsconfig - Absolute file path of tsconfig.json.
6
+ */
7
+ export async function generateMarkdownDocumentation(entryPoints, tsconfig) {
8
+ const app = await Application.bootstrap({ entryPoints, tsconfig });
9
+ const project = await app.convert();
10
+ if (!project) {
11
+ throw new Error('Failed to convert project.');
12
+ }
13
+ return Array.from(renderProjectDocumentation(project)).join('\n');
14
+ }
15
+ function* renderProjectDocumentation(project) {
16
+ if (!project.groups) {
17
+ throw new Error('No code to document found! Is this a lib?');
18
+ }
19
+ for (const group of project.groups) {
20
+ for (const declaration of group.children) {
21
+ yield* renderDeclaration(declaration);
22
+ }
23
+ }
24
+ }
25
+ function* renderDeclaration(declaration) {
26
+ const typeName = formatTypeName(declaration.kind);
27
+ yield `# ${typeName}: \`${declaration.name}\`<a id="${generateAnchor(declaration)}"></a>`;
28
+ yield* renderSummaryBlock(declaration);
29
+ for (const group of declaration.groups ?? []) {
30
+ const publicMembers = group.children.filter(member => !member.flags.isPrivate && !member.flags.isProtected);
31
+ if (publicMembers.length === 0)
32
+ continue;
33
+ // Sort by order in code
34
+ publicMembers.sort((a, b) => a.id - b.id);
35
+ switch (group.title) {
36
+ case 'Constructors':
37
+ if (publicMembers.length !== 1)
38
+ throw Error();
39
+ yield* renderMethod(publicMembers[0], true);
40
+ continue;
41
+ case 'Properties':
42
+ //yield '';
43
+ //yield '**Properties**';
44
+ for (const member of publicMembers)
45
+ yield formatParameter(member);
46
+ continue;
47
+ case 'Methods':
48
+ //yield '';
49
+ //yield '**Methods**';
50
+ for (const member of publicMembers)
51
+ yield* renderMethod(member);
52
+ continue;
53
+ default:
54
+ console.log(group);
55
+ throw Error('Unknown group title');
56
+ }
57
+ }
58
+ if (declaration.type) {
59
+ yield `\n**Type:** <code>${formatType(declaration.type)}</code>`;
60
+ }
61
+ }
62
+ function* renderMethod(declaration, isConstructor = false) {
63
+ if (declaration.signatures?.length !== 1)
64
+ throw Error('should be 1');
65
+ const [signature] = declaration.signatures;
66
+ const functionName = signature.name;
67
+ const parameters = formatMethodParameters(signature.parameters ?? []);
68
+ const returnType = signature.type;
69
+ const prefix = isConstructor ? 'Constructor' : 'Method';
70
+ yield `## ${prefix}: \`${functionName}(${parameters})\``;
71
+ yield '';
72
+ yield* renderSummaryBlock(signature);
73
+ if (signature.parameters && signature.parameters.length > 0) {
74
+ yield '';
75
+ yield '**Parameters:**';
76
+ for (const parameter of signature.parameters) {
77
+ yield formatParameter(parameter);
78
+ }
79
+ }
80
+ if (returnType) {
81
+ yield '';
82
+ yield `**Returns:** <code>${formatType(returnType)}</code>`;
83
+ }
84
+ }
85
+ function formatMethodParameters(parameters) {
86
+ return parameters.map(param => param.name).join(', ');
87
+ }
88
+ // Helper Functions
89
+ function formatTypeName(kind) {
90
+ switch (kind) {
91
+ case ReflectionKind.Class: return 'Class';
92
+ case ReflectionKind.Interface: return 'Interface';
93
+ case ReflectionKind.TypeAlias: return 'Type';
94
+ default: throw new Error(`Unknown reflection kind: ${kind}`);
95
+ }
96
+ }
97
+ function formatParameter(ref) {
98
+ let line = ` - <code>${ref.name}${resolveTypeDeclaration(ref.type)}</code>`;
99
+ if (ref.flags.isOptional)
100
+ line += ' (optional)';
101
+ const summary = extractSummary(ref.comment);
102
+ if (summary)
103
+ line += ' \n ' + summary;
104
+ return line;
105
+ }
106
+ function extractSummary(comment) {
107
+ if (!comment)
108
+ return '';
109
+ return comment.summary.map(line => line.text).join('');
110
+ }
111
+ function* renderSummaryBlock(ref) {
112
+ yield '';
113
+ if (ref.comment) {
114
+ yield formatComment(ref.comment);
115
+ return;
116
+ }
117
+ const { type } = ref;
118
+ if (type?.type === 'reflection') {
119
+ if (type.declaration.signatures?.length !== 1)
120
+ throw Error();
121
+ const [signature] = type.declaration.signatures;
122
+ if (signature.comment) {
123
+ yield formatComment(signature.comment);
124
+ return;
125
+ }
126
+ }
127
+ yield generateSourceLink(ref) + '\n';
128
+ return;
129
+ function formatComment(comment) {
130
+ return (extractSummary(comment) + ' ' + generateSourceLink(ref)).replace(/\n/m, ' \n') + '\n';
131
+ }
132
+ }
133
+ function resolveTypeDeclaration(someType) {
134
+ if (!someType)
135
+ return '';
136
+ return `: ${formatType(someType)}`;
137
+ }
138
+ function formatType(someType) {
139
+ return getTypeRec(someType);
140
+ function getTypeRec(some) {
141
+ switch (some.type) {
142
+ case 'intrinsic':
143
+ return some.name;
144
+ case 'literal':
145
+ return JSON.stringify(some.value);
146
+ case 'reference':
147
+ let result = some.name;
148
+ if (some.reflection)
149
+ result = `[${result}](#${generateAnchor(some.reflection)})`;
150
+ if (some.typeArguments?.length ?? 0)
151
+ result += '<'
152
+ + (some.typeArguments ?? [])
153
+ .map(getTypeRec).join(',')
154
+ + '>';
155
+ return result;
156
+ case 'reflection':
157
+ if (!some.declaration.signatures)
158
+ throw Error();
159
+ if (some.declaration.signatures.length !== 1)
160
+ throw Error();
161
+ const [signature] = some.declaration.signatures;
162
+ const type = signature.type ? getTypeRec(signature.type) : 'void';
163
+ const parameters = (signature.parameters ?? [])
164
+ .map(p => {
165
+ return p.name + (p.type ? ': ' + getTypeRec(p.type) : '');
166
+ }).join(', ');
167
+ return `(${parameters}) => ${type}`;
168
+ case 'tuple':
169
+ return `[${some.elements.map(getTypeRec).join(', ')}]`;
170
+ case 'union':
171
+ return some.types.map(getTypeRec).join(' | ');
172
+ default:
173
+ console.log(some);
174
+ throw Error();
175
+ }
176
+ }
177
+ }
178
+ function generateSourceLink(ref) {
179
+ if (!ref.sources || ref.sources.length < 1)
180
+ return '';
181
+ if (ref.sources.length > 1)
182
+ throw Error();
183
+ const [source] = ref.sources;
184
+ return `<sup><a href="${source.url}">[src]</a></sup>`;
185
+ }
186
+ function generateAnchor(ref) {
187
+ let typeName;
188
+ switch (ref.kind) {
189
+ case ReflectionKind.Class:
190
+ typeName = 'class';
191
+ break;
192
+ case ReflectionKind.Interface:
193
+ typeName = 'interface';
194
+ break;
195
+ case ReflectionKind.TypeAlias:
196
+ typeName = 'type';
197
+ break;
198
+ default:
199
+ console.log(ref);
200
+ throw new Error('Unknown reflection kind');
201
+ }
202
+ return `${typeName}_${ref.name}`.toLowerCase();
203
+ }
204
+ //# sourceMappingURL=typedoc.js.map
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@versatiles/release-tool",
3
+ "version": "1.0.0",
4
+ "description": "VersaTiles release and documentation tools",
5
+ "bin": {
6
+ "vrt": "./dist/index.js"
7
+ },
8
+ "files": [
9
+ "dist/**/*.js",
10
+ "dist/**/*.d.ts"
11
+ ],
12
+ "scripts": {
13
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && chmod +x dist/index.js",
14
+ "check": "npm run lint && npm run test && npm run build",
15
+ "doc": "npx vrt cmd2md vrt | npx vrt insertmd README.md '# Command'",
16
+ "lint": "eslint . --color",
17
+ "prepublish": "npm run build && npm run doc",
18
+ "test": "cd ..; NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern versatiles-release-tool"
19
+ },
20
+ "author": "yetzt <node@yetzt.me>, Michael Kreil <versatiles@michael-kreil.de>",
21
+ "license": "Unlicense",
22
+ "type": "module",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/versatiles-org/node-versatiles.git"
26
+ },
27
+ "homepage": "https://github.com/versatiles-org/node-versatiles/blob/main/versatiles-release-tool/README.md",
28
+ "devDependencies": {
29
+ "@types/node": "^20.9.2",
30
+ "remark": "^15.0.1",
31
+ "tsx": "^4.1.4",
32
+ "typedoc": "^0.25.3",
33
+ "typescript": "^5.2.2"
34
+ },
35
+ "dependencies": {
36
+ "commander": "^11.1.0"
37
+ }
38
+ }