clyops-doc 0.11.0 → 0.12.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/dist/model.d.ts CHANGED
@@ -11,6 +11,7 @@ export type Block = {
11
11
  items: {
12
12
  term: string;
13
13
  text: string;
14
+ schema?: string;
14
15
  }[];
15
16
  } | {
16
17
  kind: 'h';
@@ -101,6 +102,11 @@ export declare function synopsis(name: string, leaf: Leaf): string;
101
102
  export declare function optionLabel(o: SchemaOption): string;
102
103
  /** An option's description with its notes, as help annotates it (spec section 7). */
103
104
  export declare function optionText(o: SchemaOption): string;
105
+ /**
106
+ * A `json:SCHEMA` input's schema as indented JSON, without `$schema`; none for an input
107
+ * without one or one that only references a URL, which `accepts:` already names.
108
+ */
109
+ export declare function schemaText(item: SchemaOption | SchemaArgument): string | undefined;
104
110
  /** The first sentence of a description (its first line at most), for the NAME line. */
105
111
  export declare function firstSentence(text: string): string;
106
112
  /** Today in UTC, or SOURCE_DATE_EPOCH's date for reproducible builds. */
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
package/dist/model.js CHANGED
@@ -78,6 +78,26 @@ function argumentText(a) {
78
78
  notes.push(`accepts: ${describeRule(a.validation)}`);
79
79
  return notes.length ? `${a.description}${a.description ? ' ' : ''}(${notes.join('; ')})` : a.description;
80
80
  }
81
+ /**
82
+ * A `json:SCHEMA` input's schema as indented JSON, without `$schema`; none for an input
83
+ * without one or one that only references a URL, which `accepts:` already names.
84
+ */
85
+ export function schemaText(item) {
86
+ const schema = item.schema;
87
+ if (!item.validation.startsWith('json:') || schema === null || schema === undefined)
88
+ return undefined;
89
+ if (typeof schema !== 'object' || Array.isArray(schema))
90
+ return JSON.stringify(schema);
91
+ const { $schema: _version, ...rest } = schema;
92
+ const keys = Object.keys(rest);
93
+ if (keys.length === 0 || (keys.length === 1 && keys[0] === '$ref'))
94
+ return undefined;
95
+ return JSON.stringify(rest, null, 2);
96
+ }
97
+ const withSchema = (item, term, text) => {
98
+ const schema = schemaText(item);
99
+ return schema ? { term, text, schema } : { term, text };
100
+ };
81
101
  function stream(s) {
82
102
  return [s.description, s.contentType && `(${s.contentType})`].filter(Boolean).join(' ') || 'Declared, without a description.';
83
103
  }
@@ -108,8 +128,8 @@ function leafParts(leaf) {
108
128
  ...leaf.requiredCommands.map((r) => `Needs ${r.command} on PATH: ${r.description}${r.installHint ? ` (${r.installHint})` : ''}.`),
109
129
  ].filter(Boolean);
110
130
  return {
111
- args: dl(leaf.arguments.map((a) => ({ term: a.isVariadic ? `<${a.name}...>` : `<${a.name}>`, text: argumentText(a) }))),
112
- options: dl(leaf.options.filter((o) => o.name !== 'help').map((o) => ({ term: optionLabel(o), text: optionText(o) }))),
131
+ args: dl(leaf.arguments.map((a) => withSchema(a, a.isVariadic ? `<${a.name}...>` : `<${a.name}>`, argumentText(a)))),
132
+ options: dl(leaf.options.filter((o) => o.name !== 'help').map((o) => withSchema(o, optionLabel(o), optionText(o)))),
113
133
  streams: dl(streams),
114
134
  notes: notes.map((text) => ({ kind: 'p', text })),
115
135
  };
package/dist/render.js CHANGED
@@ -24,7 +24,7 @@ function manBlock(b) {
24
24
  case 'pre':
25
25
  return ['.PP', '.nf', '.RS 4', troff(b.text), '.RE', '.fi'];
26
26
  case 'dl':
27
- return b.items.flatMap((i) => ['.TP', `\\fB${troff(i.term)}\\fR`, troff(i.text)]);
27
+ return b.items.flatMap((i) => ['.TP', `\\fB${troff(i.term)}\\fR`, troff(i.text), ...(i.schema ? ['.RS', '.PP', 'JSON Schema:', '.nf', troff(i.schema), '.fi', '.RE'] : [])]);
28
28
  case 'refs':
29
29
  return ['.PP', ...b.items.map((r, n) => `.BR ${arg(r.page)} ${arg(`(${r.section})${n < b.items.length - 1 ? ',' : ''}`)}`)];
30
30
  }
@@ -72,10 +72,10 @@ function code(text) {
72
72
  const fence = '`'.repeat(run);
73
73
  return run > 1 ? `${fence} ${text} ${fence}` : `${fence}${text}${fence}`;
74
74
  }
75
- function fenced(text) {
75
+ function fenced(text, info = '') {
76
76
  const run = Math.max(2, ...(text.match(/`+/g) ?? []).map((m) => m.length)) + 1;
77
77
  const fence = '`'.repeat(run);
78
- return [fence, text, fence];
78
+ return [fence + info, text, fence];
79
79
  }
80
80
  function markdownBlock(b) {
81
81
  switch (b.kind) {
@@ -86,7 +86,7 @@ function markdownBlock(b) {
86
86
  case 'pre':
87
87
  return [...fenced(b.text), ''];
88
88
  case 'dl':
89
- return [...b.items.map((i) => `- ${code(i.term)}: ${markdownText(i.text)}`), ''];
89
+ return [...b.items.flatMap((i) => [`- ${code(i.term)}: ${markdownText(i.text)}`, ...(i.schema ? ['', ' JSON Schema:', '', ...fenced(i.schema, 'json').join('\n').split('\n').map((l) => ` ${l}`), ''] : [])]), ''];
90
90
  case 'refs':
91
91
  return [b.items.map((r) => `[${markdownText(`${r.page}(${r.section})`)}](${encodeURI(r.page)}.md)`).join(', '), ''];
92
92
  }
@@ -123,7 +123,7 @@ function htmlBlock(b) {
123
123
  case 'pre':
124
124
  return `<pre><code>${htmlText(b.text)}</code></pre>`;
125
125
  case 'dl':
126
- return `<dl>\n${b.items.map((i) => `<dt><code>${htmlText(i.term)}</code></dt>\n<dd>${htmlText(i.text)}</dd>`).join('\n')}\n</dl>`;
126
+ return `<dl>\n${b.items.map((i) => `<dt><code>${htmlText(i.term)}</code></dt>\n<dd>${htmlText(i.text)}${i.schema ? `\n<details><summary>JSON Schema</summary><pre><code>${htmlText(i.schema)}</code></pre></details>` : ''}</dd>`).join('\n')}\n</dl>`;
127
127
  case 'refs':
128
128
  return `<p>${b.items.map((r) => `<a href="${htmlText(encodeURI(r.page))}.html"><code>${htmlText(r.page)}</code>(${htmlText(r.section)})</a>`).join(', ')}</p>`;
129
129
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clyops-doc",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Documentation (man pages, Markdown, HTML) from any clyops tool's --help-json-schema.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -36,9 +36,9 @@
36
36
  "src"
37
37
  ],
38
38
  "dependencies": {
39
- "clyops": "0.11.0",
40
- "clyops-schema": "0.11.0",
41
- "clyops-tools": "0.11.0"
39
+ "clyops": "0.12.0",
40
+ "clyops-schema": "0.12.0",
41
+ "clyops-tools": "0.12.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^22.0.0",
package/src/model.ts CHANGED
@@ -7,7 +7,7 @@ import type { Schema, SchemaArgument, SchemaBody, SchemaConfig, SchemaOption, Sc
7
7
  export type Block =
8
8
  | { /** A paragraph of plain text. */ kind: 'p'; text: string }
9
9
  | { /** Text shown as is, in a fixed-width font. */ kind: 'pre'; text: string }
10
- | { /** A list of terms, each with its description. */ kind: 'dl'; items: { term: string; text: string }[] }
10
+ | { /** A list of terms, each with its description and, for a `json:SCHEMA` input, its schema as indented JSON. */ kind: 'dl'; items: { term: string; text: string; schema?: string }[] }
11
11
  | { /** A subsection heading, e.g. one per command. */ kind: 'h'; text: string }
12
12
  | { /** Other pages, as SEE ALSO lists them: `page(section)`, linked in Markdown and HTML. */ kind: 'refs'; items: { page: string; section: string }[] };
13
13
 
@@ -148,6 +148,25 @@ function argumentText(a: SchemaArgument): string {
148
148
  return notes.length ? `${a.description}${a.description ? ' ' : ''}(${notes.join('; ')})` : a.description;
149
149
  }
150
150
 
151
+ /**
152
+ * A `json:SCHEMA` input's schema as indented JSON, without `$schema`; none for an input
153
+ * without one or one that only references a URL, which `accepts:` already names.
154
+ */
155
+ export function schemaText(item: SchemaOption | SchemaArgument): string | undefined {
156
+ const schema = item.schema;
157
+ if (!item.validation.startsWith('json:') || schema === null || schema === undefined) return undefined;
158
+ if (typeof schema !== 'object' || Array.isArray(schema)) return JSON.stringify(schema);
159
+ const { $schema: _version, ...rest } = schema as Record<string, unknown>;
160
+ const keys = Object.keys(rest);
161
+ if (keys.length === 0 || (keys.length === 1 && keys[0] === '$ref')) return undefined;
162
+ return JSON.stringify(rest, null, 2);
163
+ }
164
+
165
+ const withSchema = (item: SchemaOption | SchemaArgument, term: string, text: string) => {
166
+ const schema = schemaText(item);
167
+ return schema ? { term, text, schema } : { term, text };
168
+ };
169
+
151
170
  function stream(s: SchemaStream): string {
152
171
  return [s.description, s.contentType && `(${s.contentType})`].filter(Boolean).join(' ') || 'Declared, without a description.';
153
172
  }
@@ -167,7 +186,7 @@ const EFFECTS: Record<string, string> = {
167
186
 
168
187
  /** A leaf's parts: its arguments, options and streams as definition lists, and notes as text. */
169
188
  function leafParts(leaf: Leaf): { args?: Block; options?: Block; streams?: Block; notes: Block[] } {
170
- const dl = (items: { term: string; text: string }[]): Block | undefined => (items.length ? { kind: 'dl', items } : undefined);
189
+ const dl = (items: { term: string; text: string; schema?: string }[]): Block | undefined => (items.length ? { kind: 'dl', items } : undefined);
171
190
  const streams = [
172
191
  ...(leaf.stdin ? [{ term: 'stdin', text: stream(leaf.stdin) }] : []),
173
192
  ...(leaf.stdout ? [{ term: 'stdout', text: stream(leaf.stdout) }] : []),
@@ -181,8 +200,8 @@ function leafParts(leaf: Leaf): { args?: Block; options?: Block; streams?: Block
181
200
  ...leaf.requiredCommands.map((r) => `Needs ${r.command} on PATH: ${r.description}${r.installHint ? ` (${r.installHint})` : ''}.`),
182
201
  ].filter(Boolean);
183
202
  return {
184
- args: dl(leaf.arguments.map((a) => ({ term: a.isVariadic ? `<${a.name}...>` : `<${a.name}>`, text: argumentText(a) }))),
185
- options: dl(leaf.options.filter((o) => o.name !== 'help').map((o) => ({ term: optionLabel(o), text: optionText(o) }))),
203
+ args: dl(leaf.arguments.map((a) => withSchema(a, a.isVariadic ? `<${a.name}...>` : `<${a.name}>`, argumentText(a)))),
204
+ options: dl(leaf.options.filter((o) => o.name !== 'help').map((o) => withSchema(o, optionLabel(o), optionText(o)))),
186
205
  streams: dl(streams),
187
206
  notes: notes.map((text) => ({ kind: 'p', text })),
188
207
  };
package/src/render.ts CHANGED
@@ -33,7 +33,7 @@ function manBlock(b: Block): string[] {
33
33
  case 'pre':
34
34
  return ['.PP', '.nf', '.RS 4', troff(b.text), '.RE', '.fi'];
35
35
  case 'dl':
36
- return b.items.flatMap((i) => ['.TP', `\\fB${troff(i.term)}\\fR`, troff(i.text)]);
36
+ return b.items.flatMap((i) => ['.TP', `\\fB${troff(i.term)}\\fR`, troff(i.text), ...(i.schema ? ['.RS', '.PP', 'JSON Schema:', '.nf', troff(i.schema), '.fi', '.RE'] : [])]);
37
37
  case 'refs':
38
38
  return ['.PP', ...b.items.map((r, n) => `.BR ${arg(r.page)} ${arg(`(${r.section})${n < b.items.length - 1 ? ',' : ''}`)}`)];
39
39
  }
@@ -86,10 +86,10 @@ function code(text: string): string {
86
86
  return run > 1 ? `${fence} ${text} ${fence}` : `${fence}${text}${fence}`;
87
87
  }
88
88
 
89
- function fenced(text: string): string[] {
89
+ function fenced(text: string, info = ''): string[] {
90
90
  const run = Math.max(2, ...(text.match(/`+/g) ?? []).map((m) => m.length)) + 1;
91
91
  const fence = '`'.repeat(run);
92
- return [fence, text, fence];
92
+ return [fence + info, text, fence];
93
93
  }
94
94
 
95
95
  function markdownBlock(b: Block): string[] {
@@ -101,7 +101,7 @@ function markdownBlock(b: Block): string[] {
101
101
  case 'pre':
102
102
  return [...fenced(b.text), ''];
103
103
  case 'dl':
104
- return [...b.items.map((i) => `- ${code(i.term)}: ${markdownText(i.text)}`), ''];
104
+ return [...b.items.flatMap((i) => [`- ${code(i.term)}: ${markdownText(i.text)}`, ...(i.schema ? ['', ' JSON Schema:', '', ...fenced(i.schema, 'json').join('\n').split('\n').map((l) => ` ${l}`), ''] : [])]), ''];
105
105
  case 'refs':
106
106
  return [b.items.map((r) => `[${markdownText(`${r.page}(${r.section})`)}](${encodeURI(r.page)}.md)`).join(', '), ''];
107
107
  }
@@ -142,7 +142,7 @@ function htmlBlock(b: Block): string {
142
142
  case 'pre':
143
143
  return `<pre><code>${htmlText(b.text)}</code></pre>`;
144
144
  case 'dl':
145
- return `<dl>\n${b.items.map((i) => `<dt><code>${htmlText(i.term)}</code></dt>\n<dd>${htmlText(i.text)}</dd>`).join('\n')}\n</dl>`;
145
+ return `<dl>\n${b.items.map((i) => `<dt><code>${htmlText(i.term)}</code></dt>\n<dd>${htmlText(i.text)}${i.schema ? `\n<details><summary>JSON Schema</summary><pre><code>${htmlText(i.schema)}</code></pre></details>` : ''}</dd>`).join('\n')}\n</dl>`;
146
146
  case 'refs':
147
147
  return `<p>${b.items.map((r) => `<a href="${htmlText(encodeURI(r.page))}.html"><code>${htmlText(r.page)}</code>(${htmlText(r.section)})</a>`).join(', ')}</p>`;
148
148
  }