@travetto/doc 3.0.2 → 3.1.0-rc.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/README.md +65 -83
- package/__index__.ts +3 -4
- package/package.json +3 -3
- package/src/jsx.ts +107 -0
- package/src/mapping/lib-mapping.ts +107 -0
- package/src/mapping/mod-mapping.ts +250 -0
- package/src/render/context.ts +95 -25
- package/src/render/html.ts +151 -71
- package/src/render/markdown.ts +123 -60
- package/src/render/renderer.ts +146 -0
- package/src/types.ts +23 -53
- package/src/util/file.ts +28 -13
- package/src/util/resolve.ts +39 -62
- package/src/util/run.ts +11 -22
- package/support/cli.doc.ts +58 -50
- package/src/doc.ts +0 -24
- package/src/lib.ts +0 -109
- package/src/mod-mapping.ts +0 -258
- package/src/mod.ts +0 -8
- package/src/nodes.ts +0 -334
- package/src/render/util.ts +0 -67
package/src/nodes.ts
DELETED
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'fs';
|
|
2
|
-
|
|
3
|
-
import { path, RootIndex, PackageUtil } from '@travetto/manifest';
|
|
4
|
-
|
|
5
|
-
import { FileUtil, } from './util/file';
|
|
6
|
-
import { DocRunUtil, RunConfig } from './util/run';
|
|
7
|
-
import { Content, DocNode, TextType } from './types';
|
|
8
|
-
import { ResolveUtil } from './util/resolve';
|
|
9
|
-
|
|
10
|
-
function $c(val: string): TextType;
|
|
11
|
-
function $c(val: DocNode | string): DocNode;
|
|
12
|
-
function $c(val: DocNode | string | undefined): DocNode | undefined;
|
|
13
|
-
function $c(val: string | DocNode | undefined): DocNode | undefined {
|
|
14
|
-
return val === undefined ? undefined : typeof val === 'string' ?
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
16
|
-
{ _type: 'text' as const, content: val } as TextType : val;
|
|
17
|
-
}
|
|
18
|
-
const $n = <T extends string, U extends Record<string, unknown>>(t: T, values: U): { _type: T } & U =>
|
|
19
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
20
|
-
({ _type: t, ...values } as { _type: T } & U);
|
|
21
|
-
|
|
22
|
-
type FormattedCommand = { formatCommand?(cmd: string, args: string[]): string };
|
|
23
|
-
|
|
24
|
-
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* All Node Types
|
|
28
|
-
*/
|
|
29
|
-
export const node = {
|
|
30
|
-
buildList(items: Content[], ordered = false) {
|
|
31
|
-
return $n('list', {
|
|
32
|
-
items: items.map(x => {
|
|
33
|
-
if (Array.isArray(x)) {
|
|
34
|
-
x = node.Item(node.Group(x), ordered);
|
|
35
|
-
} else if (typeof x === 'string') {
|
|
36
|
-
x = $c(x);
|
|
37
|
-
}
|
|
38
|
-
switch (x._type) {
|
|
39
|
-
case 'list': return x;
|
|
40
|
-
case 'item': return { ...x, ordered };
|
|
41
|
-
default: return node.Item(x, ordered);
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
});
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Simple Text Content
|
|
49
|
-
* @param text
|
|
50
|
-
*/
|
|
51
|
-
Text: (text: string) => ({ _type: 'text' as const, content: text }),
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Strong Content
|
|
55
|
-
* @param content
|
|
56
|
-
*/
|
|
57
|
-
Strong: (content: Content) => $n('strong', { content: $c(content) }),
|
|
58
|
-
/**
|
|
59
|
-
* Group of content nodes
|
|
60
|
-
* @param items
|
|
61
|
-
*/
|
|
62
|
-
Group: (items: DocNode | DocNode[]) => $n('group', { nodes: [items].flat() }),
|
|
63
|
-
/**
|
|
64
|
-
* Method declaration
|
|
65
|
-
* @param content
|
|
66
|
-
*/
|
|
67
|
-
Method: (content: Content) => $n('method', { content: $c(content) }),
|
|
68
|
-
/**
|
|
69
|
-
* Command invocation
|
|
70
|
-
* @param script
|
|
71
|
-
* @param args
|
|
72
|
-
*/
|
|
73
|
-
Command: (script: Content, ...args: Content[]) => $n('command', { content: $c([script, ...args].join(' ')) }),
|
|
74
|
-
/**
|
|
75
|
-
* Terminal output
|
|
76
|
-
* @param title
|
|
77
|
-
* @param script
|
|
78
|
-
*/
|
|
79
|
-
Terminal: (title: Content, script: Content) => $n('terminal', { title: $c(title), content: $c(script), language: 'bash' }),
|
|
80
|
-
/**
|
|
81
|
-
* Input text
|
|
82
|
-
* @param content
|
|
83
|
-
*/
|
|
84
|
-
Input: (content: Content) => $n('input', { content: $c(content) }),
|
|
85
|
-
/**
|
|
86
|
-
* Path reference
|
|
87
|
-
* @param content
|
|
88
|
-
*/
|
|
89
|
-
Path: (content: Content) => $n('path', { content: $c(content) }),
|
|
90
|
-
/**
|
|
91
|
-
* Class reference
|
|
92
|
-
* @param content
|
|
93
|
-
*/
|
|
94
|
-
Class: (content: Content) => $n('class', { content: $c(content) }),
|
|
95
|
-
/**
|
|
96
|
-
* Field reference
|
|
97
|
-
* @param content
|
|
98
|
-
*/
|
|
99
|
-
Field: (content: Content) => $n('field', { content: $c(content) }),
|
|
100
|
-
/**
|
|
101
|
-
* Primary Section
|
|
102
|
-
* @param content
|
|
103
|
-
*/
|
|
104
|
-
Section: (title: Content) => $n('section', { title: $c(title) }),
|
|
105
|
-
/**
|
|
106
|
-
* Sub-section
|
|
107
|
-
* @param content
|
|
108
|
-
*/
|
|
109
|
-
SubSection: (title: Content) => $n('subsection', { title: $c(title) }),
|
|
110
|
-
/**
|
|
111
|
-
* Sub-sub-section
|
|
112
|
-
* @param content
|
|
113
|
-
*/
|
|
114
|
-
SubSubSection: (title: Content) => $n('subsubsection', { title: $c(title) }),
|
|
115
|
-
/**
|
|
116
|
-
* Library reference
|
|
117
|
-
* @param content
|
|
118
|
-
*/
|
|
119
|
-
Library: (title: Content, link: Content) => $n('library', { title: $c(title), link: $c(link) }),
|
|
120
|
-
/**
|
|
121
|
-
* In page anchor reference
|
|
122
|
-
* @param title
|
|
123
|
-
* @param fragment
|
|
124
|
-
*/
|
|
125
|
-
Anchor: (title: Content, fragment: Content) => $n('anchor', { title: $c(title), fragment: $c(fragment) }),
|
|
126
|
-
/**
|
|
127
|
-
* A note
|
|
128
|
-
* @param content
|
|
129
|
-
*/
|
|
130
|
-
Note: (content: Content) => $n('note', { content: $c(content) }),
|
|
131
|
-
/**
|
|
132
|
-
* List item
|
|
133
|
-
* @param item
|
|
134
|
-
* @param ordered
|
|
135
|
-
*/
|
|
136
|
-
Item: (item: DocNode, ordered = false) => $n('item', { node: item, ordered }),
|
|
137
|
-
/**
|
|
138
|
-
* Raw Doc Header
|
|
139
|
-
* @param title
|
|
140
|
-
* @param description
|
|
141
|
-
*/
|
|
142
|
-
RawHeader: (title: Content, description?: string) => $n('header', { title: $c(title), description: $c(description) }),
|
|
143
|
-
/**
|
|
144
|
-
* Table Of Contents
|
|
145
|
-
* @param title
|
|
146
|
-
*/
|
|
147
|
-
TableOfContents: (title: Content) => $n('toc', { title: $c(title) }),
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Link to a snippet of code, including line number
|
|
151
|
-
* @param title
|
|
152
|
-
* @param file
|
|
153
|
-
* @param startPattern
|
|
154
|
-
*/
|
|
155
|
-
SnippetLink: (title: Content, file: string, startPattern: RegExp) => {
|
|
156
|
-
const res = ResolveUtil.resolveSnippetLink(file, startPattern);
|
|
157
|
-
return $n('file', { title: $c(title), link: $c(res.file), line: res.line });
|
|
158
|
-
},
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Run a command, and include the output as part of the document
|
|
162
|
-
* @param title
|
|
163
|
-
* @param cmd
|
|
164
|
-
* @param args
|
|
165
|
-
* @param cfg
|
|
166
|
-
*/
|
|
167
|
-
Execute: (title: Content, cmd: string, args: string[] = [], cfg: RunConfig & FormattedCommand = {}) => {
|
|
168
|
-
if (cmd !== 'trv') {
|
|
169
|
-
cmd = FileUtil.resolveFile(cmd).replace(path.cwd(), '.');
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const script = DocRunUtil.run(cmd, args, cfg);
|
|
173
|
-
const prefix = !/.*\/doc\/.*[.]ts$/.test(cmd) ? '$' : '$ node ';
|
|
174
|
-
|
|
175
|
-
const commandDisplay = cfg.formatCommand?.(cmd, args) ?? `${cmd} ${args.join(' ')}`;
|
|
176
|
-
|
|
177
|
-
return node.Terminal(title, `${prefix} ${commandDisplay}\n\n${script}`);
|
|
178
|
-
},
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Node Module Reference
|
|
182
|
-
* @param name
|
|
183
|
-
*/
|
|
184
|
-
Mod(name: string, cfg?: { folder: string, displayName: string, description: string }) {
|
|
185
|
-
if (!cfg) {
|
|
186
|
-
const folder = RootIndex.getModule(name)!.sourcePath;
|
|
187
|
-
const pkg = PackageUtil.readPackage(folder);
|
|
188
|
-
cfg = {
|
|
189
|
-
folder,
|
|
190
|
-
displayName: pkg.travetto!.displayName!,
|
|
191
|
-
description: pkg.description!
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
return $n('mod', { title: $c(cfg.displayName), link: $c(cfg.folder), description: $c(cfg.description), name: $c(name) });
|
|
195
|
-
},
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* File reference
|
|
199
|
-
* @param title
|
|
200
|
-
* @param file
|
|
201
|
-
*/
|
|
202
|
-
Ref: (title: Content, file: string | Function) => {
|
|
203
|
-
if (typeof file === 'function') {
|
|
204
|
-
file = RootIndex.getFunctionMetadata(file)!.source;
|
|
205
|
-
}
|
|
206
|
-
const res = ResolveUtil.resolveRef(title, file);
|
|
207
|
-
return $n('ref', { title: $c(res.title), link: $c(res.file), line: res.line });
|
|
208
|
-
},
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Code sample
|
|
212
|
-
* @param title
|
|
213
|
-
* @param content
|
|
214
|
-
* @param outline
|
|
215
|
-
* @param language
|
|
216
|
-
*/
|
|
217
|
-
Code: (title: Content, content: Content | Function, outline = false, language = 'typescript', rewrite?: (text: string) => string) => {
|
|
218
|
-
if (typeof content === 'function') {
|
|
219
|
-
content = RootIndex.getFunctionMetadata(content)!.source;
|
|
220
|
-
}
|
|
221
|
-
const res = ResolveUtil.resolveCode(content, language, outline);
|
|
222
|
-
if (rewrite && typeof res.content === 'string') {
|
|
223
|
-
res.content = rewrite(res.content);
|
|
224
|
-
}
|
|
225
|
-
return $n('code', { title: $c(title), content: $c(res.content), language: res.language, file: $c(res.file) });
|
|
226
|
-
},
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Configuration Block
|
|
230
|
-
* @param title
|
|
231
|
-
* @param content
|
|
232
|
-
* @param language
|
|
233
|
-
*/
|
|
234
|
-
Config: (title: Content, content: Content, language = 'yaml') => {
|
|
235
|
-
const res = ResolveUtil.resolveConfig(content, language);
|
|
236
|
-
return $n('config', { title: $c(title), content: $c(res.content), language: res.language, file: $c(res.file) });
|
|
237
|
-
},
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Standard header
|
|
241
|
-
* @param install
|
|
242
|
-
* @param pkg
|
|
243
|
-
*/
|
|
244
|
-
Header: (mod?: string, install = true) => {
|
|
245
|
-
if (!mod) {
|
|
246
|
-
mod = RootIndex.mainPackage.name;
|
|
247
|
-
}
|
|
248
|
-
const pkg = PackageUtil.readPackage(RootIndex.getModule(mod)!.sourcePath);
|
|
249
|
-
return $n('header', { title: $c(pkg.travetto?.displayName ?? pkg.name), description: $c(pkg.description), package: pkg.name, install });
|
|
250
|
-
},
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Comment
|
|
254
|
-
* @param text
|
|
255
|
-
* @returns
|
|
256
|
-
*/
|
|
257
|
-
Comment: (text: string) => $n('comment', { text: $c(text) }),
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Code Snippet
|
|
261
|
-
* @param title
|
|
262
|
-
* @param file
|
|
263
|
-
* @param startPattern
|
|
264
|
-
* @param endPattern
|
|
265
|
-
* @param outline
|
|
266
|
-
*/
|
|
267
|
-
Snippet: (title: Content, file: string | Function, startPattern: RegExp, endPattern?: RegExp, outline?: boolean) => {
|
|
268
|
-
if (typeof file !== 'string') {
|
|
269
|
-
file = RootIndex.getFunctionMetadata(file)!.source;
|
|
270
|
-
}
|
|
271
|
-
const res = ResolveUtil.resolveSnippet(file, startPattern, endPattern, outline);
|
|
272
|
-
return $n('code', {
|
|
273
|
-
title: $c(title), content: $c(res.text), line: res.line, file: $c(res.file), language: res.language,
|
|
274
|
-
link: node.SnippetLink(title, file, startPattern)
|
|
275
|
-
});
|
|
276
|
-
},
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Installing a package or program
|
|
280
|
-
* @param title
|
|
281
|
-
* @param pkg
|
|
282
|
-
*/
|
|
283
|
-
Install: (title: Content, pkg: Content) => {
|
|
284
|
-
if (typeof pkg === 'string' && !pkg.includes(' ')) {
|
|
285
|
-
return $n('install', {
|
|
286
|
-
title: $c(title), language: 'bash', content: $c(`npm install ${pkg}\n\n# or\n\nyarn add ${pkg}`)
|
|
287
|
-
});
|
|
288
|
-
} else {
|
|
289
|
-
return $n('install', { title: $c(title), language: 'bash', content: $c(pkg), subtype: undefined });
|
|
290
|
-
}
|
|
291
|
-
},
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Standard List
|
|
295
|
-
* @param items
|
|
296
|
-
*/
|
|
297
|
-
List: (...items: Content[]) => node.buildList(items),
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Ordered List
|
|
301
|
-
* @param items
|
|
302
|
-
*/
|
|
303
|
-
Ordered: (...items: Content[]) => node.buildList(items, true),
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Table
|
|
307
|
-
* @param headers
|
|
308
|
-
* @param rows
|
|
309
|
-
*/
|
|
310
|
-
Table: (headers: Content[], ...rows: Content[][]) =>
|
|
311
|
-
$n('table', {
|
|
312
|
-
headers: headers.map(x => typeof x === 'string' ? $c(x) : x),
|
|
313
|
-
rows: rows.map(row =>
|
|
314
|
-
row.map(x => typeof x === 'string' ? $c(x) : x)
|
|
315
|
-
)
|
|
316
|
-
}),
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Image reference
|
|
320
|
-
* @param title
|
|
321
|
-
* @param file
|
|
322
|
-
*/
|
|
323
|
-
Image: (title: Content, file: string) => {
|
|
324
|
-
if (!/^https?:/.test(file) && !existsSync(file)) {
|
|
325
|
-
throw new Error(`${file} is not a valid location`);
|
|
326
|
-
}
|
|
327
|
-
return $n('image', { title: $c(title), link: $c(file) });
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
type NodeType = typeof node;
|
|
332
|
-
|
|
333
|
-
export type AllTypeMap = { [K in keyof NodeType]: ReturnType<NodeType[K]> };
|
|
334
|
-
export type AllType = ReturnType<(NodeType)[keyof NodeType]>;
|
package/src/render/util.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { RootIndex, PackageUtil, path } from '@travetto/manifest';
|
|
2
|
-
|
|
3
|
-
import { RenderContext } from './context';
|
|
4
|
-
import { Html } from './html';
|
|
5
|
-
import { Markdown } from './markdown';
|
|
6
|
-
import { DocumentShape, Wrapper } from '../types';
|
|
7
|
-
import { AllType } from '../nodes';
|
|
8
|
-
|
|
9
|
-
const renderers = { [Html.ext]: Html, [Markdown.ext]: Markdown };
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Render utilities
|
|
13
|
-
*/
|
|
14
|
-
export class RenderUtil {
|
|
15
|
-
|
|
16
|
-
static #imported = new Map<string, { root: AllType, wrap?: Wrapper }>();
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Render content of file and format
|
|
20
|
-
* @param file
|
|
21
|
-
* @param fmt
|
|
22
|
-
* @returns
|
|
23
|
-
*/
|
|
24
|
-
static async render(file: string, fmt: string = Markdown.ext): Promise<string> {
|
|
25
|
-
fmt = fmt.replace(/^[.]/, ''); // Strip leading .
|
|
26
|
-
if (!renderers[fmt]) {
|
|
27
|
-
throw new Error(`Unknown renderer with format: ${fmt}`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
let mod = RootIndex.getFromSource(file)?.import;
|
|
31
|
-
|
|
32
|
-
if (RootIndex.manifest.moduleType === 'module') {
|
|
33
|
-
mod = `${mod}?ts=${Date.now()}`;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
37
|
-
const res = await import(mod!) as DocumentShape;
|
|
38
|
-
|
|
39
|
-
if (!this.#imported.has(file)) {
|
|
40
|
-
this.#imported.set(file, {
|
|
41
|
-
wrap: res.wrap,
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
43
|
-
root: await res.text() as AllType
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const { wrap, root } = this.#imported.get(file)!;
|
|
48
|
-
|
|
49
|
-
const manifestPkg = PackageUtil.readPackage(RootIndex.getModule('@travetto/manifest')!.sourcePath);
|
|
50
|
-
|
|
51
|
-
const mf = RootIndex.manifest;
|
|
52
|
-
|
|
53
|
-
const pkg = PackageUtil.readPackage(mf.workspacePath);
|
|
54
|
-
const mainPath = path.resolve(mf.workspacePath, mf.mainFolder);
|
|
55
|
-
const repoBaseUrl = pkg.travetto?.docBaseUrl ?? mainPath;
|
|
56
|
-
|
|
57
|
-
const ctx = new RenderContext(
|
|
58
|
-
file,
|
|
59
|
-
path.resolve(pkg.travetto?.docRoot ?? mf.workspacePath),
|
|
60
|
-
repoBaseUrl,
|
|
61
|
-
repoBaseUrl.includes('travetto.github') ? repoBaseUrl : manifestPkg.travetto!.docBaseUrl!
|
|
62
|
-
);
|
|
63
|
-
const content = renderers[fmt].render(root, ctx).replace(/\n{3,100}/msg, '\n\n').trim();
|
|
64
|
-
const preamble = renderers[fmt].render(ctx.preamble, ctx);
|
|
65
|
-
return `${preamble}\n${wrap?.[fmt]?.(content) ?? content}\n`;
|
|
66
|
-
}
|
|
67
|
-
}
|