@xyd-js/opencli-remark 0.0.0-build-b7bd05c-20260701151111

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +222 -0
  4. package/dist/index.cjs +290 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.d.cts +36 -0
  7. package/dist/index.d.ts +36 -0
  8. package/dist/index.js +271 -0
  9. package/dist/index.js.map +1 -0
  10. package/index.ts +4 -0
  11. package/opencli-spec.json +382 -0
  12. package/package.json +36 -0
  13. package/src/__fixtures__/1.code-block-format/input.md +15 -0
  14. package/src/__fixtures__/1.code-block-format/output.md +15 -0
  15. package/src/__fixtures__/10.variadic-arguments/input.md +5 -0
  16. package/src/__fixtures__/10.variadic-arguments/output.md +5 -0
  17. package/src/__fixtures__/11.no-matching-key/actual.md +30 -0
  18. package/src/__fixtures__/11.no-matching-key/input.md +30 -0
  19. package/src/__fixtures__/11.no-matching-key/output.md +30 -0
  20. package/src/__fixtures__/2.list-format/input.md +16 -0
  21. package/src/__fixtures__/2.list-format/output.md +19 -0
  22. package/src/__fixtures__/3.root-command/input.md +9 -0
  23. package/src/__fixtures__/3.root-command/output.md +9 -0
  24. package/src/__fixtures__/4.nested-command/input.md +14 -0
  25. package/src/__fixtures__/4.nested-command/output.md +17 -0
  26. package/src/__fixtures__/5.command-alias/input.md +7 -0
  27. package/src/__fixtures__/5.command-alias/output.md +7 -0
  28. package/src/__fixtures__/6.options-with-arguments/input.md +9 -0
  29. package/src/__fixtures__/6.options-with-arguments/output.md +10 -0
  30. package/src/__fixtures__/7.no-args-or-opts/input.md +13 -0
  31. package/src/__fixtures__/7.no-args-or-opts/output.md +13 -0
  32. package/src/__fixtures__/8.multiple-placeholders/input.md +11 -0
  33. package/src/__fixtures__/8.multiple-placeholders/output.md +12 -0
  34. package/src/__fixtures__/9.list-format-arguments/input.md +8 -0
  35. package/src/__fixtures__/9.list-format-arguments/output.md +9 -0
  36. package/src/__fixtures__/opencli-spec.json +81 -0
  37. package/src/__tests__/generate-types.ts +30 -0
  38. package/src/__tests__/remark-opencli.test.ts +100 -0
  39. package/src/__tests__/testHelpers.ts +110 -0
  40. package/src/__tests__/types.gen.ts +1 -0
  41. package/src/remark-opencli.ts +386 -0
  42. package/src/types.ts +269 -0
  43. package/tsconfig.json +18 -0
  44. package/tsup.config.ts +19 -0
  45. package/vitest.config.ts +8 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # @xyd-js/opencli-remark
2
+
3
+ ## 0.0.0-build-b7bd05c-20260701151111
4
+
5
+ ### Patch Changes
6
+
7
+ - update all packages
8
+ - Updated dependencies
9
+ - @xyd-js/opencli@0.0.0-build-b7bd05c-20260701151111
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) LiveSession Sp.z.o.o
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # xyd-opencli-remark
2
+
3
+ The package includes a remark plugin for generating OpenCLI documentation from variables in markdown files.
4
+
5
+ ## Usage
6
+
7
+ ```typescript
8
+ import { remarkOpencliDocs } from '@xyd-js/opencli-remark';
9
+ import remarkFrontmatter from 'remark-frontmatter';
10
+ import remarkStringify from 'remark-stringify';
11
+ import { remark } from 'remark';
12
+
13
+ // Configure multiple CLI specs
14
+ remark()
15
+ .use(remarkFrontmatter)
16
+ .use(remarkOpencliDocs, {
17
+ xyd: { source: './xyd-cli.json' },
18
+ npm: { source: './npm-cli.json' },
19
+ // Add more CLIs as needed
20
+ })
21
+ .use(remarkStringify)
22
+ .process(markdown);
23
+ ```
24
+
25
+ ## Configuration
26
+
27
+ The plugin accepts an object where each key represents a CLI identifier, and the value contains the spec configuration:
28
+
29
+ ```typescript
30
+ {
31
+ [cliKey: string]: {
32
+ source: string; // Path to OpenCLI spec JSON file (relative to markdown file) or URL
33
+ }
34
+ }
35
+ ```
36
+
37
+ **Example:**
38
+ ```typescript
39
+ remarkOpencliDocs({
40
+ xyd: { source: './xyd-cli.json' },
41
+ npm: { source: 'https://example.com/npm-cli.json' }
42
+ })
43
+ ```
44
+
45
+ ## Frontmatter Configuration
46
+
47
+ In your markdown frontmatter, specify which CLI to use and the command path:
48
+
49
+ ```yaml
50
+ ---
51
+ xyd.opencli.xyd: "dev"
52
+ ---
53
+ ```
54
+
55
+ The CLI key (e.g., `xyd`) must match a key in your plugin configuration. The command path is **relative to the CLI root** (no CLI name prefix needed).
56
+
57
+ ### Command Path Examples
58
+
59
+ - **Root command**: Use an empty string `""`
60
+ ```yaml
61
+ xyd.opencli.xyd: ""
62
+ ```
63
+
64
+ - **Top-level command**: Just the command name
65
+ ```yaml
66
+ xyd.opencli.xyd: "dev"
67
+ ```
68
+
69
+ - **Nested command**: Space-separated path
70
+ ```yaml
71
+ xyd.opencli.xyd: "components install"
72
+ ```
73
+
74
+ - **Using aliases**: You can use command aliases
75
+ ```yaml
76
+ xyd.opencli.xyd: "d" # if "d" is an alias for "dev"
77
+ ```
78
+
79
+ ### Indent Style Configuration
80
+
81
+ You can configure the output format for arguments and options:
82
+
83
+ ```yaml
84
+ ---
85
+ xyd.opencli.xyd:
86
+ command: "dev"
87
+ indent: list # or "code" (default)
88
+ ---
89
+ ```
90
+
91
+ - **`code`** (default): Tab-indented CLI-style format, suitable for code blocks
92
+ - **`list`**: Markdown list format with backticks, suitable for regular markdown
93
+
94
+ ## Example Markdown
95
+
96
+ ### Code Block Format (default)
97
+
98
+ **Input:**
99
+ ```markdown
100
+ ---
101
+ xyd.opencli.xyd: "dev"
102
+ ---
103
+
104
+ ```sh
105
+ Usage: {opencli.current.usage}
106
+
107
+ {opencli.current.description}
108
+
109
+ Arguments:
110
+ {opencli.current.arguments}
111
+
112
+ Options:
113
+ {opencli.current.options}
114
+ ```
115
+
116
+ **Output:**
117
+ ```markdown
118
+ ---
119
+ xyd.opencli.xyd: "dev"
120
+ ---
121
+
122
+ ```sh
123
+ Usage: xyd dev [flags]
124
+
125
+ Run your docs locally in development mode
126
+
127
+ Options:
128
+ -p, --port <number> Port to run the dev server on
129
+ -l, --logLevel <string> Set logging level (e.g. info, debug)
130
+ --verbose Enable verbose output
131
+ --debug Enable debug output
132
+ ```
133
+
134
+ ### List Format
135
+
136
+ **Input:**
137
+ ```markdown
138
+ ---
139
+ xyd.opencli.xyd:
140
+ command: "dev"
141
+ indent: list
142
+ ---
143
+
144
+ ## Usage
145
+ `{opencli.current.usage}`
146
+
147
+ {opencli.current.description}
148
+
149
+ ## Arguments
150
+ {opencli.current.arguments}
151
+
152
+ ## Options
153
+ {opencli.current.options}
154
+ ```
155
+
156
+ **Output:**
157
+ ```markdown
158
+ ---
159
+ xyd.opencli.xyd:
160
+ command: "dev"
161
+ indent: list
162
+ ---
163
+
164
+ ## Usage
165
+
166
+ `xyd dev [flags]`
167
+
168
+ Run your docs locally in development mode
169
+
170
+ ## Arguments
171
+
172
+ ## Options
173
+
174
+ - `-p`, `--port <number>` Port to run the dev server on
175
+ - `-l`, `--logLevel <string>` Set logging level (e.g. info, debug)
176
+ - `--verbose` Enable verbose output
177
+ - `--debug` Enable debug output
178
+ ```
179
+
180
+ ## Variables
181
+
182
+ The following Variables are supported:
183
+
184
+ | Variable | Description | Format Support |
185
+ |------------|-------------|----------------|
186
+ | `{opencli.current.usage}` | Generates usage line (e.g., `xyd dev [flags]`) | All formats |
187
+ | `{opencli.current.description}` | Command description | All formats |
188
+ | `{opencli.current.commands}` | List of available subcommands | All formats |
189
+ | `{opencli.current.arguments}` | Command arguments documentation | Code blocks, text (code style), or list nodes (list style) |
190
+ | `{opencli.current.options}` | Command options/flags documentation | Code blocks, text (code style), or list nodes (list style) |
191
+
192
+ **Note:**
193
+ - `{opencli.current.arguments}` and `{opencli.current.options}` work in:
194
+ - Code blocks (always code format)
195
+ - Text nodes (code format when `indent: 'code'`)
196
+ - List nodes (list format when `indent: 'list'` - automatically converted to markdown lists)
197
+
198
+ ## Multiple CLIs
199
+
200
+ You can configure and use multiple CLI specs in the same project:
201
+
202
+ ```typescript
203
+ remarkOpencliDocs({
204
+ xyd: { source: './xyd-cli.json' },
205
+ npm: { source: './npm-cli.json' },
206
+ git: { source: './git-cli.json' }
207
+ })
208
+ ```
209
+
210
+ Then in different markdown files, reference the appropriate CLI:
211
+
212
+ ```yaml
213
+ # File 1: xyd-dev.md
214
+ ---
215
+ xyd.opencli.xyd: "dev"
216
+ ---
217
+
218
+ # File 2: npm-install.md
219
+ ---
220
+ xyd.opencli.npm: "install"
221
+ ---
222
+ ```
package/dist/index.cjs ADDED
@@ -0,0 +1,290 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ remarkOpencliDocs: () => remarkOpencliDocs
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+ __reExport(index_exports, require("@xyd-js/opencli"), module.exports);
28
+
29
+ // src/remark-opencli.ts
30
+ var import_unist_util_visit = require("unist-util-visit");
31
+ var import_vfile_matter = require("vfile-matter");
32
+ var import_js_yaml = require("js-yaml");
33
+ var import_opencli = require("@xyd-js/opencli");
34
+ function remarkOpencliDocs(options) {
35
+ return async function transformer(tree, file) {
36
+ var _a;
37
+ if (!file) {
38
+ return;
39
+ }
40
+ if (!file.data) {
41
+ file.data = {};
42
+ }
43
+ let hasOpencliKey = false;
44
+ let yamlContent = null;
45
+ (0, import_unist_util_visit.visit)(tree, "yaml", (node) => {
46
+ if (node.value && !yamlContent) {
47
+ const content = String(node.value);
48
+ yamlContent = content;
49
+ if (content.includes("xyd.opencli.")) {
50
+ hasOpencliKey = true;
51
+ }
52
+ }
53
+ });
54
+ if (!yamlContent && file.value) {
55
+ const fileValue = typeof file.value === "string" ? file.value : new TextDecoder().decode(file.value);
56
+ const frontmatterMatch = fileValue.match(/^---\n([\s\S]*?)\n---/);
57
+ if (frontmatterMatch && frontmatterMatch[1].includes("xyd.opencli.")) {
58
+ hasOpencliKey = true;
59
+ yamlContent = frontmatterMatch[1];
60
+ }
61
+ }
62
+ if (!hasOpencliKey) {
63
+ return;
64
+ }
65
+ let frontmatter = file.data.matter;
66
+ if (!frontmatter && yamlContent) {
67
+ try {
68
+ frontmatter = (0, import_js_yaml.load)(yamlContent);
69
+ file.data.matter = frontmatter;
70
+ } catch (error) {
71
+ if (file.value) {
72
+ (0, import_vfile_matter.matter)(file);
73
+ frontmatter = file.data.matter;
74
+ }
75
+ }
76
+ }
77
+ if (!frontmatter && file.value) {
78
+ (0, import_vfile_matter.matter)(file);
79
+ frontmatter = file.data.matter;
80
+ }
81
+ let cliKey = null;
82
+ let opencliConfig = null;
83
+ for (const key in frontmatter) {
84
+ if (key.startsWith("xyd.opencli.")) {
85
+ cliKey = key.substring("xyd.opencli.".length);
86
+ opencliConfig = frontmatter[key];
87
+ break;
88
+ }
89
+ }
90
+ if (!cliKey || opencliConfig === void 0 || opencliConfig === null) {
91
+ return;
92
+ }
93
+ const cliConfig = options[cliKey];
94
+ if (!cliConfig || !cliConfig.source) {
95
+ console.warn(`No configuration found for CLI key "${cliKey}"`);
96
+ return;
97
+ }
98
+ let commandPath;
99
+ let indentStyle = "code";
100
+ if (typeof opencliConfig === "string") {
101
+ commandPath = opencliConfig;
102
+ } else if (typeof opencliConfig === "object" && opencliConfig !== null) {
103
+ commandPath = opencliConfig.command || "";
104
+ indentStyle = opencliConfig.indent === "list" ? "list" : "code";
105
+ } else {
106
+ return;
107
+ }
108
+ const normalizedPath = (commandPath == null ? void 0 : commandPath.trim()) || "";
109
+ const spec = await (0, import_opencli.loadOpencliSpec)(cliConfig.source, { cwd: file.dirname });
110
+ if (!spec) {
111
+ console.warn(`Failed to load OpenCLI spec from ${cliConfig.source}`);
112
+ return;
113
+ }
114
+ const command = (0, import_opencli.findCommand)(spec, normalizedPath);
115
+ if (!command) {
116
+ console.warn(`Command "${normalizedPath || "(root)"}" not found in OpenCLI spec`);
117
+ return;
118
+ }
119
+ const cliTitle = ((_a = spec.info) == null ? void 0 : _a.title) || "";
120
+ const displayPath = normalizedPath ? `${cliTitle} ${normalizedPath}`.trim() : cliTitle || command.name;
121
+ const usage = (0, import_opencli.generateUsage)(spec, command, displayPath);
122
+ const description = (0, import_opencli.generateDescription)(command);
123
+ const subcommands = (0, import_opencli.generateCommands)(command);
124
+ const argsText = (0, import_opencli.generateArguments)(command, "code");
125
+ const optsText = (0, import_opencli.generateOptions)(command, "code");
126
+ const replaceSimplePlaceholders = (value) => {
127
+ return value.replace(/\{opencli\.current\.usage\}/g, usage).replace(/\{opencli\.current\.description\}/g, description).replace(/\{opencli\.current\.commands\}/g, subcommands);
128
+ };
129
+ (0, import_unist_util_visit.visit)(tree, "text", (node) => {
130
+ if (typeof node.value === "string") {
131
+ node.value = replaceSimplePlaceholders(node.value);
132
+ if (indentStyle === "code") {
133
+ node.value = node.value.replace(/\{opencli\.current\.arguments\}/g, argsText).replace(/\{opencli\.current\.options\}/g, optsText);
134
+ }
135
+ }
136
+ });
137
+ (0, import_unist_util_visit.visit)(tree, "inlineCode", (node) => {
138
+ if (typeof node.value === "string") {
139
+ node.value = replaceSimplePlaceholders(node.value);
140
+ if (indentStyle === "code") {
141
+ node.value = node.value.replace(/\{opencli\.current\.arguments\}/g, argsText).replace(/\{opencli\.current\.options\}/g, optsText);
142
+ }
143
+ }
144
+ });
145
+ (0, import_unist_util_visit.visit)(tree, "code", (node) => {
146
+ if (typeof node.value === "string") {
147
+ node.value = replaceSimplePlaceholders(node.value).replace(/\{opencli\.current\.arguments\}/g, argsText).replace(/\{opencli\.current\.options\}/g, optsText);
148
+ }
149
+ });
150
+ const mdxExprValue = (expr) => {
151
+ switch (expr) {
152
+ case "opencli.current.usage":
153
+ return usage;
154
+ case "opencli.current.description":
155
+ return description;
156
+ case "opencli.current.commands":
157
+ return subcommands;
158
+ case "opencli.current.arguments":
159
+ return argsText;
160
+ case "opencli.current.options":
161
+ return optsText;
162
+ default:
163
+ return null;
164
+ }
165
+ };
166
+ (0, import_unist_util_visit.visit)(tree, ["mdxFlowExpression", "mdxTextExpression"], (node, index, parent) => {
167
+ if (!parent || index === void 0 || typeof node.value !== "string") return;
168
+ const expr = node.value.trim();
169
+ if (!expr.startsWith("opencli.current.")) return;
170
+ if (indentStyle === "list" && (expr === "opencli.current.arguments" || expr === "opencli.current.options")) {
171
+ const listNode = expr === "opencli.current.arguments" ? createArgumentsListNode(command) : createOptionsListNode(command);
172
+ parent.children[index] = listNode || { type: "text", value: "" };
173
+ return;
174
+ }
175
+ const value = mdxExprValue(expr);
176
+ if (value === null) return;
177
+ if (node.type === "mdxFlowExpression") {
178
+ parent.children[index] = expr === "opencli.current.description" ? { type: "paragraph", children: [{ type: "text", value }] } : { type: "code", value };
179
+ } else {
180
+ parent.children[index] = { type: "text", value };
181
+ }
182
+ });
183
+ if (indentStyle === "list") {
184
+ (0, import_unist_util_visit.visit)(tree, "paragraph", (node, index, parent) => {
185
+ var _a2;
186
+ if (!parent || index === void 0) return;
187
+ const textChild = (_a2 = node.children) == null ? void 0 : _a2.find(
188
+ (c) => {
189
+ var _a3;
190
+ return c.type === "text" && ((_a3 = c.value) == null ? void 0 : _a3.includes("{opencli.current.arguments}"));
191
+ }
192
+ );
193
+ if (textChild) {
194
+ const listNode = createArgumentsListNode(command);
195
+ if (listNode) {
196
+ parent.children[index] = listNode;
197
+ } else {
198
+ textChild.value = textChild.value.replace("{opencli.current.arguments}", "");
199
+ }
200
+ }
201
+ });
202
+ (0, import_unist_util_visit.visit)(tree, "paragraph", (node, index, parent) => {
203
+ var _a2;
204
+ if (!parent || index === void 0) return;
205
+ const textChild = (_a2 = node.children) == null ? void 0 : _a2.find(
206
+ (c) => {
207
+ var _a3;
208
+ return c.type === "text" && ((_a3 = c.value) == null ? void 0 : _a3.includes("{opencli.current.options}"));
209
+ }
210
+ );
211
+ if (textChild) {
212
+ const listNode = createOptionsListNode(command);
213
+ if (listNode) {
214
+ parent.children[index] = listNode;
215
+ } else {
216
+ textChild.value = textChild.value.replace("{opencli.current.options}", "");
217
+ }
218
+ }
219
+ });
220
+ }
221
+ };
222
+ }
223
+ function createArgumentsListNode(command) {
224
+ if (!command.arguments || command.arguments.length === 0) {
225
+ return null;
226
+ }
227
+ const visibleArgs = command.arguments.filter((arg) => !arg.hidden);
228
+ if (visibleArgs.length === 0) {
229
+ return null;
230
+ }
231
+ return {
232
+ type: "list",
233
+ ordered: false,
234
+ spread: false,
235
+ children: visibleArgs.map((arg) => ({
236
+ type: "listItem",
237
+ spread: false,
238
+ children: [{
239
+ type: "paragraph",
240
+ children: [
241
+ { type: "inlineCode", value: arg.name.toLowerCase() },
242
+ { type: "text", value: arg.description ? ` ${arg.description}` : "" }
243
+ ]
244
+ }]
245
+ }))
246
+ };
247
+ }
248
+ function createOptionsListNode(command) {
249
+ if (!command.options || command.options.length === 0) {
250
+ return null;
251
+ }
252
+ const visibleOptions = command.options.filter((opt) => !opt.hidden);
253
+ if (visibleOptions.length === 0) {
254
+ return null;
255
+ }
256
+ return {
257
+ type: "list",
258
+ ordered: false,
259
+ spread: false,
260
+ children: visibleOptions.map((option) => {
261
+ var _a;
262
+ const aliases = ((_a = option.aliases) == null ? void 0 : _a.filter((a) => a.length === 1)) || [];
263
+ const short = aliases.length > 0 ? `-${aliases[0]}` : "";
264
+ const long = `--${option.name}`;
265
+ const children = [];
266
+ if (short) {
267
+ children.push({ type: "inlineCode", value: short });
268
+ children.push({ type: "text", value: ", " });
269
+ }
270
+ children.push({ type: "inlineCode", value: long });
271
+ if (option.description) {
272
+ children.push({ type: "text", value: ` ${option.description}` });
273
+ }
274
+ return {
275
+ type: "listItem",
276
+ spread: false,
277
+ children: [{
278
+ type: "paragraph",
279
+ children
280
+ }]
281
+ };
282
+ })
283
+ };
284
+ }
285
+ // Annotate the CommonJS export names for ESM import in node:
286
+ 0 && (module.exports = {
287
+ remarkOpencliDocs,
288
+ ...require("@xyd-js/opencli")
289
+ });
290
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../index.ts","../src/remark-opencli.ts"],"sourcesContent":["// The OpenCLI model + helpers now live in @xyd-js/opencli; re-export them so\n// existing consumers of @xyd-js/opencli-remark keep working.\nexport * from '@xyd-js/opencli';\nexport { remarkOpencliDocs, type OpencliDocsOptions } from './src/remark-opencli';\n","import { visit } from 'unist-util-visit';\nimport { VFile } from 'vfile';\nimport { Root } from 'mdast';\nimport { matter } from 'vfile-matter';\nimport { load } from 'js-yaml';\n\nimport {\n loadOpencliSpec,\n findCommand,\n generateUsage,\n generateDescription,\n generateArguments,\n generateOptions,\n generateCommands,\n type Command,\n} from '@xyd-js/opencli';\n\nexport interface OpencliDocsOptions {\n [cliKey: string]: {\n source: string; // File path or URL\n };\n}\n\n/**\n * Remark plugin for generating OpenCLI documentation from placeholders\n *\n * @example\n * ```md\n * ---\n * xyd.opencli.spice: \"install\"\n * ---\n *\n * ### Usage\n * {opencli.current.usage}\n *\n * ### Flags\n * {opencli.current.flags}\n * ```\n *\n * @example\n * ```ts\n * remarkOpencliDocs({\n * spice: { source: './spice-spec.json' },\n * npm: { source: './npm-spec.json' }\n * })\n * ```\n */\nexport function remarkOpencliDocs(options: OpencliDocsOptions) {\n return async function transformer(tree: Root, file?: VFile) {\n // Return early if no file is provided\n if (!file) {\n return;\n }\n\n // Ensure file.data exists\n if (!file.data) {\n file.data = {};\n }\n\n // Quick check: look for xyd.opencli.* pattern in YAML nodes before parsing\n let hasOpencliKey = false;\n let yamlContent: string | null = null;\n\n visit(tree, 'yaml', (node: any) => {\n if (node.value && !yamlContent) {\n const content = String(node.value);\n yamlContent = content;\n // Quick string check for xyd.opencli. pattern\n if (content.includes('xyd.opencli.')) {\n hasOpencliKey = true;\n }\n }\n });\n\n // If no YAML node found, check file.value directly\n if (!yamlContent && file.value) {\n const fileValue = typeof file.value === 'string' ? file.value : new TextDecoder().decode(file.value);\n const frontmatterMatch = fileValue.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (frontmatterMatch && frontmatterMatch[1].includes('xyd.opencli.')) {\n hasOpencliKey = true;\n yamlContent = frontmatterMatch[1];\n }\n }\n\n // If no xyd.opencli.* key found anywhere, return early without any processing\n if (!hasOpencliKey) {\n return;\n }\n\n // Now parse frontmatter since we know there's a potential match\n let frontmatter = file.data.matter as Record<string, any> | undefined;\n\n // If not parsed, parse from YAML content we found\n if (!frontmatter && yamlContent) {\n try {\n frontmatter = load(yamlContent) as Record<string, any>;\n file.data.matter = frontmatter;\n } catch (error) {\n // Failed to parse YAML, try parsing from file.value\n if (file.value) {\n matter(file as any);\n frontmatter = file.data.matter as Record<string, any> | undefined;\n }\n }\n }\n\n // Fallback: try to parse from file.value if YAML nodes weren't found\n if (!frontmatter && file.value) {\n matter(file as any);\n frontmatter = file.data.matter as Record<string, any> | undefined;\n }\n\n // Find xyd.opencli.{cliKey} pattern in frontmatter\n let cliKey: string | null = null;\n let opencliConfig: any = null;\n\n for (const key in frontmatter) {\n if (key.startsWith('xyd.opencli.')) {\n cliKey = key.substring('xyd.opencli.'.length);\n opencliConfig = frontmatter[key];\n break;\n }\n }\n\n // If no xyd.opencli.{cliKey} found, return early\n if (!cliKey || opencliConfig === undefined || opencliConfig === null) {\n return;\n }\n\n // Get the CLI config for this key\n const cliConfig = options[cliKey];\n if (!cliConfig || !cliConfig.source) {\n console.warn(`No configuration found for CLI key \"${cliKey}\"`);\n return;\n }\n\n // Parse xyd.opencli.{cliKey} - can be string or object\n let commandPath: string;\n let indentStyle: 'code' | 'list' = 'code'; // default\n\n if (typeof opencliConfig === 'string') {\n commandPath = opencliConfig;\n } else if (typeof opencliConfig === 'object' && opencliConfig !== null) {\n commandPath = opencliConfig.command || '';\n indentStyle = opencliConfig.indent === 'list' ? 'list' : 'code';\n } else {\n return;\n }\n\n const normalizedPath = commandPath?.trim() || '';\n\n // Load OpenCLI spec (resolve relative file paths from the markdown file's dir)\n const spec = await loadOpencliSpec(cliConfig.source, { cwd: file.dirname });\n if (!spec) {\n console.warn(`Failed to load OpenCLI spec from ${cliConfig.source}`);\n return;\n }\n\n // Find the command in the spec\n const command = findCommand(spec, normalizedPath);\n if (!command) {\n console.warn(`Command \"${normalizedPath || '(root)'}\" not found in OpenCLI spec`);\n return;\n }\n\n // Build display path: CLI title + command path (or just CLI title for root)\n const cliTitle = spec.info?.title || '';\n const displayPath = normalizedPath\n ? `${cliTitle} ${normalizedPath}`.trim()\n : cliTitle || command.name;\n\n // Generate documentation content\n const usage = generateUsage(spec, command, displayPath);\n const description = generateDescription(command);\n // const flags = generateFlags(command);\n const subcommands = generateCommands(command);\n\n // For code format, generate string content\n const argsText = generateArguments(command, 'code');\n const optsText = generateOptions(command, 'code');\n\n // Helper function to replace simple placeholders (usage, description)\n const replaceSimplePlaceholders = (value: string) => {\n return value\n .replace(/\\{opencli\\.current\\.usage\\}/g, usage)\n .replace(/\\{opencli\\.current\\.description\\}/g, description)\n // .replace(/\\{opencli\\.current\\.flags\\}/g, flags)\n .replace(/\\{opencli\\.current\\.commands\\}/g, subcommands);\n };\n\n // Replace placeholders in text nodes\n visit(tree, 'text', (node: any) => {\n if (typeof node.value === 'string') {\n node.value = replaceSimplePlaceholders(node.value);\n // For code style, also replace arguments/options as text\n if (indentStyle === 'code') {\n node.value = node.value\n .replace(/\\{opencli\\.current\\.arguments\\}/g, argsText)\n .replace(/\\{opencli\\.current\\.options\\}/g, optsText);\n }\n }\n });\n\n // Replace placeholders in inline code (backticks)\n visit(tree, 'inlineCode', (node: any) => {\n if (typeof node.value === 'string') {\n node.value = replaceSimplePlaceholders(node.value);\n if (indentStyle === 'code') {\n node.value = node.value\n .replace(/\\{opencli\\.current\\.arguments\\}/g, argsText)\n .replace(/\\{opencli\\.current\\.options\\}/g, optsText);\n }\n }\n });\n\n // Replace placeholders in code blocks\n visit(tree, 'code', (node: any) => {\n if (typeof node.value === 'string') {\n node.value = replaceSimplePlaceholders(node.value)\n .replace(/\\{opencli\\.current\\.arguments\\}/g, argsText)\n .replace(/\\{opencli\\.current\\.options\\}/g, optsText);\n }\n });\n\n // In an MDX pipeline `{opencli.current.*}` is parsed as a JS expression node\n // (mdxFlowExpression / mdxTextExpression), not literal text — so the visitors\n // above never see it (and it would throw at render since `opencli` is undefined).\n // Resolve those expression nodes here.\n const mdxExprValue = (expr: string): string | null => {\n switch (expr) {\n case 'opencli.current.usage': return usage;\n case 'opencli.current.description': return description;\n case 'opencli.current.commands': return subcommands;\n case 'opencli.current.arguments': return argsText;\n case 'opencli.current.options': return optsText;\n default: return null;\n }\n };\n visit(tree, ['mdxFlowExpression', 'mdxTextExpression'], (node: any, index: number | undefined, parent: any) => {\n if (!parent || index === undefined || typeof node.value !== 'string') return;\n const expr = node.value.trim();\n if (!expr.startsWith('opencli.current.')) return;\n\n if (indentStyle === 'list' && (expr === 'opencli.current.arguments' || expr === 'opencli.current.options')) {\n const listNode = expr === 'opencli.current.arguments'\n ? createArgumentsListNode(command)\n : createOptionsListNode(command);\n parent.children[index] = listNode || { type: 'text', value: '' };\n return;\n }\n\n const value = mdxExprValue(expr);\n if (value === null) return;\n\n if (node.type === 'mdxFlowExpression') {\n parent.children[index] = expr === 'opencli.current.description'\n ? { type: 'paragraph', children: [{ type: 'text', value }] }\n : { type: 'code', value };\n } else {\n parent.children[index] = { type: 'text', value };\n }\n });\n\n // For list format, replace argument/option placeholders with mdast list nodes\n if (indentStyle === 'list') {\n // Replace {opencli.current.arguments} with list node\n visit(tree, 'paragraph', (node: any, index: number | undefined, parent: any) => {\n if (!parent || index === undefined) return;\n\n const textChild = node.children?.find((c: any) =>\n c.type === 'text' && c.value?.includes('{opencli.current.arguments}')\n );\n\n if (textChild) {\n const listNode = createArgumentsListNode(command);\n if (listNode) {\n parent.children[index] = listNode;\n } else {\n // No arguments, just remove the placeholder\n textChild.value = textChild.value.replace('{opencli.current.arguments}', '');\n }\n }\n });\n\n // Replace {opencli.current.options} with list node\n visit(tree, 'paragraph', (node: any, index: number | undefined, parent: any) => {\n if (!parent || index === undefined) return;\n\n const textChild = node.children?.find((c: any) =>\n c.type === 'text' && c.value?.includes('{opencli.current.options}')\n );\n\n if (textChild) {\n const listNode = createOptionsListNode(command);\n if (listNode) {\n parent.children[index] = listNode;\n } else {\n // No options, just remove the placeholder\n textChild.value = textChild.value.replace('{opencli.current.options}', '');\n }\n }\n });\n }\n };\n}\n\n/**\n * Create mdast list node for arguments (for list indent style)\n */\nfunction createArgumentsListNode(command: Command): any | null {\n if (!command.arguments || command.arguments.length === 0) {\n return null;\n }\n\n const visibleArgs = command.arguments.filter(arg => !arg.hidden);\n if (visibleArgs.length === 0) {\n return null;\n }\n\n return {\n type: 'list',\n ordered: false,\n spread: false,\n children: visibleArgs.map(arg => ({\n type: 'listItem',\n spread: false,\n children: [{\n type: 'paragraph',\n children: [\n { type: 'inlineCode', value: arg.name.toLowerCase() },\n { type: 'text', value: arg.description ? ` ${arg.description}` : '' }\n ]\n }]\n }))\n };\n}\n\n/**\n * Create mdast list node for options (for list indent style)\n */\nfunction createOptionsListNode(command: Command): any | null {\n if (!command.options || command.options.length === 0) {\n return null;\n }\n\n const visibleOptions = command.options.filter(opt => !opt.hidden);\n if (visibleOptions.length === 0) {\n return null;\n }\n\n return {\n type: 'list',\n ordered: false,\n spread: false,\n children: visibleOptions.map(option => {\n const aliases = option.aliases?.filter(a => a.length === 1) || [];\n const short = aliases.length > 0 ? `-${aliases[0]}` : '';\n const long = `--${option.name}`;\n\n const children: any[] = [];\n\n // Add short alias if exists\n if (short) {\n children.push({ type: 'inlineCode', value: short });\n children.push({ type: 'text', value: ', ' });\n }\n\n // Add long option\n children.push({ type: 'inlineCode', value: long });\n\n // Add description\n if (option.description) {\n children.push({ type: 'text', value: ` ${option.description}` });\n }\n\n return {\n type: 'listItem',\n spread: false,\n children: [{\n type: 'paragraph',\n children\n }]\n };\n })\n };\n}\n"],"mappings":"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","names":["_a"]}
@@ -0,0 +1,36 @@
1
+ export * from '@xyd-js/opencli';
2
+ import { VFile } from 'vfile';
3
+ import { Root } from 'mdast';
4
+
5
+ interface OpencliDocsOptions {
6
+ [cliKey: string]: {
7
+ source: string;
8
+ };
9
+ }
10
+ /**
11
+ * Remark plugin for generating OpenCLI documentation from placeholders
12
+ *
13
+ * @example
14
+ * ```md
15
+ * ---
16
+ * xyd.opencli.spice: "install"
17
+ * ---
18
+ *
19
+ * ### Usage
20
+ * {opencli.current.usage}
21
+ *
22
+ * ### Flags
23
+ * {opencli.current.flags}
24
+ * ```
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * remarkOpencliDocs({
29
+ * spice: { source: './spice-spec.json' },
30
+ * npm: { source: './npm-spec.json' }
31
+ * })
32
+ * ```
33
+ */
34
+ declare function remarkOpencliDocs(options: OpencliDocsOptions): (tree: Root, file?: VFile) => Promise<void>;
35
+
36
+ export { type OpencliDocsOptions, remarkOpencliDocs };
@@ -0,0 +1,36 @@
1
+ export * from '@xyd-js/opencli';
2
+ import { VFile } from 'vfile';
3
+ import { Root } from 'mdast';
4
+
5
+ interface OpencliDocsOptions {
6
+ [cliKey: string]: {
7
+ source: string;
8
+ };
9
+ }
10
+ /**
11
+ * Remark plugin for generating OpenCLI documentation from placeholders
12
+ *
13
+ * @example
14
+ * ```md
15
+ * ---
16
+ * xyd.opencli.spice: "install"
17
+ * ---
18
+ *
19
+ * ### Usage
20
+ * {opencli.current.usage}
21
+ *
22
+ * ### Flags
23
+ * {opencli.current.flags}
24
+ * ```
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * remarkOpencliDocs({
29
+ * spice: { source: './spice-spec.json' },
30
+ * npm: { source: './npm-spec.json' }
31
+ * })
32
+ * ```
33
+ */
34
+ declare function remarkOpencliDocs(options: OpencliDocsOptions): (tree: Root, file?: VFile) => Promise<void>;
35
+
36
+ export { type OpencliDocsOptions, remarkOpencliDocs };