@stritti/vitepress-plugin-openspec 0.6.1 → 0.7.1

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/README.md CHANGED
@@ -64,12 +64,14 @@ export default defineConfig(
64
64
 
65
65
  | Option | Type | Default | Description |
66
66
  | --- | --- | --- | --- |
67
- | `specDir` | `string` | `'./openspec'` | Path to your project's `openspec/` directory |
67
+ | `specDir` | `string` | `'./openspec'` | Path to your project's `openspec/` directory. Can be an absolute path or relative to the working directory — use `path.resolve(__dirname, '../../openspec')` when `config.ts` lives in `docs/.vitepress/`. |
68
68
  | `outDir` | `string` | `'openspec'` | Output directory relative to VitePress `srcDir` |
69
69
  | `srcDir` | `string` | `process.cwd()` | VitePress source directory (the `docs/` folder) |
70
70
  | `nav` | `boolean` | `true` | Whether to prepend an openspec entry to `themeConfig.nav` |
71
71
  | `sidebar` | `boolean` | `true` | Whether to inject the openspec sidebar section into `themeConfig.sidebar` |
72
72
 
73
+ > **Missing directory** — if `specDir` does not exist the plugin emits a `console.warn` and skips page generation, nav, and sidebar. No error is thrown and your VitePress build continues normally. This is intentional for projects that haven't set up an `openspec/` folder yet.
74
+
73
75
  ---
74
76
 
75
77
  ## Advanced / manual setup
package/dist/index.cjs CHANGED
@@ -3,23 +3,22 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var fs = require('fs');
6
- var path2 = require('path');
6
+ var path = require('path');
7
7
  var pc = require('picocolors');
8
- var yaml = require('js-yaml');
8
+ var jsYaml = require('js-yaml');
9
9
 
10
10
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
11
 
12
12
  var fs__default = /*#__PURE__*/_interopDefault(fs);
13
- var path2__default = /*#__PURE__*/_interopDefault(path2);
13
+ var path__default = /*#__PURE__*/_interopDefault(path);
14
14
  var pc__default = /*#__PURE__*/_interopDefault(pc);
15
- var yaml__default = /*#__PURE__*/_interopDefault(yaml);
16
15
 
17
16
  // src/plugin.ts
18
17
  function readOpenSpecYaml(dir) {
19
- const yamlPath = path2__default.default.join(dir, ".openspec.yaml");
18
+ const yamlPath = path__default.default.join(dir, ".openspec.yaml");
20
19
  if (!fs__default.default.existsSync(yamlPath)) return {};
21
20
  try {
22
- return yaml__default.default.load(fs__default.default.readFileSync(yamlPath, "utf-8")) ?? {};
21
+ return jsYaml.load(fs__default.default.readFileSync(yamlPath, "utf-8")) ?? {};
23
22
  } catch {
24
23
  return {};
25
24
  }
@@ -70,21 +69,21 @@ function formatDate(val) {
70
69
  function readArtifacts(dir) {
71
70
  const artifacts = [];
72
71
  for (const name of ["proposal", "design", "tasks"]) {
73
- if (fs__default.default.existsSync(path2__default.default.join(dir, `${name}.md`))) artifacts.push(name);
72
+ if (fs__default.default.existsSync(path__default.default.join(dir, `${name}.md`))) artifacts.push(name);
74
73
  }
75
74
  return artifacts;
76
75
  }
77
76
  function readOpenSpecFolder(dir) {
78
- const resolved = path2__default.default.resolve(dir);
77
+ const resolved = path__default.default.resolve(dir);
79
78
  if (!fs__default.default.existsSync(resolved)) {
80
79
  throw new Error(`[vitepress-plugin-openspec] openspec directory not found: ${resolved}`);
81
80
  }
82
81
  const specs = [];
83
- const specsDir = path2__default.default.join(resolved, "specs");
82
+ const specsDir = path__default.default.join(resolved, "specs");
84
83
  if (fs__default.default.existsSync(specsDir)) {
85
84
  for (const entry of fs__default.default.readdirSync(specsDir, { withFileTypes: true })) {
86
85
  if (!entry.isDirectory()) continue;
87
- const specPath = path2__default.default.join(specsDir, entry.name, "spec.md");
86
+ const specPath = path__default.default.join(specsDir, entry.name, "spec.md");
88
87
  if (!fs__default.default.existsSync(specPath)) continue;
89
88
  const content = fs__default.default.readFileSync(specPath, "utf-8");
90
89
  specs.push({
@@ -96,12 +95,12 @@ function readOpenSpecFolder(dir) {
96
95
  }
97
96
  }
98
97
  const changes = [];
99
- const changesDir = path2__default.default.join(resolved, "changes");
98
+ const changesDir = path__default.default.join(resolved, "changes");
100
99
  if (fs__default.default.existsSync(changesDir)) {
101
100
  for (const entry of fs__default.default.readdirSync(changesDir, { withFileTypes: true })) {
102
101
  if (!entry.isDirectory() || entry.name === "archive") continue;
103
- const changeDir = path2__default.default.join(changesDir, entry.name);
104
- if (!fs__default.default.existsSync(path2__default.default.join(changeDir, ".openspec.yaml"))) continue;
102
+ const changeDir = path__default.default.join(changesDir, entry.name);
103
+ if (!fs__default.default.existsSync(path__default.default.join(changeDir, ".openspec.yaml"))) continue;
105
104
  const meta = readOpenSpecYaml(changeDir);
106
105
  changes.push({
107
106
  name: entry.name,
@@ -113,11 +112,11 @@ function readOpenSpecFolder(dir) {
113
112
  }
114
113
  }
115
114
  const archivedChanges = [];
116
- const archiveDir = path2__default.default.join(changesDir, "archive");
115
+ const archiveDir = path__default.default.join(changesDir, "archive");
117
116
  if (fs__default.default.existsSync(archiveDir)) {
118
117
  for (const entry of fs__default.default.readdirSync(archiveDir, { withFileTypes: true })) {
119
118
  if (!entry.isDirectory()) continue;
120
- const changeDir = path2__default.default.join(archiveDir, entry.name);
119
+ const changeDir = path__default.default.join(archiveDir, entry.name);
121
120
  const match = entry.name.match(/^(\d{4}-\d{2}-\d{2})-(.+)$/);
122
121
  const archivedDate = match?.[1];
123
122
  const name = match?.[2] ?? entry.name;
@@ -258,6 +257,35 @@ function generateChangesIndexPage(folder, outDir) {
258
257
  lines.push("");
259
258
  return lines.join("\n");
260
259
  }
260
+ function rewriteRelativeLinks(content, srcFilePath, openspecRootDir, outDir) {
261
+ const srcDir = path__default.default.dirname(srcFilePath);
262
+ return content.replace(
263
+ /(\[[^\]]*\])\(([^)]+)\)/g,
264
+ (_match, linkText, urlPart) => {
265
+ const titleMatch = urlPart.match(/^(.+?)(\s+["'][^"']*["'])?\s*$/);
266
+ if (!titleMatch) return _match;
267
+ const rawUrl = titleMatch[1].trim();
268
+ const title = titleMatch[2] ?? "";
269
+ if (!rawUrl || rawUrl.startsWith("http://") || rawUrl.startsWith("https://") || rawUrl.startsWith("//") || rawUrl.startsWith("/") || rawUrl.startsWith("#") || rawUrl.startsWith("mailto:") || rawUrl.startsWith("tel:")) {
270
+ return _match;
271
+ }
272
+ const hashIdx = rawUrl.indexOf("#");
273
+ const urlWithoutFragment = hashIdx >= 0 ? rawUrl.slice(0, hashIdx) : rawUrl;
274
+ const fragment = hashIdx >= 0 ? rawUrl.slice(hashIdx) : "";
275
+ if (!urlWithoutFragment) {
276
+ return _match;
277
+ }
278
+ const resolvedPath = path__default.default.resolve(srcDir, urlWithoutFragment);
279
+ const relToOpenspec = path__default.default.relative(openspecRootDir, resolvedPath);
280
+ if (relToOpenspec.startsWith("..") || path__default.default.isAbsolute(relToOpenspec)) {
281
+ return _match;
282
+ }
283
+ const vitePath = relToOpenspec.replace(/\.md$/, "").replace(/\\/g, "/");
284
+ const absoluteLink = `/${outDir}/${vitePath}${fragment}`;
285
+ return `${linkText}(${absoluteLink}${title})`;
286
+ }
287
+ );
288
+ }
261
289
  function changeItems(change, outDir, isArchived = false) {
262
290
  const prefix = isArchived ? `/${outDir}/changes/archive/${change.archiveFolderName}` : `/${outDir}/changes/${change.name}`;
263
291
  return change.artifacts.map((a) => ({
@@ -267,6 +295,10 @@ function changeItems(change, outDir, isArchived = false) {
267
295
  }
268
296
  function generateOpenSpecSidebar(specDir, options = {}) {
269
297
  const outDir = options.outDir ?? "openspec";
298
+ if (!fs__default.default.existsSync(path__default.default.resolve(specDir))) {
299
+ console.warn(`[vitepress-plugin-openspec] openspec directory not found: ${path__default.default.relative(process.cwd(), path__default.default.resolve(specDir))} \u2014 skipping sidebar generation`);
300
+ return [];
301
+ }
270
302
  const folder = readOpenSpecFolder(specDir);
271
303
  const groups = [];
272
304
  groups.push({
@@ -304,10 +336,9 @@ function generateOpenSpecSidebar(specDir, options = {}) {
304
336
  }
305
337
  function openspecNav(specDir, options = {}) {
306
338
  const outDir = options.outDir ?? "openspec";
307
- if (!fs__default.default.existsSync(path2__default.default.resolve(specDir))) {
308
- throw new Error(
309
- `[vitepress-plugin-openspec] openspec directory not found: ${path2__default.default.resolve(specDir)}`
310
- );
339
+ if (!fs__default.default.existsSync(path__default.default.resolve(specDir))) {
340
+ console.warn(`[vitepress-plugin-openspec] openspec directory not found: ${path__default.default.relative(process.cwd(), path__default.default.resolve(specDir))} \u2014 skipping nav generation`);
341
+ return null;
311
342
  }
312
343
  return {
313
344
  text: options.text ?? "Docs",
@@ -318,36 +349,38 @@ function openspecNav(specDir, options = {}) {
318
349
  // src/plugin.ts
319
350
  var PLUGIN_NAME = "vitepress-plugin-openspec";
320
351
  function writeFile(filePath, content) {
321
- fs__default.default.mkdirSync(path2__default.default.dirname(filePath), { recursive: true });
352
+ fs__default.default.mkdirSync(path__default.default.dirname(filePath), { recursive: true });
322
353
  fs__default.default.writeFileSync(filePath, content, "utf-8");
323
354
  }
324
- function copyFile(src, dest) {
325
- fs__default.default.mkdirSync(path2__default.default.dirname(dest), { recursive: true });
326
- fs__default.default.copyFileSync(src, dest);
327
- }
328
355
  function generateOpenSpecPages(userOptions = {}) {
329
356
  const specDir = userOptions.specDir ?? "./openspec";
330
357
  const outDir = userOptions.outDir ?? "openspec";
331
358
  const srcDir = userOptions.srcDir ?? process.cwd();
332
- const absoluteOutDir = path2__default.default.resolve(srcDir, outDir);
359
+ const absoluteOutDir = path__default.default.resolve(srcDir, outDir);
360
+ if (!fs__default.default.existsSync(path__default.default.resolve(specDir))) {
361
+ console.warn(
362
+ `${pc__default.default.bold(pc__default.default.yellow(`[${PLUGIN_NAME}]`))} openspec directory not found: ${path__default.default.relative(srcDir, path__default.default.resolve(specDir))} \u2014 skipping page generation`
363
+ );
364
+ return;
365
+ }
333
366
  try {
334
367
  const folder = readOpenSpecFolder(specDir);
335
368
  for (const spec of folder.specs) {
336
- const dest = path2__default.default.join(absoluteOutDir, "specs", spec.name, "index.md");
369
+ const dest = path__default.default.join(absoluteOutDir, "specs", spec.name, "index.md");
337
370
  writeFile(dest, generateSpecPage(spec));
338
371
  }
339
372
  writeFile(
340
- path2__default.default.join(absoluteOutDir, "specs", "index.md"),
373
+ path__default.default.join(absoluteOutDir, "specs", "index.md"),
341
374
  generateSpecsIndexPage(folder.specs, outDir)
342
375
  );
343
376
  for (const change of folder.changes) {
344
- writeChangePage(change, absoluteOutDir, outDir, false);
377
+ writeChangePage(change, absoluteOutDir, outDir, false, folder.dir);
345
378
  }
346
379
  for (const change of folder.archivedChanges) {
347
- writeChangePage(change, absoluteOutDir, outDir, true);
380
+ writeChangePage(change, absoluteOutDir, outDir, true, folder.dir);
348
381
  }
349
382
  writeFile(
350
- path2__default.default.join(absoluteOutDir, "changes", "index.md"),
383
+ path__default.default.join(absoluteOutDir, "changes", "index.md"),
351
384
  generateChangesIndexPage(folder, outDir)
352
385
  );
353
386
  const rootIndex = [
@@ -361,9 +394,9 @@ function generateOpenSpecPages(userOptions = {}) {
361
394
  `- [Changes](/${outDir}/changes/) \u2014 active and archived change proposals`,
362
395
  ""
363
396
  ].join("\n");
364
- writeFile(path2__default.default.join(absoluteOutDir, "index.md"), rootIndex);
397
+ writeFile(path__default.default.join(absoluteOutDir, "index.md"), rootIndex);
365
398
  writeFile(
366
- path2__default.default.join(absoluteOutDir, ".gitignore"),
399
+ path__default.default.join(absoluteOutDir, ".gitignore"),
367
400
  "# Generated by vitepress-plugin-openspec \u2014 do not commit generated files.\n*\n!.gitignore\n"
368
401
  );
369
402
  console.log(
@@ -386,14 +419,15 @@ function openspec(userOptions = {}) {
386
419
  }
387
420
  };
388
421
  }
389
- function writeChangePage(change, absoluteOutDir, outDir, isArchived) {
390
- const subPath = isArchived ? path2__default.default.join("changes", "archive", `${change.archivedDate}-${change.name}`) : path2__default.default.join("changes", change.name);
391
- const changeOutDir = path2__default.default.join(absoluteOutDir, subPath);
392
- writeFile(path2__default.default.join(changeOutDir, "index.md"), generateChangeIndexPage(change, outDir));
422
+ function writeChangePage(change, absoluteOutDir, outDir, isArchived, openspecRootDir) {
423
+ const subPath = isArchived ? path__default.default.join("changes", "archive", `${change.archivedDate}-${change.name}`) : path__default.default.join("changes", change.name);
424
+ const changeOutDir = path__default.default.join(absoluteOutDir, subPath);
425
+ writeFile(path__default.default.join(changeOutDir, "index.md"), generateChangeIndexPage(change, outDir));
393
426
  for (const artifact of change.artifacts) {
394
- const srcFile = path2__default.default.join(change.dir, `${artifact}.md`);
395
- const destFile = path2__default.default.join(changeOutDir, `${artifact}.md`);
396
- copyFile(srcFile, destFile);
427
+ const srcFile = path__default.default.join(change.dir, `${artifact}.md`);
428
+ const destFile = path__default.default.join(changeOutDir, `${artifact}.md`);
429
+ const content = fs__default.default.readFileSync(srcFile, "utf-8");
430
+ writeFile(destFile, rewriteRelativeLinks(content, srcFile, openspecRootDir, outDir));
397
431
  }
398
432
  }
399
433
  function withOpenSpec(config, options = {}) {
@@ -409,7 +443,7 @@ function withOpenSpec(config, options = {}) {
409
443
  if (options.nav !== false) {
410
444
  const navEntry = openspecNav(specDir, { outDir });
411
445
  const existingNav = themeConfig.nav ?? [];
412
- themeConfig.nav = [navEntry, ...existingNav];
446
+ themeConfig.nav = navEntry ? [navEntry, ...existingNav] : existingNav;
413
447
  }
414
448
  if (options.sidebar !== false && !Array.isArray(themeConfig.sidebar)) {
415
449
  const sidebarKey = `/${outDir}/`;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/plugin.ts"],"names":["path","fs","yaml","pc"],"mappings":"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","file":"index.cjs","sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport yaml from 'js-yaml'\nimport type {\n CapabilitySpec,\n Change,\n ChangeArtifact,\n NavItem,\n OpenSpecFolder,\n SidebarItem,\n} from './types.js'\n\n// ---------------------------------------------------------------------------\n// Folder reader\n// ---------------------------------------------------------------------------\n\nfunction readOpenSpecYaml(dir: string): Record<string, unknown> {\n const yamlPath = path.join(dir, '.openspec.yaml')\n if (!fs.existsSync(yamlPath)) return {}\n try {\n return (yaml.load(fs.readFileSync(yamlPath, 'utf-8')) ?? {}) as Record<string, unknown>\n } catch {\n return {}\n }\n}\n\nconst ACRONYM_DICT: Record<string, string> = {\n api: 'API',\n rest: 'REST',\n graphql: 'GraphQL',\n grpc: 'gRPC',\n openapi: 'OpenAPI',\n oauth: 'OAuth',\n oauth2: 'OAuth2',\n http: 'HTTP',\n https: 'HTTPS',\n url: 'URL',\n uri: 'URI',\n sdk: 'SDK',\n ui: 'UI',\n ux: 'UX',\n id: 'ID',\n db: 'DB',\n sql: 'SQL',\n css: 'CSS',\n html: 'HTML',\n json: 'JSON',\n yaml: 'YAML',\n xml: 'XML',\n jwt: 'JWT',\n ci: 'CI',\n cd: 'CD',\n}\n\nfunction humanizeLabel(name: string): string {\n if (!name) return ''\n return name\n .split('-')\n .map((word) => {\n if (/^v\\d+$/.test(word)) return word\n return ACRONYM_DICT[word] ?? (word.charAt(0).toUpperCase() + word.slice(1))\n })\n .join(' ')\n}\n\nfunction parseFrontmatterTitle(content: string): string | undefined {\n const match = content.match(/^---\\s*\\n(?:.*\\n)*?title:\\s*['\"]?([^\\n'\"]+)['\"]?\\s*\\n/)\n return match?.[1]?.trim() || undefined\n}\n\nfunction formatDate(val: unknown): string | undefined {\n if (!val) return undefined\n if (val instanceof Date) return val.toISOString().slice(0, 10)\n return String(val)\n}\n\nfunction readArtifacts(dir: string): ChangeArtifact[] {\n const artifacts: ChangeArtifact[] = []\n for (const name of ['proposal', 'design', 'tasks'] as ChangeArtifact[]) {\n if (fs.existsSync(path.join(dir, `${name}.md`))) artifacts.push(name)\n }\n return artifacts\n}\n\n/**\n * Scans an openspec/ directory and returns a structured representation of all\n * canonical specs, active changes, and archived changes.\n *\n * Throws if the directory does not exist.\n */\nexport function readOpenSpecFolder(dir: string): OpenSpecFolder {\n const resolved = path.resolve(dir)\n if (!fs.existsSync(resolved)) {\n throw new Error(`[vitepress-plugin-openspec] openspec directory not found: ${resolved}`)\n }\n\n // --- Canonical specs ---\n const specs: CapabilitySpec[] = []\n const specsDir = path.join(resolved, 'specs')\n if (fs.existsSync(specsDir)) {\n for (const entry of fs.readdirSync(specsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const specPath = path.join(specsDir, entry.name, 'spec.md')\n if (!fs.existsSync(specPath)) continue\n const content = fs.readFileSync(specPath, 'utf-8')\n specs.push({\n name: entry.name,\n title: parseFrontmatterTitle(content),\n specPath,\n content,\n })\n }\n }\n\n // --- Active changes ---\n const changes: Change[] = []\n const changesDir = path.join(resolved, 'changes')\n if (fs.existsSync(changesDir)) {\n for (const entry of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!entry.isDirectory() || entry.name === 'archive') continue\n const changeDir = path.join(changesDir, entry.name)\n if (!fs.existsSync(path.join(changeDir, '.openspec.yaml'))) continue\n const meta = readOpenSpecYaml(changeDir)\n changes.push({\n name: entry.name,\n title: meta.title ? String(meta.title) : undefined,\n dir: changeDir,\n artifacts: readArtifacts(changeDir),\n createdDate: formatDate(meta.created),\n })\n }\n }\n\n // --- Archived changes ---\n const archivedChanges: Change[] = []\n const archiveDir = path.join(changesDir, 'archive')\n if (fs.existsSync(archiveDir)) {\n for (const entry of fs.readdirSync(archiveDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const changeDir = path.join(archiveDir, entry.name)\n // Parse YYYY-MM-DD-<name> format\n const match = entry.name.match(/^(\\d{4}-\\d{2}-\\d{2})-(.+)$/)\n const archivedDate = match?.[1]\n const name = match?.[2] ?? entry.name\n const meta = readOpenSpecYaml(changeDir)\n archivedChanges.push({\n name,\n title: meta.title ? String(meta.title) : undefined,\n dir: changeDir,\n artifacts: readArtifacts(changeDir),\n createdDate: formatDate(meta.created),\n archivedDate,\n archiveFolderName: entry.name,\n })\n }\n }\n\n return { dir: resolved, specs, changes, archivedChanges }\n}\n\n// ---------------------------------------------------------------------------\n// Spec content transformations\n// ---------------------------------------------------------------------------\n\nfunction extractSpecDescription(content: string): string | undefined {\n const reqMatch = content.match(/^### Requirement:[^\\n]*\\n+([\\s\\S]*?)(?=\\n#{1,4} |\\n*$)/m)\n if (!reqMatch) return undefined\n const para = reqMatch[1].trim()\n if (!para) return undefined\n const sentenceMatch = para.match(/^([^.?!]+[.?!])/)\n if (!sentenceMatch) return undefined\n let sentence = sentenceMatch[1].trim()\n if (sentence.length > 160) {\n const cut = sentence.lastIndexOf(' ', 160)\n sentence = (cut > 0 ? sentence.slice(0, cut) : sentence.slice(0, 160)) + '…'\n }\n return sentence.replace(/\"/g, '\\\\\"')\n}\n\nfunction stripDeltaMarkers(content: string): string {\n const stripped = content\n .split('\\n')\n .filter((line) => !/^## (ADDED|MODIFIED|REMOVED) Requirements\\s*$/.test(line))\n .join('\\n')\n // Collapse consecutive blank lines to a single blank line\n return stripped.replace(/\\n{3,}/g, '\\n\\n')\n}\n\nfunction transformScenarios(content: string): string {\n const lines = content.split('\\n')\n const result: string[] = []\n let inScenario = false\n\n for (const line of lines) {\n const scenarioMatch = line.match(/^#### Scenario: (.+)$/)\n const isHeading = /^#{1,6} /.test(line)\n\n if (scenarioMatch) {\n if (inScenario) result.push(':::')\n result.push(`:::details ${scenarioMatch[1]}`)\n inScenario = true\n } else if (isHeading && inScenario) {\n result.push(':::')\n result.push('')\n result.push(line)\n inScenario = false\n } else {\n result.push(line)\n }\n }\n\n if (inScenario) result.push(':::')\n return result.join('\\n')\n}\n\n// ---------------------------------------------------------------------------\n// Page generators\n// ---------------------------------------------------------------------------\n\n/**\n * Generates VitePress Markdown for a canonical capability spec page.\n */\nexport function generateSpecPage(spec: CapabilitySpec): string {\n const description = extractSpecDescription(spec.content)\n const transformed = transformScenarios(stripDeltaMarkers(spec.content))\n const lines: string[] = []\n if (description) {\n lines.push('---')\n lines.push(`description: \"${description}\"`)\n lines.push('---')\n lines.push('')\n }\n lines.push(`# ${spec.title ?? humanizeLabel(spec.name)}`)\n lines.push('')\n lines.push(transformed.trimEnd())\n lines.push('')\n return lines.join('\\n')\n}\n\n/**\n * Generates the index page listing all canonical specs.\n */\nexport function generateSpecsIndexPage(specs: CapabilitySpec[], outDir: string): string {\n const lines: string[] = []\n lines.push('# Specifications')\n lines.push('')\n lines.push('Canonical capability specifications for this project.')\n lines.push('')\n if (specs.length === 0) {\n lines.push('*No specifications defined yet.*')\n } else {\n for (const spec of specs) {\n lines.push(`- [${spec.title ?? humanizeLabel(spec.name)}](/${outDir}/specs/${spec.name}/)`)\n }\n }\n lines.push('')\n return lines.join('\\n')\n}\n\n/**\n * Generates the index page for a single change.\n */\nexport function generateChangeIndexPage(change: Change, outDir: string): string {\n const lines: string[] = []\n lines.push(`# ${change.title ?? humanizeLabel(change.name)}`)\n lines.push('')\n if (change.createdDate) {\n lines.push(`**Created:** ${change.createdDate}`)\n lines.push('')\n }\n if (change.archivedDate) {\n lines.push(`**Archived:** ${change.archivedDate}`)\n lines.push('')\n }\n lines.push('## Artifacts')\n lines.push('')\n const prefix = change.archiveFolderName\n ? `/${outDir}/changes/archive/${change.archiveFolderName}`\n : `/${outDir}/changes/${change.name}`\n for (const artifact of change.artifacts) {\n const label = artifact.charAt(0).toUpperCase() + artifact.slice(1)\n lines.push(`- [${label}](${prefix}/${artifact})`)\n }\n lines.push('')\n return lines.join('\\n')\n}\n\n/**\n * Generates the changes overview page listing active and archived changes.\n */\nexport function generateChangesIndexPage(folder: OpenSpecFolder, outDir: string): string {\n const lines: string[] = []\n lines.push('# Changes')\n lines.push('')\n\n if (folder.changes.length === 0) {\n lines.push('*No active changes.*')\n } else {\n lines.push('## Active')\n lines.push('')\n for (const change of folder.changes) {\n const date = change.createdDate ? ` *(${change.createdDate})*` : ''\n lines.push(`- [${change.title ?? humanizeLabel(change.name)}](/${outDir}/changes/${change.name}/)${date}`)\n }\n }\n\n if (folder.archivedChanges.length > 0) {\n lines.push('')\n lines.push('## Archiv')\n lines.push('')\n for (const change of folder.archivedChanges) {\n const date = change.archivedDate ? ` *(archiviert: ${change.archivedDate})*` : ''\n lines.push(\n `- [${change.title ?? humanizeLabel(change.name)}](/${outDir}/changes/archive/${change.archiveFolderName}/)${date}`,\n )\n }\n }\n\n lines.push('')\n return lines.join('\\n')\n}\n\n// ---------------------------------------------------------------------------\n// Navigation helpers\n// ---------------------------------------------------------------------------\n\nfunction changeItems(change: Change, outDir: string, isArchived = false): SidebarItem[] {\n const prefix = isArchived\n ? `/${outDir}/changes/archive/${change.archiveFolderName}`\n : `/${outDir}/changes/${change.name}`\n return change.artifacts.map((a) => ({\n text: a.charAt(0).toUpperCase() + a.slice(1),\n link: `${prefix}/${a}`,\n }))\n}\n\n/**\n * Returns a VitePress sidebar configuration for the OpenSpec documentation.\n * Includes groups for Specifications, active Changes, and archived Changes.\n */\nexport function generateOpenSpecSidebar(\n specDir: string,\n options: { outDir?: string } = {},\n): SidebarItem[] {\n const outDir = options.outDir ?? 'openspec'\n const folder = readOpenSpecFolder(specDir)\n const groups: SidebarItem[] = []\n\n // Specifications group\n groups.push({\n text: 'Specifications',\n collapsed: false,\n items: [\n { text: 'Overview', link: `/${outDir}/specs/` },\n ...folder.specs.map((s) => ({ text: s.title ?? humanizeLabel(s.name), link: `/${outDir}/specs/${s.name}/` })),\n ],\n })\n\n // Changes group\n groups.push({\n text: 'Changes',\n collapsed: false,\n items: [\n { text: 'Overview', link: `/${outDir}/changes/` },\n ...folder.changes.map((c) => ({\n text: c.title ?? humanizeLabel(c.name),\n collapsed: true,\n items: changeItems(c, outDir),\n })),\n ],\n })\n\n // Archive group (only if non-empty)\n if (folder.archivedChanges.length > 0) {\n groups.push({\n text: 'Archiv',\n collapsed: true,\n items: folder.archivedChanges.map((c) => ({\n text: c.title ?? humanizeLabel(c.name),\n collapsed: true,\n items: changeItems(c, outDir, true),\n })),\n })\n }\n\n return groups\n}\n\n/**\n * Returns a VitePress nav entry for the OpenSpec documentation section.\n */\nexport function openspecNav(\n specDir: string,\n options: { outDir?: string; text?: string } = {},\n): NavItem {\n const outDir = options.outDir ?? 'openspec'\n if (!fs.existsSync(path.resolve(specDir))) {\n throw new Error(\n `[vitepress-plugin-openspec] openspec directory not found: ${path.resolve(specDir)}`,\n )\n }\n return {\n text: options.text ?? 'Docs',\n link: `/${outDir}/`,\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport pc from 'picocolors'\nimport type { Plugin } from 'vite'\nimport type { Change, OpenSpecPluginOptions, WithOpenSpecOptions } from './types.js'\nimport {\n generateChangeIndexPage,\n generateChangesIndexPage,\n generateOpenSpecSidebar,\n generateSpecPage,\n generateSpecsIndexPage,\n openspecNav,\n readOpenSpecFolder,\n} from './utils.js'\n\nconst PLUGIN_NAME = 'vitepress-plugin-openspec'\n\nfunction writeFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, content, 'utf-8')\n}\n\nfunction copyFile(src: string, dest: string): void {\n fs.mkdirSync(path.dirname(dest), { recursive: true })\n fs.copyFileSync(src, dest)\n}\n\n/**\n * Synchronously generates all VitePress Markdown pages from the openspec/\n * directory and writes them to disk.\n *\n * Call this at the top of your `docs/.vitepress/config.ts` **before**\n * `defineConfig()` so the files exist when VitePress scans the source\n * directory for routes.\n *\n * @example\n * ```typescript\n * // docs/.vitepress/config.ts\n * import { defineConfig } from 'vitepress'\n * import path from 'node:path'\n * import { fileURLToPath } from 'node:url'\n * import openspec, { generateOpenSpecPages } from 'vitepress-plugin-openspec'\n *\n * const __dirname = path.dirname(fileURLToPath(import.meta.url))\n * const specDir = path.resolve(__dirname, '../../openspec')\n *\n * // Generate pages before VitePress scans srcDir for routes\n * generateOpenSpecPages({ specDir, outDir: 'openspec', srcDir: path.resolve(__dirname, '..') })\n *\n * export default defineConfig({ ... })\n * ```\n */\nexport function generateOpenSpecPages(userOptions: OpenSpecPluginOptions = {}): void {\n const specDir = userOptions.specDir ?? './openspec'\n const outDir = userOptions.outDir ?? 'openspec'\n const srcDir = userOptions.srcDir ?? process.cwd()\n const absoluteOutDir = path.resolve(srcDir, outDir)\n\n try {\n const folder = readOpenSpecFolder(specDir)\n\n // --- Spec pages ---\n for (const spec of folder.specs) {\n const dest = path.join(absoluteOutDir, 'specs', spec.name, 'index.md')\n writeFile(dest, generateSpecPage(spec))\n }\n writeFile(\n path.join(absoluteOutDir, 'specs', 'index.md'),\n generateSpecsIndexPage(folder.specs, outDir),\n )\n\n // --- Active change pages ---\n for (const change of folder.changes) {\n writeChangePage(change, absoluteOutDir, outDir, false)\n }\n\n // --- Archived change pages ---\n for (const change of folder.archivedChanges) {\n writeChangePage(change, absoluteOutDir, outDir, true)\n }\n\n // --- Changes index ---\n writeFile(\n path.join(absoluteOutDir, 'changes', 'index.md'),\n generateChangesIndexPage(folder, outDir),\n )\n\n // --- Root index ---\n const rootIndex = [\n '# Project Documentation',\n '',\n \"This section is generated from the project's [OpenSpec](https://openspec.dev/) folder.\",\n 'OpenSpec is a lightweight, file-based workflow for spec-driven development —',\n 'it structures your project\\'s capability specifications and change proposals as plain Markdown files.',\n '',\n `- [Specifications](/${outDir}/specs/) — canonical capability specs`,\n `- [Changes](/${outDir}/changes/) — active and archived change proposals`,\n '',\n ].join('\\n')\n writeFile(path.join(absoluteOutDir, 'index.md'), rootIndex)\n\n // Write a self-managed .gitignore so consumers don't need to add the\n // output directory to their project-level .gitignore manually.\n writeFile(\n path.join(absoluteOutDir, '.gitignore'),\n '# Generated by vitepress-plugin-openspec — do not commit generated files.\\n*\\n!.gitignore\\n',\n )\n\n console.log(\n `${pc.bold(pc.cyan(`[${PLUGIN_NAME}]`))} Generated docs from ${pc.cyan(specDir)}: ` +\n `${pc.green(String(folder.specs.length))} spec(s), ` +\n `${pc.green(String(folder.changes.length))} change(s), ` +\n `${pc.green(String(folder.archivedChanges.length))} archived`,\n )\n } catch (err) {\n console.error(\n `${pc.bold(pc.red(`[${PLUGIN_NAME}]`))} Failed to process openspec directory \"${specDir}\": ${String(err)}`,\n )\n }\n}\n\n/**\n * VitePress plugin that reads an openspec/ directory and generates structured\n * Markdown documentation pages inside the VitePress source directory.\n *\n * For the pages to be available on the first build (including CI), also call\n * `generateOpenSpecPages()` at the top of your `config.ts` before `defineConfig`.\n *\n * @example\n * ```typescript\n * // .vitepress/config.ts\n * import { defineConfig } from 'vitepress'\n * import openspec, { generateOpenSpecPages } from 'vitepress-plugin-openspec'\n *\n * generateOpenSpecPages({ specDir, outDir: 'openspec', srcDir: path.resolve(__dirname, '..') })\n *\n * export default defineConfig({\n * vite: { plugins: [openspec({ specDir: './openspec', outDir: 'project-docs' })] },\n * })\n * ```\n */\nexport function openspec(userOptions: OpenSpecPluginOptions = {}): Plugin {\n return {\n name: PLUGIN_NAME,\n enforce: 'pre',\n\n configResolved(resolvedConfig) {\n const vpConfig = (resolvedConfig as unknown as { vitepress?: { srcDir?: string } }).vitepress\n const srcDir =\n userOptions.srcDir ?? vpConfig?.srcDir ?? resolvedConfig.root ?? process.cwd()\n generateOpenSpecPages({ ...userOptions, srcDir })\n },\n }\n}\n\nfunction writeChangePage(\n change: Change,\n absoluteOutDir: string,\n outDir: string,\n isArchived: boolean,\n): void {\n const subPath = isArchived\n ? path.join('changes', 'archive', `${change.archivedDate}-${change.name}`)\n : path.join('changes', change.name)\n const changeOutDir = path.join(absoluteOutDir, subPath)\n\n // Write index page\n writeFile(path.join(changeOutDir, 'index.md'), generateChangeIndexPage(change, outDir))\n\n // Copy artifact files\n for (const artifact of change.artifacts) {\n const srcFile = path.join(change.dir, `${artifact}.md`)\n const destFile = path.join(changeOutDir, `${artifact}.md`)\n copyFile(srcFile, destFile)\n }\n}\n\n/**\n * One-call VitePress config helper that wires up the full openspec integration.\n *\n * Calls `generateOpenSpecPages()` synchronously (required before VitePress scans\n * for routes), then merges the openspec Vite plugin, nav entry, and sidebar section\n * into the provided config object.\n *\n * Other Vite plugins go into `vite.plugins` as usual — `withOpenSpec` appends to\n * the array without replacing it:\n *\n * @example\n * ```typescript\n * // docs/.vitepress/config.ts\n * import { defineConfig } from 'vitepress'\n * import { withOpenSpec } from 'vitepress-plugin-openspec'\n *\n * export default defineConfig(\n * withOpenSpec({\n * vite: { plugins: [myOtherPlugin()] }, // other plugins are preserved\n * themeConfig: { nav: [], sidebar: {} },\n * })\n * )\n * ```\n *\n * @param config - Your VitePress `UserConfig` object (same as what `defineConfig` accepts).\n * @param options - OpenSpec options. All fields are optional; defaults match `generateOpenSpecPages`.\n */\nexport function withOpenSpec<T extends Record<string, unknown>>(\n config: T,\n options: WithOpenSpecOptions = {},\n): T {\n const specDir = options.specDir ?? './openspec'\n const outDir = options.outDir ?? 'openspec'\n const srcDir = options.srcDir ?? process.cwd()\n\n generateOpenSpecPages({ specDir, outDir, srcDir })\n\n const result = { ...config } as Record<string, unknown>\n\n // --- Vite plugin ---\n const vite = (result.vite ?? {}) as Record<string, unknown>\n const existingPlugins = (vite.plugins as unknown[]) ?? []\n result.vite = { ...vite, plugins: [...existingPlugins, openspec({ specDir, outDir, srcDir })] }\n\n const themeConfig = (result.themeConfig ?? {}) as Record<string, unknown>\n\n // --- Nav ---\n if (options.nav !== false) {\n const navEntry = openspecNav(specDir, { outDir })\n const existingNav = (themeConfig.nav as unknown[]) ?? []\n themeConfig.nav = [navEntry, ...existingNav]\n }\n\n // --- Sidebar ---\n if (options.sidebar !== false && !Array.isArray(themeConfig.sidebar)) {\n const sidebarKey = `/${outDir}/`\n const existingSidebar = (themeConfig.sidebar ?? {}) as Record<string, unknown>\n if (!existingSidebar[sidebarKey]) {\n themeConfig.sidebar = {\n ...existingSidebar,\n [sidebarKey]: generateOpenSpecSidebar(specDir, { outDir }),\n }\n }\n }\n\n result.themeConfig = themeConfig\n\n return result as T\n}\n\nexport default openspec\n"]}
1
+ {"version":3,"sources":["../src/utils.ts","../src/plugin.ts"],"names":["path","fs","yamlLoad","pc"],"mappings":";;;;;;;;;;;;;;;;AAgBA,SAAS,iBAAiB,GAAA,EAAsC;AAC9D,EAAA,MAAM,QAAA,GAAWA,qBAAA,CAAK,IAAA,CAAK,GAAA,EAAK,gBAAgB,CAAA;AAChD,EAAA,IAAI,CAACC,mBAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,SAAU,EAAC;AACtC,EAAA,IAAI;AACF,IAAA,OAAQC,YAASD,mBAAA,CAAG,YAAA,CAAa,UAAU,OAAO,CAAC,KAAK,EAAC;AAAA,EAC3D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAEA,IAAM,YAAA,GAAuC;AAAA,EAC3C,GAAA,EAAK,KAAA;AAAA,EACL,IAAA,EAAM,MAAA;AAAA,EACN,OAAA,EAAS,SAAA;AAAA,EACT,IAAA,EAAM,MAAA;AAAA,EACN,OAAA,EAAS,SAAA;AAAA,EACT,KAAA,EAAO,OAAA;AAAA,EACP,MAAA,EAAQ,QAAA;AAAA,EACR,IAAA,EAAM,MAAA;AAAA,EACN,KAAA,EAAO,OAAA;AAAA,EACP,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,EAAA,EAAI,IAAA;AAAA,EACJ,EAAA,EAAI,IAAA;AAAA,EACJ,EAAA,EAAI,IAAA;AAAA,EACJ,EAAA,EAAI,IAAA;AAAA,EACJ,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,IAAA,EAAM,MAAA;AAAA,EACN,IAAA,EAAM,MAAA;AAAA,EACN,IAAA,EAAM,MAAA;AAAA,EACN,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,EAAA,EAAI,IAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAEA,SAAS,cAAc,IAAA,EAAsB;AAC3C,EAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAClB,EAAA,OAAO,KACJ,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,CAAI,CAAC,IAAA,KAAS;AACb,IAAA,IAAI,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA,EAAG,OAAO,IAAA;AAChC,IAAA,OAAO,YAAA,CAAa,IAAI,CAAA,IAAM,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA;AAAA,EAC3E,CAAC,CAAA,CACA,IAAA,CAAK,GAAG,CAAA;AACb;AAEA,SAAS,sBAAsB,OAAA,EAAqC;AAClE,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,uDAAuD,CAAA;AACnF,EAAA,OAAO,KAAA,GAAQ,CAAC,CAAA,EAAG,IAAA,EAAK,IAAK,MAAA;AAC/B;AAEA,SAAS,WAAW,GAAA,EAAkC;AACpD,EAAA,IAAI,CAAC,KAAK,OAAO,MAAA;AACjB,EAAA,IAAI,GAAA,YAAe,MAAM,OAAO,GAAA,CAAI,aAAY,CAAE,KAAA,CAAM,GAAG,EAAE,CAAA;AAC7D,EAAA,OAAO,OAAO,GAAG,CAAA;AACnB;AAEA,SAAS,cAAc,GAAA,EAA+B;AACpD,EAAA,MAAM,YAA8B,EAAC;AACrC,EAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,UAAA,EAAY,QAAA,EAAU,OAAO,CAAA,EAAuB;AACtE,IAAA,IAAIA,mBAAA,CAAG,UAAA,CAAWD,qBAAA,CAAK,IAAA,CAAK,GAAA,EAAK,CAAA,EAAG,IAAI,CAAA,GAAA,CAAK,CAAC,CAAA,EAAG,SAAA,CAAU,IAAA,CAAK,IAAI,CAAA;AAAA,EACtE;AACA,EAAA,OAAO,SAAA;AACT;AAQO,SAAS,mBAAmB,GAAA,EAA6B;AAC9D,EAAA,MAAM,QAAA,GAAWA,qBAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AACjC,EAAA,IAAI,CAACC,mBAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC5B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0DAAA,EAA6D,QAAQ,CAAA,CAAE,CAAA;AAAA,EACzF;AAGA,EAAA,MAAM,QAA0B,EAAC;AACjC,EAAA,MAAM,QAAA,GAAWD,qBAAA,CAAK,IAAA,CAAK,QAAA,EAAU,OAAO,CAAA;AAC5C,EAAA,IAAIC,mBAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC3B,IAAA,KAAA,MAAW,KAAA,IAASA,oBAAG,WAAA,CAAY,QAAA,EAAU,EAAE,aAAA,EAAe,IAAA,EAAM,CAAA,EAAG;AACrE,MAAA,IAAI,CAAC,KAAA,CAAM,WAAA,EAAY,EAAG;AAC1B,MAAA,MAAM,WAAWD,qBAAA,CAAK,IAAA,CAAK,QAAA,EAAU,KAAA,CAAM,MAAM,SAAS,CAAA;AAC1D,MAAA,IAAI,CAACC,mBAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC9B,MAAA,MAAM,OAAA,GAAUA,mBAAA,CAAG,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AACjD,MAAA,KAAA,CAAM,IAAA,CAAK;AAAA,QACT,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,KAAA,EAAO,sBAAsB,OAAO,CAAA;AAAA,QACpC,QAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF;AAGA,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,MAAM,UAAA,GAAaD,qBAAA,CAAK,IAAA,CAAK,QAAA,EAAU,SAAS,CAAA;AAChD,EAAA,IAAIC,mBAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC7B,IAAA,KAAA,MAAW,KAAA,IAASA,oBAAG,WAAA,CAAY,UAAA,EAAY,EAAE,aAAA,EAAe,IAAA,EAAM,CAAA,EAAG;AACvE,MAAA,IAAI,CAAC,KAAA,CAAM,WAAA,EAAY,IAAK,KAAA,CAAM,SAAS,SAAA,EAAW;AACtD,MAAA,MAAM,SAAA,GAAYD,qBAAA,CAAK,IAAA,CAAK,UAAA,EAAY,MAAM,IAAI,CAAA;AAClD,MAAA,IAAI,CAACC,oBAAG,UAAA,CAAWD,qBAAA,CAAK,KAAK,SAAA,EAAW,gBAAgB,CAAC,CAAA,EAAG;AAC5D,MAAA,MAAM,IAAA,GAAO,iBAAiB,SAAS,CAAA;AACvC,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,OAAO,IAAA,CAAK,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,GAAI,MAAA;AAAA,QACzC,GAAA,EAAK,SAAA;AAAA,QACL,SAAA,EAAW,cAAc,SAAS,CAAA;AAAA,QAClC,WAAA,EAAa,UAAA,CAAW,IAAA,CAAK,OAAO;AAAA,OACrC,CAAA;AAAA,IACH;AAAA,EACF;AAGA,EAAA,MAAM,kBAA4B,EAAC;AACnC,EAAA,MAAM,UAAA,GAAaA,qBAAA,CAAK,IAAA,CAAK,UAAA,EAAY,SAAS,CAAA;AAClD,EAAA,IAAIC,mBAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC7B,IAAA,KAAA,MAAW,KAAA,IAASA,oBAAG,WAAA,CAAY,UAAA,EAAY,EAAE,aAAA,EAAe,IAAA,EAAM,CAAA,EAAG;AACvE,MAAA,IAAI,CAAC,KAAA,CAAM,WAAA,EAAY,EAAG;AAC1B,MAAA,MAAM,SAAA,GAAYD,qBAAA,CAAK,IAAA,CAAK,UAAA,EAAY,MAAM,IAAI,CAAA;AAElD,MAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,4BAA4B,CAAA;AAC3D,MAAA,MAAM,YAAA,GAAe,QAAQ,CAAC,CAAA;AAC9B,MAAA,MAAM,IAAA,GAAO,KAAA,GAAQ,CAAC,CAAA,IAAK,KAAA,CAAM,IAAA;AACjC,MAAA,MAAM,IAAA,GAAO,iBAAiB,SAAS,CAAA;AACvC,MAAA,eAAA,CAAgB,IAAA,CAAK;AAAA,QACnB,IAAA;AAAA,QACA,OAAO,IAAA,CAAK,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,GAAI,MAAA;AAAA,QACzC,GAAA,EAAK,SAAA;AAAA,QACL,SAAA,EAAW,cAAc,SAAS,CAAA;AAAA,QAClC,WAAA,EAAa,UAAA,CAAW,IAAA,CAAK,OAAO,CAAA;AAAA,QACpC,YAAA;AAAA,QACA,mBAAmB,KAAA,CAAM;AAAA,OAC1B,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,SAAS,eAAA,EAAgB;AAC1D;AAMA,SAAS,uBAAuB,OAAA,EAAqC;AACnE,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,KAAA,CAAM,yDAAyD,CAAA;AACxF,EAAA,IAAI,CAAC,UAAU,OAAO,MAAA;AACtB,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,CAAC,CAAA,CAAE,IAAA,EAAK;AAC9B,EAAA,IAAI,CAAC,MAAM,OAAO,MAAA;AAClB,EAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,KAAA,CAAM,iBAAiB,CAAA;AAClD,EAAA,IAAI,CAAC,eAAe,OAAO,MAAA;AAC3B,EAAA,IAAI,QAAA,GAAW,aAAA,CAAc,CAAC,CAAA,CAAE,IAAA,EAAK;AACrC,EAAA,IAAI,QAAA,CAAS,SAAS,GAAA,EAAK;AACzB,IAAA,MAAM,GAAA,GAAM,QAAA,CAAS,WAAA,CAAY,GAAA,EAAK,GAAG,CAAA;AACzC,IAAA,QAAA,GAAA,CAAY,GAAA,GAAM,CAAA,GAAI,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,GAAI,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,IAAK,QAAA;AAAA,EAC3E;AACA,EAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,IAAA,EAAM,KAAK,CAAA;AACrC;AAEA,SAAS,kBAAkB,OAAA,EAAyB;AAClD,EAAA,MAAM,QAAA,GAAW,OAAA,CACd,KAAA,CAAM,IAAI,EACV,MAAA,CAAO,CAAC,IAAA,KAAS,CAAC,gDAAgD,IAAA,CAAK,IAAI,CAAC,CAAA,CAC5E,KAAK,IAAI,CAAA;AAEZ,EAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,SAAA,EAAW,MAAM,CAAA;AAC3C;AAEA,SAAS,mBAAmB,OAAA,EAAyB;AACnD,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA;AAChC,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,IAAI,UAAA,GAAa,KAAA;AAEjB,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,KAAA,CAAM,uBAAuB,CAAA;AACxD,IAAA,MAAM,SAAA,GAAY,UAAA,CAAW,IAAA,CAAK,IAAI,CAAA;AAEtC,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,IAAI,UAAA,EAAY,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AACjC,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,WAAA,EAAc,aAAA,CAAc,CAAC,CAAC,CAAA,CAAE,CAAA;AAC5C,MAAA,UAAA,GAAa,IAAA;AAAA,IACf,CAAA,MAAA,IAAW,aAAa,UAAA,EAAY;AAClC,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,MAAA,MAAA,CAAO,KAAK,EAAE,CAAA;AACd,MAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAChB,MAAA,UAAA,GAAa,KAAA;AAAA,IACf,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAAA,IAClB;AAAA,EACF;AAEA,EAAA,IAAI,UAAA,EAAY,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AACjC,EAAA,OAAO,MAAA,CAAO,KAAK,IAAI,CAAA;AACzB;AASO,SAAS,iBAAiB,IAAA,EAA8B;AAC7D,EAAA,MAAM,WAAA,GAAc,sBAAA,CAAuB,IAAA,CAAK,OAAO,CAAA;AACvD,EAAA,MAAM,WAAA,GAAc,kBAAA,CAAmB,iBAAA,CAAkB,IAAA,CAAK,OAAO,CAAC,CAAA;AACtE,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAChB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,cAAA,EAAiB,WAAW,CAAA,CAAA,CAAG,CAAA;AAC1C,IAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAChB,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AACA,EAAA,KAAA,CAAM,IAAA,CAAK,KAAK,IAAA,CAAK,KAAA,IAAS,cAAc,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AACxD,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,CAAM,IAAA,CAAK,WAAA,CAAY,OAAA,EAAS,CAAA;AAChC,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAKO,SAAS,sBAAA,CAAuB,OAAyB,MAAA,EAAwB;AACtF,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,KAAK,kBAAkB,CAAA;AAC7B,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,CAAM,KAAK,uDAAuD,CAAA;AAClE,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,KAAA,CAAM,KAAK,kCAAkC,CAAA;AAAA,EAC/C,CAAA,MAAO;AACL,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,GAAA,EAAM,IAAA,CAAK,KAAA,IAAS,aAAA,CAAc,IAAA,CAAK,IAAI,CAAC,CAAA,GAAA,EAAM,MAAM,CAAA,OAAA,EAAU,IAAA,CAAK,IAAI,CAAA,EAAA,CAAI,CAAA;AAAA,IAC5F;AAAA,EACF;AACA,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAKO,SAAS,uBAAA,CAAwB,QAAgB,MAAA,EAAwB;AAC9E,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,IAAA,CAAK,KAAK,MAAA,CAAO,KAAA,IAAS,cAAc,MAAA,CAAO,IAAI,CAAC,CAAA,CAAE,CAAA;AAC5D,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,IAAI,OAAO,WAAA,EAAa;AACtB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,aAAA,EAAgB,MAAA,CAAO,WAAW,CAAA,CAAE,CAAA;AAC/C,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AACA,EAAA,IAAI,OAAO,YAAA,EAAc;AACvB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,cAAA,EAAiB,MAAA,CAAO,YAAY,CAAA,CAAE,CAAA;AACjD,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AACA,EAAA,KAAA,CAAM,KAAK,cAAc,CAAA;AACzB,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,iBAAA,GAClB,CAAA,CAAA,EAAI,MAAM,CAAA,iBAAA,EAAoB,MAAA,CAAO,iBAAiB,CAAA,CAAA,GACtD,CAAA,CAAA,EAAI,MAAM,CAAA,SAAA,EAAY,OAAO,IAAI,CAAA,CAAA;AACrC,EAAA,KAAA,MAAW,QAAA,IAAY,OAAO,SAAA,EAAW;AACvC,IAAA,MAAM,KAAA,GAAQ,SAAS,MAAA,CAAO,CAAC,EAAE,WAAA,EAAY,GAAI,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA;AACjE,IAAA,KAAA,CAAM,KAAK,CAAA,GAAA,EAAM,KAAK,KAAK,MAAM,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,CAAG,CAAA;AAAA,EAClD;AACA,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAKO,SAAS,wBAAA,CAAyB,QAAwB,MAAA,EAAwB;AACvF,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,KAAK,WAAW,CAAA;AACtB,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAEb,EAAA,IAAI,MAAA,CAAO,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG;AAC/B,IAAA,KAAA,CAAM,KAAK,sBAAsB,CAAA;AAAA,EACnC,CAAA,MAAO;AACL,IAAA,KAAA,CAAM,KAAK,WAAW,CAAA;AACtB,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,IAAA,KAAA,MAAW,MAAA,IAAU,OAAO,OAAA,EAAS;AACnC,MAAA,MAAM,OAAO,MAAA,CAAO,WAAA,GAAc,CAAA,GAAA,EAAM,MAAA,CAAO,WAAW,CAAA,EAAA,CAAA,GAAO,EAAA;AACjE,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,GAAA,EAAM,MAAA,CAAO,KAAA,IAAS,cAAc,MAAA,CAAO,IAAI,CAAC,CAAA,GAAA,EAAM,MAAM,CAAA,SAAA,EAAY,MAAA,CAAO,IAAI,CAAA,EAAA,EAAK,IAAI,CAAA,CAAE,CAAA;AAAA,IAC3G;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,CAAO,eAAA,CAAgB,MAAA,GAAS,CAAA,EAAG;AACrC,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,IAAA,KAAA,CAAM,KAAK,WAAW,CAAA;AACtB,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,IAAA,KAAA,MAAW,MAAA,IAAU,OAAO,eAAA,EAAiB;AAC3C,MAAA,MAAM,OAAO,MAAA,CAAO,YAAA,GAAe,CAAA,eAAA,EAAkB,MAAA,CAAO,YAAY,CAAA,EAAA,CAAA,GAAO,EAAA;AAC/E,MAAA,KAAA,CAAM,IAAA;AAAA,QACJ,CAAA,GAAA,EAAM,MAAA,CAAO,KAAA,IAAS,aAAA,CAAc,MAAA,CAAO,IAAI,CAAC,CAAA,GAAA,EAAM,MAAM,CAAA,iBAAA,EAAoB,MAAA,CAAO,iBAAiB,KAAK,IAAI,CAAA;AAAA,OACnH;AAAA,IACF;AAAA,EACF;AAEA,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AA0BO,SAAS,oBAAA,CACd,OAAA,EACA,WAAA,EACA,eAAA,EACA,MAAA,EACQ;AACR,EAAA,MAAM,MAAA,GAASA,qBAAA,CAAK,OAAA,CAAQ,WAAW,CAAA;AAEvC,EAAA,OAAO,OAAA,CAAQ,OAAA;AAAA,IACb,0BAAA;AAAA,IACA,CAAC,MAAA,EAAQ,QAAA,EAAkB,OAAA,KAAoB;AAE7C,MAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,KAAA,CAAM,gCAAgC,CAAA;AACjE,MAAA,IAAI,CAAC,YAAY,OAAO,MAAA;AACxB,MAAA,MAAM,MAAA,GAAS,UAAA,CAAW,CAAC,CAAA,CAAE,IAAA,EAAK;AAClC,MAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,CAAC,CAAA,IAAK,EAAA;AAG/B,MAAA,IACE,CAAC,MAAA,IACD,MAAA,CAAO,UAAA,CAAW,SAAS,CAAA,IAC3B,MAAA,CAAO,UAAA,CAAW,UAAU,CAAA,IAC5B,MAAA,CAAO,UAAA,CAAW,IAAI,CAAA,IACtB,MAAA,CAAO,UAAA,CAAW,GAAG,CAAA,IACrB,MAAA,CAAO,UAAA,CAAW,GAAG,CAAA,IACrB,MAAA,CAAO,UAAA,CAAW,SAAS,CAAA,IAC3B,MAAA,CAAO,UAAA,CAAW,MAAM,CAAA,EACxB;AACA,QAAA,OAAO,MAAA;AAAA,MACT;AAGA,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA;AAClC,MAAA,MAAM,qBAAqB,OAAA,IAAW,CAAA,GAAI,OAAO,KAAA,CAAM,CAAA,EAAG,OAAO,CAAA,GAAI,MAAA;AACrE,MAAA,MAAM,WAAW,OAAA,IAAW,CAAA,GAAI,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,GAAI,EAAA;AAExD,MAAA,IAAI,CAAC,kBAAA,EAAoB;AAEvB,QAAA,OAAO,MAAA;AAAA,MACT;AAGA,MAAA,MAAM,YAAA,GAAeA,qBAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,kBAAkB,CAAA;AAG5D,MAAA,MAAM,aAAA,GAAgBA,qBAAA,CAAK,QAAA,CAAS,eAAA,EAAiB,YAAY,CAAA;AACjE,MAAA,IAAI,cAAc,UAAA,CAAW,IAAI,KAAKA,qBAAA,CAAK,UAAA,CAAW,aAAa,CAAA,EAAG;AACpE,QAAA,OAAO,MAAA;AAAA,MACT;AAGA,MAAA,MAAM,QAAA,GAAW,cAAc,OAAA,CAAQ,OAAA,EAAS,EAAE,CAAA,CAAE,OAAA,CAAQ,OAAO,GAAG,CAAA;AACtE,MAAA,MAAM,eAAe,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA,EAAI,QAAQ,GAAG,QAAQ,CAAA,CAAA;AAEtD,MAAA,OAAO,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,YAAY,GAAG,KAAK,CAAA,CAAA,CAAA;AAAA,IAC5C;AAAA,GACF;AACF;AAMA,SAAS,WAAA,CAAY,MAAA,EAAgB,MAAA,EAAgB,UAAA,GAAa,KAAA,EAAsB;AACtF,EAAA,MAAM,MAAA,GAAS,UAAA,GACX,CAAA,CAAA,EAAI,MAAM,CAAA,iBAAA,EAAoB,MAAA,CAAO,iBAAiB,CAAA,CAAA,GACtD,CAAA,CAAA,EAAI,MAAM,CAAA,SAAA,EAAY,MAAA,CAAO,IAAI,CAAA,CAAA;AACrC,EAAA,OAAO,MAAA,CAAO,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IAClC,IAAA,EAAM,EAAE,MAAA,CAAO,CAAC,EAAE,WAAA,EAAY,GAAI,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA;AAAA,IAC3C,IAAA,EAAM,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,CAAC,CAAA;AAAA,GACtB,CAAE,CAAA;AACJ;AAMO,SAAS,uBAAA,CACd,OAAA,EACA,OAAA,GAA+B,EAAC,EACjB;AACf,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,UAAA;AACjC,EAAA,IAAI,CAACC,mBAAA,CAAG,UAAA,CAAWD,sBAAK,OAAA,CAAQ,OAAO,CAAC,CAAA,EAAG;AACzC,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,0DAAA,EAA6DA,qBAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,GAAA,EAAI,EAAGA,qBAAA,CAAK,OAAA,CAAQ,OAAO,CAAC,CAAC,CAAA,mCAAA,CAAgC,CAAA;AAC7J,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,MAAM,MAAA,GAAS,mBAAmB,OAAO,CAAA;AACzC,EAAA,MAAM,SAAwB,EAAC;AAG/B,EAAA,MAAA,CAAO,IAAA,CAAK;AAAA,IACV,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,EAAW,KAAA;AAAA,IACX,KAAA,EAAO;AAAA,MACL,EAAE,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,CAAA,CAAA,EAAI,MAAM,CAAA,OAAA,CAAA,EAAU;AAAA,MAC9C,GAAG,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,MAAM,CAAA,CAAE,KAAA,IAAS,cAAc,CAAA,CAAE,IAAI,GAAG,IAAA,EAAM,CAAA,CAAA,EAAI,MAAM,CAAA,OAAA,EAAU,CAAA,CAAE,IAAI,CAAA,CAAA,CAAA,EAAI,CAAE;AAAA;AAC9G,GACD,CAAA;AAGD,EAAA,MAAA,CAAO,IAAA,CAAK;AAAA,IACV,IAAA,EAAM,SAAA;AAAA,IACN,SAAA,EAAW,KAAA;AAAA,IACX,KAAA,EAAO;AAAA,MACL,EAAE,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,CAAA,CAAA,EAAI,MAAM,CAAA,SAAA,CAAA,EAAY;AAAA,MAChD,GAAG,MAAA,CAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QAC5B,IAAA,EAAM,CAAA,CAAE,KAAA,IAAS,aAAA,CAAc,EAAE,IAAI,CAAA;AAAA,QACrC,SAAA,EAAW,IAAA;AAAA,QACX,KAAA,EAAO,WAAA,CAAY,CAAA,EAAG,MAAM;AAAA,OAC9B,CAAE;AAAA;AACJ,GACD,CAAA;AAGD,EAAA,IAAI,MAAA,CAAO,eAAA,CAAgB,MAAA,GAAS,CAAA,EAAG;AACrC,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,QAAA;AAAA,MACN,SAAA,EAAW,IAAA;AAAA,MACX,KAAA,EAAO,MAAA,CAAO,eAAA,CAAgB,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QACxC,IAAA,EAAM,CAAA,CAAE,KAAA,IAAS,aAAA,CAAc,EAAE,IAAI,CAAA;AAAA,QACrC,SAAA,EAAW,IAAA;AAAA,QACX,KAAA,EAAO,WAAA,CAAY,CAAA,EAAG,MAAA,EAAQ,IAAI;AAAA,OACpC,CAAE;AAAA,KACH,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,MAAA;AACT;AAKO,SAAS,WAAA,CACd,OAAA,EACA,OAAA,GAA8C,EAAC,EAC/B;AAChB,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,UAAA;AACjC,EAAA,IAAI,CAACC,mBAAA,CAAG,UAAA,CAAWD,sBAAK,OAAA,CAAQ,OAAO,CAAC,CAAA,EAAG;AACzC,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,0DAAA,EAA6DA,qBAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,GAAA,EAAI,EAAGA,qBAAA,CAAK,OAAA,CAAQ,OAAO,CAAC,CAAC,CAAA,+BAAA,CAA4B,CAAA;AACzJ,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,QAAQ,IAAA,IAAQ,MAAA;AAAA,IACtB,IAAA,EAAM,IAAI,MAAM,CAAA,CAAA;AAAA,GAClB;AACF;;;AC3dA,IAAM,WAAA,GAAc,2BAAA;AAEpB,SAAS,SAAA,CAAU,UAAkB,OAAA,EAAuB;AAC1D,EAAAC,mBAAAA,CAAG,UAAUD,qBAAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AACxD,EAAAC,mBAAAA,CAAG,aAAA,CAAc,QAAA,EAAU,OAAA,EAAS,OAAO,CAAA;AAC7C;AA2BO,SAAS,qBAAA,CAAsB,WAAA,GAAqC,EAAC,EAAS;AACnF,EAAA,MAAM,OAAA,GAAU,YAAY,OAAA,IAAW,YAAA;AACvC,EAAA,MAAM,MAAA,GAAS,YAAY,MAAA,IAAU,UAAA;AACrC,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,MAAA,IAAU,OAAA,CAAQ,GAAA,EAAI;AACjD,EAAA,MAAM,cAAA,GAAiBD,qBAAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,MAAM,CAAA;AAElD,EAAA,IAAI,CAACC,mBAAAA,CAAG,UAAA,CAAWD,sBAAK,OAAA,CAAQ,OAAO,CAAC,CAAA,EAAG;AACzC,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,GAAGG,mBAAA,CAAG,IAAA,CAAKA,oBAAG,MAAA,CAAO,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA,CAAG,CAAC,CAAC,CAAA,+BAAA,EAAkCH,sBAAK,QAAA,CAAS,MAAA,EAAQA,sBAAK,OAAA,CAAQ,OAAO,CAAC,CAAC,CAAA,gCAAA;AAAA,KACzH;AACA,IAAA;AAAA,EACF;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,mBAAmB,OAAO,CAAA;AAGzC,IAAA,KAAA,MAAW,IAAA,IAAQ,OAAO,KAAA,EAAO;AAC/B,MAAA,MAAM,OAAOA,qBAAAA,CAAK,IAAA,CAAK,gBAAgB,OAAA,EAAS,IAAA,CAAK,MAAM,UAAU,CAAA;AACrE,MAAA,SAAA,CAAU,IAAA,EAAM,gBAAA,CAAiB,IAAI,CAAC,CAAA;AAAA,IACxC;AACA,IAAA,SAAA;AAAA,MACEA,qBAAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,OAAA,EAAS,UAAU,CAAA;AAAA,MAC7C,sBAAA,CAAuB,MAAA,CAAO,KAAA,EAAO,MAAM;AAAA,KAC7C;AAGA,IAAA,KAAA,MAAW,MAAA,IAAU,OAAO,OAAA,EAAS;AACnC,MAAA,eAAA,CAAgB,MAAA,EAAQ,cAAA,EAAgB,MAAA,EAAQ,KAAA,EAAO,OAAO,GAAG,CAAA;AAAA,IACnE;AAGA,IAAA,KAAA,MAAW,MAAA,IAAU,OAAO,eAAA,EAAiB;AAC3C,MAAA,eAAA,CAAgB,MAAA,EAAQ,cAAA,EAAgB,MAAA,EAAQ,IAAA,EAAM,OAAO,GAAG,CAAA;AAAA,IAClE;AAGA,IAAA,SAAA;AAAA,MACEA,qBAAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,SAAA,EAAW,UAAU,CAAA;AAAA,MAC/C,wBAAA,CAAyB,QAAQ,MAAM;AAAA,KACzC;AAGA,IAAA,MAAM,SAAA,GAAY;AAAA,MAChB,yBAAA;AAAA,MACA,EAAA;AAAA,MACA,wFAAA;AAAA,MACA,mFAAA;AAAA,MACA,sGAAA;AAAA,MACA,EAAA;AAAA,MACA,uBAAuB,MAAM,CAAA,0CAAA,CAAA;AAAA,MAC7B,gBAAgB,MAAM,CAAA,sDAAA,CAAA;AAAA,MACtB;AAAA,KACF,CAAE,KAAK,IAAI,CAAA;AACX,IAAA,SAAA,CAAUA,qBAAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,UAAU,GAAG,SAAS,CAAA;AAI1D,IAAA,SAAA;AAAA,MACEA,qBAAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,YAAY,CAAA;AAAA,MACtC;AAAA,KACF;AAEA,IAAA,OAAA,CAAQ,GAAA;AAAA,MACN,GAAGG,mBAAA,CAAG,IAAA,CAAKA,oBAAG,IAAA,CAAK,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA,CAAG,CAAC,CAAC,CAAA,qBAAA,EAAwBA,oBAAG,IAAA,CAAK,OAAO,CAAC,CAAA,EAAA,EAC1EA,mBAAA,CAAG,MAAM,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,MAAM,CAAC,CAAC,CAAA,UAAA,EACrCA,oBAAG,KAAA,CAAM,MAAA,CAAO,OAAO,OAAA,CAAQ,MAAM,CAAC,CAAC,CAAA,YAAA,EACvCA,oBAAG,KAAA,CAAM,MAAA,CAAO,OAAO,eAAA,CAAgB,MAAM,CAAC,CAAC,CAAA,SAAA;AAAA,KACtD;AAAA,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA;AAAA,MACN,CAAA,EAAGA,mBAAA,CAAG,IAAA,CAAKA,mBAAA,CAAG,IAAI,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA,CAAG,CAAC,CAAC,CAAA,uCAAA,EAA0C,OAAO,CAAA,GAAA,EAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,KAC1G;AAAA,EACF;AACF;AAsBO,SAAS,QAAA,CAAS,WAAA,GAAqC,EAAC,EAAW;AACxE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,WAAA;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IAET,eAAe,cAAA,EAAgB;AAC7B,MAAA,MAAM,WAAY,cAAA,CAAkE,SAAA;AACpF,MAAA,MAAM,MAAA,GACJ,YAAY,MAAA,IAAU,QAAA,EAAU,UAAU,cAAA,CAAe,IAAA,IAAQ,QAAQ,GAAA,EAAI;AAC/E,MAAA,qBAAA,CAAsB,EAAE,GAAG,WAAA,EAAa,MAAA,EAAQ,CAAA;AAAA,IAClD;AAAA,GACF;AACF;AAEA,SAAS,eAAA,CACP,MAAA,EACA,cAAA,EACA,MAAA,EACA,YACA,eAAA,EACM;AACN,EAAA,MAAM,UAAU,UAAA,GACZH,qBAAAA,CAAK,KAAK,SAAA,EAAW,SAAA,EAAW,GAAG,MAAA,CAAO,YAAY,CAAA,CAAA,EAAI,MAAA,CAAO,IAAI,CAAA,CAAE,CAAA,GACvEA,sBAAK,IAAA,CAAK,SAAA,EAAW,OAAO,IAAI,CAAA;AACpC,EAAA,MAAM,YAAA,GAAeA,qBAAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,OAAO,CAAA;AAGtD,EAAA,SAAA,CAAUA,qBAAAA,CAAK,KAAK,YAAA,EAAc,UAAU,GAAG,uBAAA,CAAwB,MAAA,EAAQ,MAAM,CAAC,CAAA;AAGtF,EAAA,KAAA,MAAW,QAAA,IAAY,OAAO,SAAA,EAAW;AACvC,IAAA,MAAM,UAAUA,qBAAAA,CAAK,IAAA,CAAK,OAAO,GAAA,EAAK,CAAA,EAAG,QAAQ,CAAA,GAAA,CAAK,CAAA;AACtD,IAAA,MAAM,WAAWA,qBAAAA,CAAK,IAAA,CAAK,YAAA,EAAc,CAAA,EAAG,QAAQ,CAAA,GAAA,CAAK,CAAA;AACzD,IAAA,MAAM,OAAA,GAAUC,mBAAAA,CAAG,YAAA,CAAa,OAAA,EAAS,OAAO,CAAA;AAChD,IAAA,SAAA,CAAU,UAAU,oBAAA,CAAqB,OAAA,EAAS,OAAA,EAAS,eAAA,EAAiB,MAAM,CAAC,CAAA;AAAA,EACrF;AACF;AA6BO,SAAS,YAAA,CACd,MAAA,EACA,OAAA,GAA+B,EAAC,EAC7B;AACH,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,YAAA;AACnC,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,UAAA;AACjC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,GAAA,EAAI;AAE7C,EAAA,qBAAA,CAAsB,EAAE,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ,CAAA;AAEjD,EAAA,MAAM,MAAA,GAAS,EAAE,GAAG,MAAA,EAAO;AAG3B,EAAA,MAAM,IAAA,GAAQ,MAAA,CAAO,IAAA,IAAQ,EAAC;AAC9B,EAAA,MAAM,eAAA,GAAmB,IAAA,CAAK,OAAA,IAAyB,EAAC;AACxD,EAAA,MAAA,CAAO,IAAA,GAAO,EAAE,GAAG,IAAA,EAAM,SAAS,CAAC,GAAG,eAAA,EAAiB,QAAA,CAAS,EAAE,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ,CAAC,CAAA,EAAE;AAE9F,EAAA,MAAM,WAAA,GAAe,MAAA,CAAO,WAAA,IAAe,EAAC;AAG5C,EAAA,IAAI,OAAA,CAAQ,QAAQ,KAAA,EAAO;AACzB,IAAA,MAAM,QAAA,GAAW,WAAA,CAAY,OAAA,EAAS,EAAE,QAAQ,CAAA;AAChD,IAAA,MAAM,WAAA,GAAe,WAAA,CAAY,GAAA,IAAqB,EAAC;AACvD,IAAA,WAAA,CAAY,MAAM,QAAA,GAAW,CAAC,QAAA,EAAU,GAAG,WAAW,CAAA,GAAI,WAAA;AAAA,EAC5D;AAGA,EAAA,IAAI,OAAA,CAAQ,YAAY,KAAA,IAAS,CAAC,MAAM,OAAA,CAAQ,WAAA,CAAY,OAAO,CAAA,EAAG;AACpE,IAAA,MAAM,UAAA,GAAa,IAAI,MAAM,CAAA,CAAA,CAAA;AAC7B,IAAA,MAAM,eAAA,GAAmB,WAAA,CAAY,OAAA,IAAW,EAAC;AACjD,IAAA,IAAI,CAAC,eAAA,CAAgB,UAAU,CAAA,EAAG;AAChC,MAAA,WAAA,CAAY,OAAA,GAAU;AAAA,QACpB,GAAG,eAAA;AAAA,QACH,CAAC,UAAU,GAAG,wBAAwB,OAAA,EAAS,EAAE,QAAQ;AAAA,OAC3D;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAA,CAAO,WAAA,GAAc,WAAA;AAErB,EAAA,OAAO,MAAA;AACT","file":"index.cjs","sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport { load as yamlLoad } from 'js-yaml'\nimport type {\n CapabilitySpec,\n Change,\n ChangeArtifact,\n NavItem,\n OpenSpecFolder,\n SidebarItem,\n} from './types.js'\n\n// ---------------------------------------------------------------------------\n// Folder reader\n// ---------------------------------------------------------------------------\n\nfunction readOpenSpecYaml(dir: string): Record<string, unknown> {\n const yamlPath = path.join(dir, '.openspec.yaml')\n if (!fs.existsSync(yamlPath)) return {}\n try {\n return (yamlLoad(fs.readFileSync(yamlPath, 'utf-8')) ?? {}) as Record<string, unknown>\n } catch {\n return {}\n }\n}\n\nconst ACRONYM_DICT: Record<string, string> = {\n api: 'API',\n rest: 'REST',\n graphql: 'GraphQL',\n grpc: 'gRPC',\n openapi: 'OpenAPI',\n oauth: 'OAuth',\n oauth2: 'OAuth2',\n http: 'HTTP',\n https: 'HTTPS',\n url: 'URL',\n uri: 'URI',\n sdk: 'SDK',\n ui: 'UI',\n ux: 'UX',\n id: 'ID',\n db: 'DB',\n sql: 'SQL',\n css: 'CSS',\n html: 'HTML',\n json: 'JSON',\n yaml: 'YAML',\n xml: 'XML',\n jwt: 'JWT',\n ci: 'CI',\n cd: 'CD',\n}\n\nfunction humanizeLabel(name: string): string {\n if (!name) return ''\n return name\n .split('-')\n .map((word) => {\n if (/^v\\d+$/.test(word)) return word\n return ACRONYM_DICT[word] ?? (word.charAt(0).toUpperCase() + word.slice(1))\n })\n .join(' ')\n}\n\nfunction parseFrontmatterTitle(content: string): string | undefined {\n const match = content.match(/^---\\s*\\n(?:.*\\n)*?title:\\s*['\"]?([^\\n'\"]+)['\"]?\\s*\\n/)\n return match?.[1]?.trim() || undefined\n}\n\nfunction formatDate(val: unknown): string | undefined {\n if (!val) return undefined\n if (val instanceof Date) return val.toISOString().slice(0, 10)\n return String(val)\n}\n\nfunction readArtifacts(dir: string): ChangeArtifact[] {\n const artifacts: ChangeArtifact[] = []\n for (const name of ['proposal', 'design', 'tasks'] as ChangeArtifact[]) {\n if (fs.existsSync(path.join(dir, `${name}.md`))) artifacts.push(name)\n }\n return artifacts\n}\n\n/**\n * Scans an openspec/ directory and returns a structured representation of all\n * canonical specs, active changes, and archived changes.\n *\n * Throws if the directory does not exist.\n */\nexport function readOpenSpecFolder(dir: string): OpenSpecFolder {\n const resolved = path.resolve(dir)\n if (!fs.existsSync(resolved)) {\n throw new Error(`[vitepress-plugin-openspec] openspec directory not found: ${resolved}`)\n }\n\n // --- Canonical specs ---\n const specs: CapabilitySpec[] = []\n const specsDir = path.join(resolved, 'specs')\n if (fs.existsSync(specsDir)) {\n for (const entry of fs.readdirSync(specsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const specPath = path.join(specsDir, entry.name, 'spec.md')\n if (!fs.existsSync(specPath)) continue\n const content = fs.readFileSync(specPath, 'utf-8')\n specs.push({\n name: entry.name,\n title: parseFrontmatterTitle(content),\n specPath,\n content,\n })\n }\n }\n\n // --- Active changes ---\n const changes: Change[] = []\n const changesDir = path.join(resolved, 'changes')\n if (fs.existsSync(changesDir)) {\n for (const entry of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!entry.isDirectory() || entry.name === 'archive') continue\n const changeDir = path.join(changesDir, entry.name)\n if (!fs.existsSync(path.join(changeDir, '.openspec.yaml'))) continue\n const meta = readOpenSpecYaml(changeDir)\n changes.push({\n name: entry.name,\n title: meta.title ? String(meta.title) : undefined,\n dir: changeDir,\n artifacts: readArtifacts(changeDir),\n createdDate: formatDate(meta.created),\n })\n }\n }\n\n // --- Archived changes ---\n const archivedChanges: Change[] = []\n const archiveDir = path.join(changesDir, 'archive')\n if (fs.existsSync(archiveDir)) {\n for (const entry of fs.readdirSync(archiveDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const changeDir = path.join(archiveDir, entry.name)\n // Parse YYYY-MM-DD-<name> format\n const match = entry.name.match(/^(\\d{4}-\\d{2}-\\d{2})-(.+)$/)\n const archivedDate = match?.[1]\n const name = match?.[2] ?? entry.name\n const meta = readOpenSpecYaml(changeDir)\n archivedChanges.push({\n name,\n title: meta.title ? String(meta.title) : undefined,\n dir: changeDir,\n artifacts: readArtifacts(changeDir),\n createdDate: formatDate(meta.created),\n archivedDate,\n archiveFolderName: entry.name,\n })\n }\n }\n\n return { dir: resolved, specs, changes, archivedChanges }\n}\n\n// ---------------------------------------------------------------------------\n// Spec content transformations\n// ---------------------------------------------------------------------------\n\nfunction extractSpecDescription(content: string): string | undefined {\n const reqMatch = content.match(/^### Requirement:[^\\n]*\\n+([\\s\\S]*?)(?=\\n#{1,4} |\\n*$)/m)\n if (!reqMatch) return undefined\n const para = reqMatch[1].trim()\n if (!para) return undefined\n const sentenceMatch = para.match(/^([^.?!]+[.?!])/)\n if (!sentenceMatch) return undefined\n let sentence = sentenceMatch[1].trim()\n if (sentence.length > 160) {\n const cut = sentence.lastIndexOf(' ', 160)\n sentence = (cut > 0 ? sentence.slice(0, cut) : sentence.slice(0, 160)) + '…'\n }\n return sentence.replace(/\"/g, '\\\\\"')\n}\n\nfunction stripDeltaMarkers(content: string): string {\n const stripped = content\n .split('\\n')\n .filter((line) => !/^## (ADDED|MODIFIED|REMOVED) Requirements\\s*$/.test(line))\n .join('\\n')\n // Collapse consecutive blank lines to a single blank line\n return stripped.replace(/\\n{3,}/g, '\\n\\n')\n}\n\nfunction transformScenarios(content: string): string {\n const lines = content.split('\\n')\n const result: string[] = []\n let inScenario = false\n\n for (const line of lines) {\n const scenarioMatch = line.match(/^#### Scenario: (.+)$/)\n const isHeading = /^#{1,6} /.test(line)\n\n if (scenarioMatch) {\n if (inScenario) result.push(':::')\n result.push(`:::details ${scenarioMatch[1]}`)\n inScenario = true\n } else if (isHeading && inScenario) {\n result.push(':::')\n result.push('')\n result.push(line)\n inScenario = false\n } else {\n result.push(line)\n }\n }\n\n if (inScenario) result.push(':::')\n return result.join('\\n')\n}\n\n// ---------------------------------------------------------------------------\n// Page generators\n// ---------------------------------------------------------------------------\n\n/**\n * Generates VitePress Markdown for a canonical capability spec page.\n */\nexport function generateSpecPage(spec: CapabilitySpec): string {\n const description = extractSpecDescription(spec.content)\n const transformed = transformScenarios(stripDeltaMarkers(spec.content))\n const lines: string[] = []\n if (description) {\n lines.push('---')\n lines.push(`description: \"${description}\"`)\n lines.push('---')\n lines.push('')\n }\n lines.push(`# ${spec.title ?? humanizeLabel(spec.name)}`)\n lines.push('')\n lines.push(transformed.trimEnd())\n lines.push('')\n return lines.join('\\n')\n}\n\n/**\n * Generates the index page listing all canonical specs.\n */\nexport function generateSpecsIndexPage(specs: CapabilitySpec[], outDir: string): string {\n const lines: string[] = []\n lines.push('# Specifications')\n lines.push('')\n lines.push('Canonical capability specifications for this project.')\n lines.push('')\n if (specs.length === 0) {\n lines.push('*No specifications defined yet.*')\n } else {\n for (const spec of specs) {\n lines.push(`- [${spec.title ?? humanizeLabel(spec.name)}](/${outDir}/specs/${spec.name}/)`)\n }\n }\n lines.push('')\n return lines.join('\\n')\n}\n\n/**\n * Generates the index page for a single change.\n */\nexport function generateChangeIndexPage(change: Change, outDir: string): string {\n const lines: string[] = []\n lines.push(`# ${change.title ?? humanizeLabel(change.name)}`)\n lines.push('')\n if (change.createdDate) {\n lines.push(`**Created:** ${change.createdDate}`)\n lines.push('')\n }\n if (change.archivedDate) {\n lines.push(`**Archived:** ${change.archivedDate}`)\n lines.push('')\n }\n lines.push('## Artifacts')\n lines.push('')\n const prefix = change.archiveFolderName\n ? `/${outDir}/changes/archive/${change.archiveFolderName}`\n : `/${outDir}/changes/${change.name}`\n for (const artifact of change.artifacts) {\n const label = artifact.charAt(0).toUpperCase() + artifact.slice(1)\n lines.push(`- [${label}](${prefix}/${artifact})`)\n }\n lines.push('')\n return lines.join('\\n')\n}\n\n/**\n * Generates the changes overview page listing active and archived changes.\n */\nexport function generateChangesIndexPage(folder: OpenSpecFolder, outDir: string): string {\n const lines: string[] = []\n lines.push('# Changes')\n lines.push('')\n\n if (folder.changes.length === 0) {\n lines.push('*No active changes.*')\n } else {\n lines.push('## Active')\n lines.push('')\n for (const change of folder.changes) {\n const date = change.createdDate ? ` *(${change.createdDate})*` : ''\n lines.push(`- [${change.title ?? humanizeLabel(change.name)}](/${outDir}/changes/${change.name}/)${date}`)\n }\n }\n\n if (folder.archivedChanges.length > 0) {\n lines.push('')\n lines.push('## Archiv')\n lines.push('')\n for (const change of folder.archivedChanges) {\n const date = change.archivedDate ? ` *(archiviert: ${change.archivedDate})*` : ''\n lines.push(\n `- [${change.title ?? humanizeLabel(change.name)}](/${outDir}/changes/archive/${change.archiveFolderName}/)${date}`,\n )\n }\n }\n\n lines.push('')\n return lines.join('\\n')\n}\n\n// ---------------------------------------------------------------------------\n// Artifact link rewriting\n// ---------------------------------------------------------------------------\n\n/**\n * Rewrites relative markdown links in an artifact file's content so that they\n * use absolute VitePress paths instead of paths relative to the original\n * openspec source directory.\n *\n * When artifact files (proposal.md, design.md, tasks.md) are copied from the\n * openspec source directory into the VitePress output directory, any relative\n * links they contain that reference other files within the openspec directory\n * must be rewritten to absolute VitePress paths — otherwise VitePress will\n * report them as dead links.\n *\n * Links that point outside the openspec root, absolute paths, HTTP URLs, and\n * anchor-only links are left unchanged.\n *\n * @param content - The markdown content of the artifact file.\n * @param srcFilePath - The absolute path of the source artifact file.\n * @param openspecRootDir - The absolute path of the openspec root directory.\n * @param outDir - The VitePress output directory name (e.g. `\"openspec\"`).\n * @returns The content with rewritten links.\n */\nexport function rewriteRelativeLinks(\n content: string,\n srcFilePath: string,\n openspecRootDir: string,\n outDir: string,\n): string {\n const srcDir = path.dirname(srcFilePath)\n\n return content.replace(\n /(\\[[^\\]]*\\])\\(([^)]+)\\)/g,\n (_match, linkText: string, urlPart: string) => {\n // Separate the URL from an optional quoted title: url \"title\" or url 'title'\n const titleMatch = urlPart.match(/^(.+?)(\\s+[\"'][^\"']*[\"'])?\\s*$/)\n if (!titleMatch) return _match\n const rawUrl = titleMatch[1].trim()\n const title = titleMatch[2] ?? ''\n\n // Leave non-relative URLs unchanged\n if (\n !rawUrl ||\n rawUrl.startsWith('http://') ||\n rawUrl.startsWith('https://') ||\n rawUrl.startsWith('//') ||\n rawUrl.startsWith('/') ||\n rawUrl.startsWith('#') ||\n rawUrl.startsWith('mailto:') ||\n rawUrl.startsWith('tel:')\n ) {\n return _match\n }\n\n // Separate the path component from any trailing fragment (#anchor)\n const hashIdx = rawUrl.indexOf('#')\n const urlWithoutFragment = hashIdx >= 0 ? rawUrl.slice(0, hashIdx) : rawUrl\n const fragment = hashIdx >= 0 ? rawUrl.slice(hashIdx) : ''\n\n if (!urlWithoutFragment) {\n // Pure anchor link — leave as-is\n return _match\n }\n\n // Resolve the relative path against the source file's directory\n const resolvedPath = path.resolve(srcDir, urlWithoutFragment)\n\n // Only rewrite links that remain within the openspec root directory\n const relToOpenspec = path.relative(openspecRootDir, resolvedPath)\n if (relToOpenspec.startsWith('..') || path.isAbsolute(relToOpenspec)) {\n return _match\n }\n\n // Build the absolute VitePress path, stripping any .md extension\n const vitePath = relToOpenspec.replace(/\\.md$/, '').replace(/\\\\/g, '/')\n const absoluteLink = `/${outDir}/${vitePath}${fragment}`\n\n return `${linkText}(${absoluteLink}${title})`\n },\n )\n}\n\n// ---------------------------------------------------------------------------\n// Navigation helpers\n// ---------------------------------------------------------------------------\n\nfunction changeItems(change: Change, outDir: string, isArchived = false): SidebarItem[] {\n const prefix = isArchived\n ? `/${outDir}/changes/archive/${change.archiveFolderName}`\n : `/${outDir}/changes/${change.name}`\n return change.artifacts.map((a) => ({\n text: a.charAt(0).toUpperCase() + a.slice(1),\n link: `${prefix}/${a}`,\n }))\n}\n\n/**\n * Returns a VitePress sidebar configuration for the OpenSpec documentation.\n * Includes groups for Specifications, active Changes, and archived Changes.\n */\nexport function generateOpenSpecSidebar(\n specDir: string,\n options: { outDir?: string } = {},\n): SidebarItem[] {\n const outDir = options.outDir ?? 'openspec'\n if (!fs.existsSync(path.resolve(specDir))) {\n console.warn(`[vitepress-plugin-openspec] openspec directory not found: ${path.relative(process.cwd(), path.resolve(specDir))} — skipping sidebar generation`)\n return []\n }\n const folder = readOpenSpecFolder(specDir)\n const groups: SidebarItem[] = []\n\n // Specifications group\n groups.push({\n text: 'Specifications',\n collapsed: false,\n items: [\n { text: 'Overview', link: `/${outDir}/specs/` },\n ...folder.specs.map((s) => ({ text: s.title ?? humanizeLabel(s.name), link: `/${outDir}/specs/${s.name}/` })),\n ],\n })\n\n // Changes group\n groups.push({\n text: 'Changes',\n collapsed: false,\n items: [\n { text: 'Overview', link: `/${outDir}/changes/` },\n ...folder.changes.map((c) => ({\n text: c.title ?? humanizeLabel(c.name),\n collapsed: true,\n items: changeItems(c, outDir),\n })),\n ],\n })\n\n // Archive group (only if non-empty)\n if (folder.archivedChanges.length > 0) {\n groups.push({\n text: 'Archiv',\n collapsed: true,\n items: folder.archivedChanges.map((c) => ({\n text: c.title ?? humanizeLabel(c.name),\n collapsed: true,\n items: changeItems(c, outDir, true),\n })),\n })\n }\n\n return groups\n}\n\n/**\n * Returns a VitePress nav entry for the OpenSpec documentation section.\n */\nexport function openspecNav(\n specDir: string,\n options: { outDir?: string; text?: string } = {},\n): NavItem | null {\n const outDir = options.outDir ?? 'openspec'\n if (!fs.existsSync(path.resolve(specDir))) {\n console.warn(`[vitepress-plugin-openspec] openspec directory not found: ${path.relative(process.cwd(), path.resolve(specDir))} — skipping nav generation`)\n return null\n }\n return {\n text: options.text ?? 'Docs',\n link: `/${outDir}/`,\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport pc from 'picocolors'\nimport type { Plugin } from 'vite'\nimport type { Change, OpenSpecPluginOptions, WithOpenSpecOptions } from './types.js'\nimport {\n generateChangeIndexPage,\n generateChangesIndexPage,\n generateOpenSpecSidebar,\n generateSpecPage,\n generateSpecsIndexPage,\n openspecNav,\n readOpenSpecFolder,\n rewriteRelativeLinks,\n} from './utils.js'\n\nconst PLUGIN_NAME = 'vitepress-plugin-openspec'\n\nfunction writeFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, content, 'utf-8')\n}\n\n/**\n * Synchronously generates all VitePress Markdown pages from the openspec/\n * directory and writes them to disk.\n *\n * Call this at the top of your `docs/.vitepress/config.ts` **before**\n * `defineConfig()` so the files exist when VitePress scans the source\n * directory for routes.\n *\n * @example\n * ```typescript\n * // docs/.vitepress/config.ts\n * import { defineConfig } from 'vitepress'\n * import path from 'node:path'\n * import { fileURLToPath } from 'node:url'\n * import openspec, { generateOpenSpecPages } from 'vitepress-plugin-openspec'\n *\n * const __dirname = path.dirname(fileURLToPath(import.meta.url))\n * const specDir = path.resolve(__dirname, '../../openspec')\n *\n * // Generate pages before VitePress scans srcDir for routes\n * generateOpenSpecPages({ specDir, outDir: 'openspec', srcDir: path.resolve(__dirname, '..') })\n *\n * export default defineConfig({ ... })\n * ```\n */\nexport function generateOpenSpecPages(userOptions: OpenSpecPluginOptions = {}): void {\n const specDir = userOptions.specDir ?? './openspec'\n const outDir = userOptions.outDir ?? 'openspec'\n const srcDir = userOptions.srcDir ?? process.cwd()\n const absoluteOutDir = path.resolve(srcDir, outDir)\n\n if (!fs.existsSync(path.resolve(specDir))) {\n console.warn(\n `${pc.bold(pc.yellow(`[${PLUGIN_NAME}]`))} openspec directory not found: ${path.relative(srcDir, path.resolve(specDir))} — skipping page generation`,\n )\n return\n }\n\n try {\n const folder = readOpenSpecFolder(specDir)\n\n // --- Spec pages ---\n for (const spec of folder.specs) {\n const dest = path.join(absoluteOutDir, 'specs', spec.name, 'index.md')\n writeFile(dest, generateSpecPage(spec))\n }\n writeFile(\n path.join(absoluteOutDir, 'specs', 'index.md'),\n generateSpecsIndexPage(folder.specs, outDir),\n )\n\n // --- Active change pages ---\n for (const change of folder.changes) {\n writeChangePage(change, absoluteOutDir, outDir, false, folder.dir)\n }\n\n // --- Archived change pages ---\n for (const change of folder.archivedChanges) {\n writeChangePage(change, absoluteOutDir, outDir, true, folder.dir)\n }\n\n // --- Changes index ---\n writeFile(\n path.join(absoluteOutDir, 'changes', 'index.md'),\n generateChangesIndexPage(folder, outDir),\n )\n\n // --- Root index ---\n const rootIndex = [\n '# Project Documentation',\n '',\n \"This section is generated from the project's [OpenSpec](https://openspec.dev/) folder.\",\n 'OpenSpec is a lightweight, file-based workflow for spec-driven development —',\n 'it structures your project\\'s capability specifications and change proposals as plain Markdown files.',\n '',\n `- [Specifications](/${outDir}/specs/) — canonical capability specs`,\n `- [Changes](/${outDir}/changes/) — active and archived change proposals`,\n '',\n ].join('\\n')\n writeFile(path.join(absoluteOutDir, 'index.md'), rootIndex)\n\n // Write a self-managed .gitignore so consumers don't need to add the\n // output directory to their project-level .gitignore manually.\n writeFile(\n path.join(absoluteOutDir, '.gitignore'),\n '# Generated by vitepress-plugin-openspec — do not commit generated files.\\n*\\n!.gitignore\\n',\n )\n\n console.log(\n `${pc.bold(pc.cyan(`[${PLUGIN_NAME}]`))} Generated docs from ${pc.cyan(specDir)}: ` +\n `${pc.green(String(folder.specs.length))} spec(s), ` +\n `${pc.green(String(folder.changes.length))} change(s), ` +\n `${pc.green(String(folder.archivedChanges.length))} archived`,\n )\n } catch (err) {\n console.error(\n `${pc.bold(pc.red(`[${PLUGIN_NAME}]`))} Failed to process openspec directory \"${specDir}\": ${String(err)}`,\n )\n }\n}\n\n/**\n * VitePress plugin that reads an openspec/ directory and generates structured\n * Markdown documentation pages inside the VitePress source directory.\n *\n * For the pages to be available on the first build (including CI), also call\n * `generateOpenSpecPages()` at the top of your `config.ts` before `defineConfig`.\n *\n * @example\n * ```typescript\n * // .vitepress/config.ts\n * import { defineConfig } from 'vitepress'\n * import openspec, { generateOpenSpecPages } from 'vitepress-plugin-openspec'\n *\n * generateOpenSpecPages({ specDir, outDir: 'openspec', srcDir: path.resolve(__dirname, '..') })\n *\n * export default defineConfig({\n * vite: { plugins: [openspec({ specDir: './openspec', outDir: 'project-docs' })] },\n * })\n * ```\n */\nexport function openspec(userOptions: OpenSpecPluginOptions = {}): Plugin {\n return {\n name: PLUGIN_NAME,\n enforce: 'pre',\n\n configResolved(resolvedConfig) {\n const vpConfig = (resolvedConfig as unknown as { vitepress?: { srcDir?: string } }).vitepress\n const srcDir =\n userOptions.srcDir ?? vpConfig?.srcDir ?? resolvedConfig.root ?? process.cwd()\n generateOpenSpecPages({ ...userOptions, srcDir })\n },\n }\n}\n\nfunction writeChangePage(\n change: Change,\n absoluteOutDir: string,\n outDir: string,\n isArchived: boolean,\n openspecRootDir: string,\n): void {\n const subPath = isArchived\n ? path.join('changes', 'archive', `${change.archivedDate}-${change.name}`)\n : path.join('changes', change.name)\n const changeOutDir = path.join(absoluteOutDir, subPath)\n\n // Write index page\n writeFile(path.join(changeOutDir, 'index.md'), generateChangeIndexPage(change, outDir))\n\n // Copy artifact files, rewriting relative links to absolute VitePress paths\n for (const artifact of change.artifacts) {\n const srcFile = path.join(change.dir, `${artifact}.md`)\n const destFile = path.join(changeOutDir, `${artifact}.md`)\n const content = fs.readFileSync(srcFile, 'utf-8')\n writeFile(destFile, rewriteRelativeLinks(content, srcFile, openspecRootDir, outDir))\n }\n}\n\n/**\n * One-call VitePress config helper that wires up the full openspec integration.\n *\n * Calls `generateOpenSpecPages()` synchronously (required before VitePress scans\n * for routes), then merges the openspec Vite plugin, nav entry, and sidebar section\n * into the provided config object.\n *\n * Other Vite plugins go into `vite.plugins` as usual — `withOpenSpec` appends to\n * the array without replacing it:\n *\n * @example\n * ```typescript\n * // docs/.vitepress/config.ts\n * import { defineConfig } from 'vitepress'\n * import { withOpenSpec } from 'vitepress-plugin-openspec'\n *\n * export default defineConfig(\n * withOpenSpec({\n * vite: { plugins: [myOtherPlugin()] }, // other plugins are preserved\n * themeConfig: { nav: [], sidebar: {} },\n * })\n * )\n * ```\n *\n * @param config - Your VitePress `UserConfig` object (same as what `defineConfig` accepts).\n * @param options - OpenSpec options. All fields are optional; defaults match `generateOpenSpecPages`.\n */\nexport function withOpenSpec<T extends Record<string, unknown>>(\n config: T,\n options: WithOpenSpecOptions = {},\n): T {\n const specDir = options.specDir ?? './openspec'\n const outDir = options.outDir ?? 'openspec'\n const srcDir = options.srcDir ?? process.cwd()\n\n generateOpenSpecPages({ specDir, outDir, srcDir })\n\n const result = { ...config } as Record<string, unknown>\n\n // --- Vite plugin ---\n const vite = (result.vite ?? {}) as Record<string, unknown>\n const existingPlugins = (vite.plugins as unknown[]) ?? []\n result.vite = { ...vite, plugins: [...existingPlugins, openspec({ specDir, outDir, srcDir })] }\n\n const themeConfig = (result.themeConfig ?? {}) as Record<string, unknown>\n\n // --- Nav ---\n if (options.nav !== false) {\n const navEntry = openspecNav(specDir, { outDir })\n const existingNav = (themeConfig.nav as unknown[]) ?? []\n themeConfig.nav = navEntry ? [navEntry, ...existingNav] : existingNav\n }\n\n // --- Sidebar ---\n if (options.sidebar !== false && !Array.isArray(themeConfig.sidebar)) {\n const sidebarKey = `/${outDir}/`\n const existingSidebar = (themeConfig.sidebar ?? {}) as Record<string, unknown>\n if (!existingSidebar[sidebarKey]) {\n themeConfig.sidebar = {\n ...existingSidebar,\n [sidebarKey]: generateOpenSpecSidebar(specDir, { outDir }),\n }\n }\n }\n\n result.themeConfig = themeConfig\n\n return result as T\n}\n\nexport default openspec\n"]}