@travetto/doc 3.0.0-rc.2 → 3.0.0-rc.21

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 CHANGED
@@ -1,5 +1,6 @@
1
- import { PathUtil, Package, FsUtil } from '@travetto/boot';
2
- import { readPackage } from '@travetto/boot/src/internal/package';
1
+ import { existsSync } from 'fs';
2
+
3
+ import { path, RootIndex, PackageUtil } from '@travetto/manifest';
3
4
 
4
5
  import { FileUtil, } from './util/file';
5
6
  import { DocRunUtil, RunConfig } from './util/run';
@@ -18,6 +19,8 @@ const $n = <T extends string, U extends Record<string, unknown>>(t: T, values: U
18
19
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
19
20
  ({ _type: t, ...values } as { _type: T } & U);
20
21
 
22
+ type FormattedCommand = { formatCommand?(cmd: string, args: string[]): string };
23
+
21
24
  /* eslint-disable @typescript-eslint/explicit-function-return-type */
22
25
 
23
26
  /**
@@ -104,6 +107,11 @@ export const node = {
104
107
  * @param content
105
108
  */
106
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) }),
107
115
  /**
108
116
  * Library reference
109
117
  * @param content
@@ -156,27 +164,34 @@ export const node = {
156
164
  * @param args
157
165
  * @param cfg
158
166
  */
159
- Execute: (title: Content, cmd: string, args: string[] = [], cfg: RunConfig = {}) => {
167
+ Execute: (title: Content, cmd: string, args: string[] = [], cfg: RunConfig & FormattedCommand = {}) => {
160
168
  if (cmd !== 'trv') {
161
- cmd = FileUtil.resolveFile(cmd).resolved.replace(PathUtil.cwd, '.');
169
+ cmd = FileUtil.resolveFile(cmd).replace(path.cwd(), '.');
162
170
  }
163
171
 
164
172
  const script = DocRunUtil.run(cmd, args, cfg);
165
- const prefix = !/.*\/doc\/.*[.]ts$/.test(cmd) ? '$' :
166
- `$ node @travetto/${cfg.module ?? 'base'}/bin/main`;
173
+ const prefix = !/.*\/doc\/.*[.]ts$/.test(cmd) ? '$' : '$ node ';
174
+
175
+ const commandDisplay = cfg.formatCommand?.(cmd, args) ?? `${cmd} ${args.join(' ')}`;
167
176
 
168
- return node.Terminal(title, `${prefix} ${cmd} ${args.join(' ')}\n\n${script}`);
177
+ return node.Terminal(title, `${prefix} ${commandDisplay}\n\n${script}`);
169
178
  },
170
179
 
171
180
  /**
172
181
  * Node Module Reference
173
- * @param folder
174
- */
175
- Mod(folder: string) {
176
- folder = PathUtil.resolveFrameworkPath(PathUtil.resolveUnix('node_modules', folder));
177
-
178
- const { description, displayName } = readPackage(folder);
179
- return $n('mod', { title: $c(displayName!), link: $c(folder), description: $c(description!) });
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) });
180
195
  },
181
196
 
182
197
  /**
@@ -184,7 +199,10 @@ export const node = {
184
199
  * @param title
185
200
  * @param file
186
201
  */
187
- Ref: (title: Content, file: string) => {
202
+ Ref: (title: Content, file: string | Function) => {
203
+ if (typeof file === 'function') {
204
+ file = RootIndex.getFunctionMetadata(file)!.source;
205
+ }
188
206
  const res = ResolveUtil.resolveRef(title, file);
189
207
  return $n('ref', { title: $c(res.title), link: $c(res.file), line: res.line });
190
208
  },
@@ -196,8 +214,14 @@ export const node = {
196
214
  * @param outline
197
215
  * @param language
198
216
  */
199
- Code: (title: Content, content: Content, outline = false, language = 'typescript') => {
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
+ }
200
221
  const res = ResolveUtil.resolveCode(content, language, outline);
222
+ if (rewrite && typeof res.content === 'string') {
223
+ res.content = rewrite(res.content);
224
+ }
201
225
  return $n('code', { title: $c(title), content: $c(res.content), language: res.language, file: $c(res.file) });
202
226
  },
203
227
 
@@ -217,8 +241,13 @@ export const node = {
217
241
  * @param install
218
242
  * @param pkg
219
243
  */
220
- Header: (install = true, pkg = Package) =>
221
- $n('header', { title: $c(pkg.displayName ?? pkg.name), description: $c(pkg.description), package: pkg.name, install }),
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
+ },
222
251
 
223
252
  /**
224
253
  * Comment
@@ -235,7 +264,10 @@ export const node = {
235
264
  * @param endPattern
236
265
  * @param outline
237
266
  */
238
- Snippet: (title: Content, file: string, startPattern: RegExp, endPattern?: RegExp, outline?: boolean) => {
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
+ }
239
271
  const res = ResolveUtil.resolveSnippet(file, startPattern, endPattern, outline);
240
272
  return $n('code', {
241
273
  title: $c(title), content: $c(res.text), line: res.line, file: $c(res.file), language: res.language,
@@ -244,13 +276,18 @@ export const node = {
244
276
  },
245
277
 
246
278
  /**
247
- * NPM Installation
279
+ * Installing a package or program
248
280
  * @param title
249
281
  * @param pkg
250
282
  */
251
283
  Install: (title: Content, pkg: Content) => {
252
- pkg = typeof pkg === 'string' && !pkg.includes(' ') ? `npm install ${pkg}` : pkg;
253
- return $n('install', { title: $c(title), language: 'bash', content: $c(pkg) });
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
+ }
254
291
  },
255
292
 
256
293
  /**
@@ -284,7 +321,7 @@ export const node = {
284
321
  * @param file
285
322
  */
286
323
  Image: (title: Content, file: string) => {
287
- if (!/^https?:/.test(file) && !FsUtil.existsSync(file)) {
324
+ if (!/^https?:/.test(file) && !existsSync(file)) {
288
325
  throw new Error(`${file} is not a valid location`);
289
326
  }
290
327
  return $n('image', { title: $c(title), link: $c(file) });
@@ -1,31 +1,24 @@
1
- type Lang = {};
2
-
3
- // TODO: Get proper typings
4
- const Prism: {
5
- plugins: { NormalizeWhitespace: Record<string, Function> };
6
- languages: Record<string, Lang>;
7
- highlight(text: string, grammar: Lang, language: string): string;
8
- } = require('prismjs');
9
-
10
- import 'prismjs/plugins/normalize-whitespace/prism-normalize-whitespace';
11
- import 'prismjs/components/prism-typescript';
12
- import 'prismjs/components/prism-javascript';
13
- import 'prismjs/components/prism-css';
14
- import 'prismjs/components/prism-scss';
15
- import 'prismjs/components/prism-yaml';
16
- import 'prismjs/components/prism-json';
17
- import 'prismjs/components/prism-sql';
18
- import 'prismjs/components/prism-properties';
19
- import 'prismjs/components/prism-bash';
20
-
21
- Prism.plugins.NormalizeWhitespace.setDefaults({
1
+ import { default as prismjs } from 'prismjs';
2
+
3
+ import 'prismjs/plugins/normalize-whitespace/prism-normalize-whitespace.js';
4
+ import 'prismjs/components/prism-typescript.js';
5
+ import 'prismjs/components/prism-javascript.js';
6
+ import 'prismjs/components/prism-css.js';
7
+ import 'prismjs/components/prism-scss.js';
8
+ import 'prismjs/components/prism-yaml.js';
9
+ import 'prismjs/components/prism-json.js';
10
+ import 'prismjs/components/prism-sql.js';
11
+ import 'prismjs/components/prism-properties.js';
12
+ import 'prismjs/components/prism-bash.js';
13
+
14
+ prismjs.plugins.NormalizeWhitespace.setDefaults({
22
15
  'remove-trailing': true,
23
16
  'remove-indent': true,
24
17
  'left-trim': true,
25
18
  'right-trim': true
26
19
  });
27
20
 
28
- const nw = Prism.plugins.NormalizeWhitespace;
21
+ const nw = prismjs.plugins.NormalizeWhitespace;
29
22
 
30
23
  const tokenMapping: { [key: string]: string } = {
31
24
  gt: '>',
@@ -44,7 +37,7 @@ export function highlight(text: string, lang: string): string | undefined {
44
37
  .replace(/&([a-z][^;]*);/g, (a, k) => tokenMapping[k] || a);
45
38
 
46
39
  try {
47
- return Prism.highlight(text, Prism.languages[lang], lang)
40
+ return prismjs.highlight(text, prismjs.languages[lang], lang)
48
41
  .replace(/(@\s*<span[^>]*)function("\s*>)/g, (a, pre, post) => `${pre}meta${post}`)
49
42
  .replace(/[{}]/g, a => `{{'${a}'}}`);
50
43
  } catch (err) {
@@ -1,6 +1,4 @@
1
- import * as path from 'path';
2
-
3
- import { PathUtil, FsUtil, Package, EnvUtil } from '@travetto/boot';
1
+ import { path } from '@travetto/manifest';
4
2
 
5
3
  import { AllType, AllTypeMap, node as n } from '../nodes';
6
4
  import { DocNode, RenderContextShape } from '../types';
@@ -13,31 +11,15 @@ export type AllChildren = AllType;
13
11
  export class RenderContext implements RenderContextShape {
14
12
 
15
13
  file: string;
14
+ baseUrl: string;
15
+ travettoBaseUrl: string;
16
+ repoRoot: string;
16
17
 
17
- constructor(file: string) {
18
- this.file = PathUtil.resolveUnix(file);
19
- }
20
-
21
- get #repoUrl(): string {
22
- return (Package.repository?.url ?? '').replace(/[.]git$/, '');
23
- }
24
-
25
- get gitBaseUrl(): string {
26
- return `${this.#repoUrl}/tree/${EnvUtil.get('TRV_DOC_BRANCH', 'main')}`;
27
- }
28
-
29
- get travettoGitBaseUrl(): string {
30
- return this.#repoUrl.includes('travetto/travetto') ? this.gitBaseUrl : 'https://github.com/travetto/travetto/main';
31
- }
32
-
33
- get gitFolder(): string {
34
- let base = PathUtil.cwd;
35
-
36
- while (base && !(FsUtil.existsSync(PathUtil.resolveUnix(base, '.git')))) {
37
- base = path.dirname(base);
38
- }
39
-
40
- return `${this.gitBaseUrl}${PathUtil.cwd.replace(base, '')}`;
18
+ constructor(file: string, repoRoot: string, baseUrl: string, travettoBaseUrl: string) {
19
+ this.file = path.toPosix(file);
20
+ this.baseUrl = baseUrl;
21
+ this.repoRoot = repoRoot;
22
+ this.travettoBaseUrl = travettoBaseUrl;
41
23
  }
42
24
 
43
25
  toc(root: DocNode): AllTypeMap['Ordered'] {
@@ -57,15 +39,14 @@ export class RenderContext implements RenderContextShape {
57
39
  return n.Group([
58
40
  n.Comment('This file was generated by @travetto/doc and should not be modified directly'),
59
41
  n.Text('\n'),
60
- n.Comment(`Please modify ${this.file.replace(PathUtil.cwd, this.gitFolder)} and execute "npx trv doc" to rebuild`),
42
+ n.Comment(`Please modify ${this.file.replace(this.repoRoot, this.baseUrl)} and execute "npx trv doc" to rebuild`),
61
43
  ]);
62
44
  }
63
45
 
64
46
  link(text: string, line?: number | { [key: string]: unknown, line?: number }): string {
65
47
  const num = typeof line === 'number' ? line : line?.line;
66
- text = PathUtil.normalizeFrameworkPath(text);
67
- return `${text.replace(PathUtil.cwd, this.gitBaseUrl)
68
- .replace(/.*@travetto\//, `${this.travettoGitBaseUrl}/module/`)}${num ? `#L${num}` : ''}`;
48
+ return `${text.replace(this.repoRoot, this.baseUrl)
49
+ .replace(/.*@travetto\//, `${this.travettoBaseUrl}/module/`)}${num ? `#L${num}` : ''}`;
69
50
  }
70
51
 
71
52
  cleanText(a?: string): string {
@@ -36,8 +36,9 @@ export const Html: Renderer = {
36
36
  case 'mod': return `<a class="module-link" href="${context.link(recurse(c.link), c)}" title="${recurse(c.description)}">${recurse(c.title)}</a>`;
37
37
  case 'image': return `<img src="${context.link(recurse(c.link), c)}" alt="${recurse(c.title)}">`;
38
38
  case 'section':
39
- case 'subsection': {
40
- const tag = c._type === 'section' ? 'h2' : 'h3';
39
+ case 'subsection':
40
+ case 'subsubsection': {
41
+ const tag = c._type === 'section' ? 'h2' : (c._type === 'subsection' ? 'h3' : 'h4');
41
42
  const title = recurse(c.title);
42
43
  return `<${tag} id="${context.getAnchorId(title)}">${title}</${tag}>`;
43
44
  }
@@ -30,6 +30,7 @@ ${context.cleanText(recurse(c.content))}
30
30
  case 'image': return `![${recurse(c.title)}](${context.link(recurse(c.link), c)})`;
31
31
  case 'section': return `## ${recurse(c.title)}`;
32
32
  case 'subsection': return `### ${recurse(c.title)}`;
33
+ case 'subsubsection': return `#### ${recurse(c.title)}`;
33
34
  case 'command':
34
35
  case 'method':
35
36
  case 'path':
@@ -60,7 +61,7 @@ ${context.cleanText(recurse(c.content))}
60
61
  case 'header':
61
62
  return `# ${recurse(c.title)}\n${c.description ? `## ${recurse(c.description)}\n` : ''}${'install' in c ? recurse(n.Install(c.package, c.package)) : ''}\n`;
62
63
  case 'text':
63
- return c.content;
64
+ return c.content.replace(/&nbsp;/g, ' ');
64
65
  }
65
66
  }
66
67
  };