@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/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]>;
@@ -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
- }