@travetto/doc 7.1.3 → 8.0.0-alpha.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/__index__.ts +2 -1
- package/package.json +4 -4
- package/src/jsx.ts +6 -8
- package/src/mapping/library.ts +2 -1
- package/src/render/html.ts +2 -1
- package/src/render/markdown.ts +2 -1
- package/src/render/renderer.ts +2 -2
- package/src/util/file.ts +12 -7
- package/src/util/package.ts +46 -0
- package/src/util/resolve.ts +10 -10
- package/src/util/run.ts +1 -1
- package/src/util/types.ts +3 -1
package/__index__.ts
CHANGED
|
@@ -2,4 +2,5 @@ export { type JSXElement as DocJSXElement, isJSXElement as isDocJSXElement } fro
|
|
|
2
2
|
export { c, d, JSXElementByFn as DocJSXElementByFn } from './src/jsx.ts';
|
|
3
3
|
export { MODULES as module } from './src/mapping/module.ts';
|
|
4
4
|
export { DocFileUtil } from './src/util/file.ts';
|
|
5
|
-
export { DocRunUtil, COMMON_DATE } from './src/util/run.ts';
|
|
5
|
+
export { DocRunUtil, COMMON_DATE } from './src/util/run.ts';
|
|
6
|
+
export { PackageDocUtil } from './src/util/package.ts';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/doc",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0-alpha.0",
|
|
4
4
|
"description": "Documentation support for the Travetto framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"directory": "module/doc"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@travetto/runtime": "^
|
|
28
|
-
"@types/prismjs": "^1.26.
|
|
27
|
+
"@travetto/runtime": "^8.0.0-alpha.0",
|
|
28
|
+
"@types/prismjs": "^1.26.6",
|
|
29
29
|
"prismjs": "^1.30.0"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@travetto/cli": "^
|
|
32
|
+
"@travetto/cli": "^8.0.0-alpha.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependenciesMeta": {
|
|
35
35
|
"@travetto/cli": {
|
package/src/jsx.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { castTo,
|
|
2
|
-
import { PackageUtil } from '@travetto/manifest';
|
|
1
|
+
import { castTo, TypedObject } from '@travetto/runtime';
|
|
3
2
|
|
|
4
3
|
import type { LIBRARIES } from './mapping/library.ts';
|
|
5
4
|
import type { MODULES } from './mapping/module.ts';
|
|
6
|
-
import type { CodeProps, RunConfig } from './util/types.ts';
|
|
5
|
+
import type { CodeProps, CodeSourceInput, RunConfig } from './util/types.ts';
|
|
7
6
|
|
|
8
7
|
import { createElement, type JSXElement, type JSXComponentFunction as CompFn } from '../support/jsx-runtime.ts';
|
|
8
|
+
import { PackageDocUtil } from './util/package.ts';
|
|
9
9
|
|
|
10
10
|
type InstallProps = { title: string, pkg: string };
|
|
11
11
|
type ExecProps = { title: string, cmd: string, args?: string[], config?: RunConfig & { formatCommand?(cmd: string, args: string[]): string } };
|
|
@@ -14,7 +14,7 @@ type HeaderProps = { title: string, description?: string };
|
|
|
14
14
|
type ModuleProps = { name: keyof typeof MODULES };
|
|
15
15
|
type LibraryProps = { name: keyof typeof LIBRARIES };
|
|
16
16
|
type LinkProps = { title: string, href: string, line?: number };
|
|
17
|
-
type CodeLinkProps = { title: string, src:
|
|
17
|
+
type CodeLinkProps = { title: string, src: CodeSourceInput, startRe: RegExp };
|
|
18
18
|
type Named = { name: string };
|
|
19
19
|
type Titled = { title: string };
|
|
20
20
|
|
|
@@ -83,7 +83,7 @@ function CodeLinker(titleOrNode: string | JSXElement, src?: string, startRe?: Re
|
|
|
83
83
|
props = { title: titleOrNode, src: src!, startRe: startRe! };
|
|
84
84
|
} else if (titleOrNode.type === Code) {
|
|
85
85
|
const node: JSXElementByFn<'Code'> = castTo(titleOrNode);
|
|
86
|
-
const srcName = typeof node.props.src === 'string' ? node.props.src : node.props.src.name;
|
|
86
|
+
const srcName = typeof node.props.src === 'string' ? node.props.src : (typeof node.props.src === 'function' ? node.props.src.name : '<UNNAMED>');
|
|
87
87
|
props = {
|
|
88
88
|
title: node.props.title ?? srcName,
|
|
89
89
|
src: node.props.src,
|
|
@@ -106,7 +106,5 @@ export const d = {
|
|
|
106
106
|
field: (name: string) => createElement(c.Field, { name }),
|
|
107
107
|
library: (name: keyof typeof LIBRARIES) => createElement(c.Library, { name }),
|
|
108
108
|
module: (name: keyof typeof MODULES) => createElement(c.Module, { name }),
|
|
109
|
-
|
|
110
|
-
workspaceInitCommand: () => PackageUtil.getWorkspaceInitCommand(Runtime),
|
|
111
|
-
get trv() { return PackageUtil.getPackageCommand(Runtime, 'trv'); },
|
|
109
|
+
get trv() { return PackageDocUtil.getPackageCommand('trv'); },
|
|
112
110
|
};
|
package/src/mapping/library.ts
CHANGED
|
@@ -5,7 +5,8 @@ export const LIBRARIES = {
|
|
|
5
5
|
Node: { title: 'Node', href: 'https://nodejs.org' },
|
|
6
6
|
TravettoPlugin: { title: 'VSCode plugin', href: 'https://marketplace.visualstudio.com/items?itemName=arcsine.travetto-plugin' },
|
|
7
7
|
Npm: { title: 'Npm', href: 'https://docs.npmjs.com/downloading-and-installing-node-js-and-npm' },
|
|
8
|
-
Yarn: { title: 'Yarn', href: 'https://
|
|
8
|
+
Yarn: { title: 'Yarn', href: 'https://yarnpkg.com' },
|
|
9
|
+
Pnpm: { title: 'Pnpm', href: 'https://pnpm.io/' },
|
|
9
10
|
Eslint: { title: 'ESLint', href: 'https://eslint.org/' },
|
|
10
11
|
Rollup: { title: 'Rollup', href: 'https://rollupjs.org/' },
|
|
11
12
|
TSConfig: { title: 'TS Config', href: 'https://www.typescriptlang.org/docs/handbook/tsconfig-json.html' },
|
package/src/render/html.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { LIBRARIES } from '../mapping/library.ts';
|
|
|
11
11
|
import type { RenderContext } from './context.ts';
|
|
12
12
|
import { DocResolveUtil } from '../util/resolve.ts';
|
|
13
13
|
import type { JSXElement } from '../../support/jsx-runtime.ts';
|
|
14
|
+
import { PackageDocUtil } from '../util/package.ts';
|
|
14
15
|
|
|
15
16
|
const ESCAPE_ENTITIES: Record<string, string> = { '<': '<', '>': '>', '&': '&', '{': "{{'{'}}", '}': "{{'}'}}" };
|
|
16
17
|
const ENTITY_REGEX = new RegExp(`[${Object.keys(ESCAPE_ENTITIES).join('')}]`, 'gm');
|
|
@@ -52,7 +53,7 @@ export const Html: RenderProvider<RenderContext> = {
|
|
|
52
53
|
},
|
|
53
54
|
Install: async ({ context, node }) => {
|
|
54
55
|
const highlighted = highlight(`
|
|
55
|
-
${
|
|
56
|
+
${PackageDocUtil.getInstallInstructions(node.props.pkg, true)}
|
|
56
57
|
`, 'bash');
|
|
57
58
|
|
|
58
59
|
return `\n
|
package/src/render/markdown.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { MODULES } from '../mapping/module.ts';
|
|
|
9
9
|
import { LIBRARIES } from '../mapping/library.ts';
|
|
10
10
|
import type { RenderContext } from './context.ts';
|
|
11
11
|
import { DocResolveUtil } from '../util/resolve.ts';
|
|
12
|
+
import { PackageDocUtil } from '../util/package.ts';
|
|
12
13
|
|
|
13
14
|
export const Markdown: RenderProvider<RenderContext> = {
|
|
14
15
|
ext: 'md',
|
|
@@ -55,7 +56,7 @@ export const Markdown: RenderProvider<RenderContext> = {
|
|
|
55
56
|
Install: async ({ context, node }) =>
|
|
56
57
|
`\n\n**Install: ${node.props.title}**
|
|
57
58
|
\`\`\`bash
|
|
58
|
-
${
|
|
59
|
+
${PackageDocUtil.getInstallInstructions(node.props.pkg, true)}
|
|
59
60
|
\`\`\`
|
|
60
61
|
`,
|
|
61
62
|
Code: async ({ context, node, props }) => {
|
package/src/render/renderer.ts
CHANGED
|
@@ -45,10 +45,10 @@ export class DocRenderer {
|
|
|
45
45
|
) {
|
|
46
46
|
const source = DocFileUtil.readSource(cls);
|
|
47
47
|
if (source) {
|
|
48
|
-
title =
|
|
48
|
+
title = DocFileUtil.isDecorator(cls.name, source.file) ? `@${title ?? cls.name}` : (title ?? cls.name);
|
|
49
49
|
const node = this.#support.createElement('CodeLink', {
|
|
50
50
|
src: source.file,
|
|
51
|
-
startRe: new RegExp(`(class|function|interface)\\s+(${cls.name
|
|
51
|
+
startRe: new RegExp(`(class|function|interface)\\s+(${RegExp.escape(cls.name)})`),
|
|
52
52
|
title
|
|
53
53
|
});
|
|
54
54
|
// @ts-expect-error
|
package/src/util/file.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { readFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { RuntimeError, Runtime, RuntimeIndex } from '@travetto/runtime';
|
|
5
5
|
import { type ManifestModuleFileType, ManifestModuleUtil } from '@travetto/manifest';
|
|
6
6
|
|
|
7
|
+
import type { CodeSourceInput } from './types.ts';
|
|
8
|
+
|
|
7
9
|
const ESLINT_PATTERN = /\s{0,10}\/\/ eslint.{0,300}$/g;
|
|
8
10
|
const ENV_KEY = /Env.([^.]{1,100})[.]key/g;
|
|
9
11
|
|
|
@@ -24,6 +26,9 @@ const EXT_TO_LANG: Record<string, string> = {
|
|
|
24
26
|
'.sh': 'bash',
|
|
25
27
|
};
|
|
26
28
|
|
|
29
|
+
type SourceOutput = { content: string, language: string, file: string };
|
|
30
|
+
type SnippetOutput = { file: string, startIdx: number, lines: string[], language: string };
|
|
31
|
+
|
|
27
32
|
/**
|
|
28
33
|
* Standard file utilities
|
|
29
34
|
*/
|
|
@@ -35,7 +40,7 @@ export class DocFileUtil {
|
|
|
35
40
|
return /^[@:A-Za-z0-9\/\\\-_.]+[.]([a-z]{2,10})$/.test(file);
|
|
36
41
|
}
|
|
37
42
|
|
|
38
|
-
static readSource(input:
|
|
43
|
+
static readSource(input: Exclude<CodeSourceInput, Promise<string>>): SourceOutput {
|
|
39
44
|
let file: string | undefined;
|
|
40
45
|
let content: string | undefined;
|
|
41
46
|
|
|
@@ -55,7 +60,7 @@ export class DocFileUtil {
|
|
|
55
60
|
} else {
|
|
56
61
|
file = Runtime.getSourceFile(input);
|
|
57
62
|
if (!existsSync(file)) {
|
|
58
|
-
throw new
|
|
63
|
+
throw new RuntimeError(`Unknown file: ${typeof input === 'string' ? input : input.name} => ${file}`);
|
|
59
64
|
}
|
|
60
65
|
content = readFileSync(file, 'utf8');
|
|
61
66
|
}
|
|
@@ -83,8 +88,8 @@ export class DocFileUtil {
|
|
|
83
88
|
}
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
static async readCodeSnippet(input:
|
|
87
|
-
const result = this.readSource(input);
|
|
91
|
+
static async readCodeSnippet(input: CodeSourceInput, startPattern: RegExp): Promise<SnippetOutput> {
|
|
92
|
+
const result = this.readSource(await input);
|
|
88
93
|
const lines = result.content.split(/\n/);
|
|
89
94
|
const startIdx = lines.findIndex(line => startPattern.test(line));
|
|
90
95
|
if (startIdx < 0) {
|
|
@@ -96,14 +101,14 @@ export class DocFileUtil {
|
|
|
96
101
|
/**
|
|
97
102
|
* Determine if a file is a decorator
|
|
98
103
|
*/
|
|
99
|
-
static
|
|
104
|
+
static isDecorator(name: string, file: string): boolean {
|
|
100
105
|
|
|
101
106
|
const key = `${name}:${file}`;
|
|
102
107
|
if (key in this.#decCache) {
|
|
103
108
|
return this.#decCache[key];
|
|
104
109
|
}
|
|
105
110
|
|
|
106
|
-
const text =
|
|
111
|
+
const text = this.readSource(file);
|
|
107
112
|
const lines = text.content.split(/\n/g);
|
|
108
113
|
|
|
109
114
|
const start = lines.findIndex(line => new RegExp(`function ${name}\\b`).test(line));
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { PACKAGE_MANAGERS, type NodePackageManager } from '@travetto/manifest';
|
|
2
|
+
import { Runtime } from '@travetto/runtime';
|
|
3
|
+
|
|
4
|
+
export class PackageDocUtil {
|
|
5
|
+
/**
|
|
6
|
+
* Get an the command for executing a package level binary
|
|
7
|
+
*/
|
|
8
|
+
static getPackageCommand(pkg: string, args: string[] = [], manager?: NodePackageManager): string {
|
|
9
|
+
switch (manager ?? Runtime.workspace.manager) {
|
|
10
|
+
case 'npm':
|
|
11
|
+
case 'yarn': return `npx ${pkg} ${args.join(' ')}`.trim();
|
|
12
|
+
case 'pnpm': return `pnpm ${pkg} ${args.join(' ')}`.trim();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get an the command for executing a package level binary
|
|
18
|
+
*/
|
|
19
|
+
static getWorkspaceInitCommand(manager?: NodePackageManager): string {
|
|
20
|
+
switch (manager ?? Runtime.workspace.manager) {
|
|
21
|
+
case 'npm': return 'npm init -f';
|
|
22
|
+
case 'yarn': return 'yarn init -y';
|
|
23
|
+
case 'pnpm': return 'pnpm init -y';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get an install command for a given npm module
|
|
29
|
+
*/
|
|
30
|
+
static getInstallCommand(pkg: string, production = false, manager?: NodePackageManager): string {
|
|
31
|
+
switch (manager ?? Runtime.workspace.manager) {
|
|
32
|
+
case 'npm': return `npm install ${production ? '' : '--save-dev '}${pkg}`;
|
|
33
|
+
case 'yarn': return `yarn add ${production ? '' : '--dev '}${pkg}`;
|
|
34
|
+
case 'pnpm': return `pnpm add ${production ? '' : '--dev '}${pkg}`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get install example for a given package
|
|
40
|
+
*/
|
|
41
|
+
static getInstallInstructions(pkg: string, production = false): string {
|
|
42
|
+
return PACKAGE_MANAGERS
|
|
43
|
+
.map(manager => this.getInstallCommand(pkg, production, manager.type))
|
|
44
|
+
.join('\n\n# or\n\n');
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/util/resolve.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DocFileUtil } from './file.ts';
|
|
2
|
-
import type { CodeProps } from './types.ts';
|
|
2
|
+
import type { CodeProps, CodeSourceInput } from './types.ts';
|
|
3
3
|
|
|
4
4
|
export type ResolvedRef = { title: string, file: string, line: number };
|
|
5
5
|
export type ResolvedCode = { text: string, language: string, file?: string };
|
|
@@ -14,26 +14,26 @@ export class DocResolveUtil {
|
|
|
14
14
|
static async resolveRef(title: string, file: string): Promise<ResolvedRef> {
|
|
15
15
|
|
|
16
16
|
let line = 0;
|
|
17
|
-
const result =
|
|
17
|
+
const result = DocFileUtil.readSource(file);
|
|
18
18
|
file = result.file;
|
|
19
19
|
|
|
20
20
|
if (result.content) {
|
|
21
21
|
line = result.content.split(/\n/g)
|
|
22
|
-
.findIndex(lineText => new RegExp(`(class|interface|function)[ ]+${
|
|
22
|
+
.findIndex(lineText => new RegExp(`(class|interface|function)[ ]+${RegExp.escape(title)}`).test(lineText));
|
|
23
23
|
if (line < 0) {
|
|
24
24
|
line = 0;
|
|
25
25
|
} else {
|
|
26
26
|
line += 1;
|
|
27
27
|
}
|
|
28
|
-
if (
|
|
28
|
+
if (DocFileUtil.isDecorator(title, file)) {
|
|
29
29
|
title = `@${title}`;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
return { title, file, line };
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
static async resolveCode(content:
|
|
36
|
-
const result = DocFileUtil.readSource(content);
|
|
35
|
+
static async resolveCode(content: CodeSourceInput, language?: string, outline = false): Promise<ResolvedCode> {
|
|
36
|
+
const result = DocFileUtil.readSource(await content);
|
|
37
37
|
let text = result.content;
|
|
38
38
|
|
|
39
39
|
let file: string | undefined;
|
|
@@ -47,7 +47,7 @@ export class DocResolveUtil {
|
|
|
47
47
|
return { text, language: language!, file };
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
static async resolveSnippet(file:
|
|
50
|
+
static async resolveSnippet(file: CodeSourceInput, startPattern: RegExp, endPattern?: RegExp, outline = false): Promise<ResolvedSnippet> {
|
|
51
51
|
const { lines, startIdx, language, file: resolvedFile } = await DocFileUtil.readCodeSnippet(file, startPattern);
|
|
52
52
|
|
|
53
53
|
const endIdx = endPattern ? lines.findIndex((line, i) => i > startIdx && endPattern.test(line)) : lines.length;
|
|
@@ -60,14 +60,14 @@ export class DocResolveUtil {
|
|
|
60
60
|
return { text, language, line: startIdx + 1, file: resolvedFile };
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
static async resolveCodeLink(file:
|
|
63
|
+
static async resolveCodeLink(file: CodeSourceInput, startPattern: RegExp): Promise<ResolvedSnippetLink> {
|
|
64
64
|
const { startIdx, file: resolvedFile } = await DocFileUtil.readCodeSnippet(file, startPattern);
|
|
65
65
|
return { file: resolvedFile, line: startIdx + 1 };
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
static applyCodePropDefaults(props: CodeProps) {
|
|
68
|
+
static applyCodePropDefaults(props: CodeProps): void {
|
|
69
69
|
const type = typeof props.src === 'function' ? props.src : undefined;
|
|
70
|
-
props.startRe ??= (type ? new RegExp(`^(export)?\\s*(interface|class)\\s+${type.name
|
|
70
|
+
props.startRe ??= (type ? new RegExp(`^(export)?\\s*(interface|class)\\s+${RegExp.escape(type.name)}\\b`) : undefined);
|
|
71
71
|
props.language ??= (type ? 'typescript' : undefined);
|
|
72
72
|
props.endRe ??= (type ? /^[}]/ : undefined);
|
|
73
73
|
props.title ??= typeof props.src == 'function' ? props.src.name.replace(/^[$]/, '') : undefined;
|
package/src/util/run.ts
CHANGED
|
@@ -6,7 +6,7 @@ import path from 'node:path';
|
|
|
6
6
|
import { Env, ExecUtil, Runtime, RuntimeIndex } from '@travetto/runtime';
|
|
7
7
|
import type { RunConfig } from './types.ts';
|
|
8
8
|
|
|
9
|
-
export const COMMON_DATE = new Date('2029-03-14T00:00:00.000').getTime();
|
|
9
|
+
export const COMMON_DATE = new Date('2029-03-14T00:00:00.000-0400').getTime();
|
|
10
10
|
|
|
11
11
|
class DocState {
|
|
12
12
|
baseline = COMMON_DATE;
|
package/src/util/types.ts
CHANGED
|
@@ -9,4 +9,6 @@ export type RunConfig = {
|
|
|
9
9
|
spawn?: (cmd: string, args: string[], options: SpawnOptions) => ChildProcess;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
export type
|
|
12
|
+
export type CodeSourceInput = string | Promise<string> | Function;
|
|
13
|
+
|
|
14
|
+
export type CodeProps = { title?: string, src: CodeSourceInput, language?: string, outline?: boolean, startRe?: RegExp, endRe?: RegExp };
|