@stritti/vitepress-plugin-openspec 0.8.2 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +6 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/dev-server.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -709,6 +709,11 @@ function openspecNav(specDir, options = {}) {
|
|
|
709
709
|
};
|
|
710
710
|
}
|
|
711
711
|
|
|
712
|
+
// src/types.ts
|
|
713
|
+
function getVitepressExtension(resolvedConfig) {
|
|
714
|
+
return resolvedConfig.vitepress;
|
|
715
|
+
}
|
|
716
|
+
|
|
712
717
|
// src/lib/dev-server.ts
|
|
713
718
|
function readNavigationSignature(options) {
|
|
714
719
|
try {
|
|
@@ -758,7 +763,7 @@ function openspec(userOptions = {}) {
|
|
|
758
763
|
enforce: "pre",
|
|
759
764
|
configResolved(resolvedConfig) {
|
|
760
765
|
detachListeners?.();
|
|
761
|
-
const vpConfig = resolvedConfig
|
|
766
|
+
const vpConfig = getVitepressExtension(resolvedConfig);
|
|
762
767
|
const srcDir = userOptions.srcDir ?? vpConfig?.srcDir ?? resolvedConfig.root ?? process.cwd();
|
|
763
768
|
try {
|
|
764
769
|
resolvedOptions = resolveOptions(userOptions, srcDir);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/logger.ts","../src/lib/detect.ts","../src/lib/options.ts","../src/lib/watch.ts","../src/lib/reader.ts","../src/lib/links.ts","../src/lib/markdown.ts","../src/lib/pages.ts","../src/lib/generator.ts","../src/lib/navigation.ts","../src/lib/dev-server.ts","../src/plugin.ts"],"names":["pc","path","fs","parent","yamlLoad","prefix","retained"],"mappings":"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","file":"index.cjs","sourcesContent":["import pc from 'picocolors'\n\nexport const PLUGIN_NAME = 'vitepress-plugin-openspec'\n\nfunction prefix(color: (s: string) => string): string {\n return pc.bold(color(`[${PLUGIN_NAME}]`))\n}\n\nexport function logWarn(message: string): void {\n console.warn(`${prefix(pc.yellow)} ${message}`)\n}\n\nexport function logInfo(message: string): void {\n console.log(`${prefix(pc.cyan)} ${message}`)\n}\n\nexport function logError(message: string): void {\n console.error(`${prefix(pc.red)} ${message}`)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { PLUGIN_NAME, logWarn } from './logger.js'\n\nconst GENERATED_MARKER = '# Generated by vitepress-plugin-openspec'\n\n/**\n * Returns how strongly a directory looks like a real openspec/ source folder.\n * - 'strong': unambiguous markers (project.md, config file, spec.md, change yaml)\n * - 'weak': only an archive layout — valid for real sources that contain only\n * archived changes, but also matches unmarked generated output, so it is\n * only used when no strong candidate exists anywhere up the tree\n * - false: generated output (identified via its generated .gitignore marker)\n * or no openspec structure at all\n */\nexport function looksLikeOpenSpecDir(dir: string): 'strong' | 'weak' | false {\n const gitignore = path.join(dir, '.gitignore')\n if (fs.existsSync(gitignore)) {\n try {\n if (fs.readFileSync(gitignore, 'utf-8').startsWith(GENERATED_MARKER)) return false\n } catch {\n // ignore unreadable files\n }\n }\n if (fs.existsSync(path.join(dir, 'project.md'))) return 'strong'\n if (fs.existsSync(path.join(dir, 'config.yaml')) || fs.existsSync(path.join(dir, 'config.yml'))) return 'strong'\n const changesDir = path.join(dir, 'changes')\n if (fs.existsSync(changesDir)) {\n try {\n for (const entry of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!entry.isDirectory() && !entry.name.endsWith('.yaml')) continue\n const marker = path.join(changesDir, entry.name, '.openspec.yaml')\n const yaml = path.join(changesDir, `${entry.name}.yaml`)\n if (fs.existsSync(marker) || fs.existsSync(yaml)) return 'strong'\n }\n } catch {\n // ignore unreadable directories\n }\n }\n const specsDir = path.join(dir, 'specs')\n if (fs.existsSync(specsDir)) {\n try {\n for (const entry of fs.readdirSync(specsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n if (fs.existsSync(path.join(specsDir, entry.name, 'spec.md'))) return 'strong'\n }\n } catch {\n // ignore unreadable directories\n }\n }\n const archiveDir = path.join(changesDir, 'archive')\n if (fs.existsSync(archiveDir)) {\n try {\n if (fs.readdirSync(archiveDir, { withFileTypes: true }).some((e) => e.isDirectory())) return 'weak'\n } catch {\n // ignore unreadable directories\n }\n }\n return false\n}\n\n/**\n * Walks up from `start` looking for a real `openspec/` folder. The nearest\n * valid source wins: an archive-only (weak) source found on the way up is\n * preferred over any strong source further up the tree, while unmarked\n * generated output at the output location is skipped as interrupted output.\n * This keeps the plugin zero-config: users do not need to pass `specDir` when\n * `openspec/` lives at the project root, even when VitePress is invoked from\n * a subfolder.\n */\nexport function findOpenSpecDir(start: string, generatedOutputDir?: string): string | undefined {\n let current = path.resolve(start)\n for (;;) {\n const candidate = path.join(current, 'openspec')\n if (fs.existsSync(candidate)) {\n const match = looksLikeOpenSpecDir(candidate)\n // A weak match at the generated output location is unmarked output\n // from an interrupted run — keep searching for the real source.\n if (match === 'weak' && generatedOutputDir && realPath(candidate) === realPath(generatedOutputDir)) {\n const parent = path.dirname(current)\n if (parent === current) return undefined\n current = parent\n continue\n }\n if (match === 'strong' || match === 'weak') return candidate\n }\n const parent = path.dirname(current)\n if (parent === current) return undefined\n current = parent\n }\n}\n\n/**\n * Resolves a path to its canonical form, following symlinks of the deepest\n * existing ancestor so containment checks are not defeated by symlinked\n * output directories.\n */\nexport function realPath(target: string): string {\n let current = path.resolve(target)\n const suffix: string[] = []\n for (;;) {\n if (fs.existsSync(current)) break\n const parent = path.dirname(current)\n if (parent === current) return path.resolve(target)\n suffix.unshift(path.basename(current))\n current = parent\n }\n try {\n current = fs.realpathSync(current)\n } catch {\n return path.resolve(target)\n }\n return suffix.length ? path.join(current, ...suffix) : current\n}\n\nconst srcDirCache = new Map<string, string | undefined>()\n\n/**\n * Detects the VitePress source directory (the folder containing `.vitepress`)\n * by checking the current working directory and its first-level subdirectories\n * (e.g. `docs/.vitepress`). Falls back to the working directory itself.\n *\n * Cached per working directory so repeated calls (e.g. from both\n * `withOpenSpec` and `generateOpenSpecPages` during one config load) do not\n * re-run detection or repeat ambiguity warnings.\n */\nexport function detectSrcDir(cwd: string): string | undefined {\n const key = path.resolve(cwd)\n if (srcDirCache.has(key)) return srcDirCache.get(key)\n const result = resolveSrcDir(key)\n srcDirCache.set(key, result)\n return result\n}\n\nfunction resolveSrcDir(cwd: string): string | undefined {\n if (path.basename(cwd) === '.vitepress') return path.dirname(cwd)\n if (fs.existsSync(path.join(cwd, '.vitepress'))) return cwd\n const matches: string[] = []\n try {\n for (const entry of fs.readdirSync(cwd, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const subDir = path.join(cwd, entry.name)\n if (fs.existsSync(path.join(subDir, '.vitepress'))) matches.push(subDir)\n }\n } catch {\n // ignore unreadable directories\n }\n if (matches.length === 1) return matches[0]\n if (matches.length > 1) {\n const docsMatch = matches.find((m) => path.basename(m) === 'docs')\n if (docsMatch) return docsMatch\n logWarn(\n `Multiple VitePress source directories found (${matches\n .map((m) => path.relative(cwd, m))\n .join(', ')}) — pass an explicit \\`srcDir\\` option. Skipping page generation.`,\n )\n return undefined\n }\n return cwd\n}\n\n/**\n * Detects the VitePress project root — the directory containing the\n * `.vitepress` folder — so a relative `srcDir` from the wrapped config can be\n * resolved the same way VitePress resolves it.\n */\nexport function detectVitePressRoot(cwd: string): string {\n const srcDir = detectSrcDir(cwd)\n return srcDir && fs.existsSync(path.join(srcDir, '.vitepress')) ? srcDir : cwd\n}\n","import path from 'node:path'\nimport type { OpenSpecPluginOptions } from '../types.js'\nimport { detectSrcDir, findOpenSpecDir } from './detect.js'\n\n/**\n * Fully resolved and validated plugin options.\n */\nexport interface ResolvedOptions {\n /** Absolute path to the openspec/ directory */\n specDir: string\n /** Output directory name relative to srcDir (e.g. \"openspec\") */\n outDir: string\n /** Absolute VitePress source directory */\n srcDir: string\n /** Absolute output directory inside srcDir */\n absoluteOutDir: string\n}\n\n/**\n * Centralizes default resolution for all plugin entry points so\n * `generateOpenSpecPages()`, `openspec()` and `withOpenSpec()` behave\n * identically.\n *\n * Defaults are zero-config: `srcDir` falls back to the auto-detected\n * VitePress source directory (the folder containing `.vitepress`), and\n * `specDir` falls back to the nearest ancestor `openspec/` folder,\n * skipping generated output recognized by its marker.\n *\n * @throws if `outDir` is not a relative path inside `srcDir`.\n */\nexport function resolveOptions(\n userOptions: OpenSpecPluginOptions = {},\n fallbackSrcDir?: string,\n): ResolvedOptions {\n // Normalize Windows-style separators so traversal variants like\n // \"nested\\\\..\\\\..\\\\outside\" cannot bypass the containment check.\n const outDir = (userOptions.outDir ?? 'openspec').replace(/\\\\/g, '/')\n if (path.isAbsolute(outDir) || outDir === '' || outDir === '.' || outDir === '..') {\n throw new Error(\n `[vitepress-plugin-openspec] Invalid outDir \"${outDir}\": it must be a relative path inside the VitePress srcDir.`,\n )\n }\n const srcDir = userOptions.srcDir ?? fallbackSrcDir ?? detectSrcDir(process.cwd()) ?? process.cwd()\n const absoluteSrcDir = path.resolve(srcDir)\n const absoluteOutDir = path.resolve(absoluteSrcDir, outDir)\n const rel = path.relative(absoluteSrcDir, absoluteOutDir)\n if (rel.startsWith('..') || path.isAbsolute(rel) || rel === '') {\n throw new Error(\n `[vitepress-plugin-openspec] Invalid outDir \"${outDir}\": it resolves outside the VitePress srcDir.`,\n )\n }\n const specDir = userOptions.specDir ?? findOpenSpecDir(process.cwd(), absoluteOutDir) ?? './openspec'\n return {\n specDir: path.resolve(specDir),\n outDir,\n srcDir: absoluteSrcDir,\n absoluteOutDir,\n }\n}\n","import path from 'node:path'\nimport type { ResolvedOptions } from './options.js'\nimport { readManifest } from './generator.js'\n\n// Basenames of files the plugin always writes into the output tree.\nconst ALWAYS_GENERATED_BASENAMES = new Set(['index.md', '.gitignore', '.openspec-manifest.json'])\n// Artifact copies the plugin writes when the output tree is distinct\n// from the openspec source tree.\nconst ARTIFACT_BASENAMES = new Set(['proposal.md', 'design.md', 'tasks.md'])\n\nconst generatedDestCache = new Map<string, Set<string>>()\n\n/**\n * Resolved absolute destinations of all files recorded in the previous\n * run's manifest — i.e. paths the plugin itself wrote. Only these exact\n * destinations count as generated, never a basename heuristic, so real\n * source artifacts that live inside the output tree remain watchable.\n */\nfunction generatedDestinations(absoluteOutDir: string): Set<string> {\n const cached = generatedDestCache.get(absoluteOutDir)\n if (cached) return cached\n const set = new Set<string>()\n for (const entry of readManifest(absoluteOutDir)) {\n set.add(path.resolve(absoluteOutDir, entry))\n }\n generatedDestCache.set(absoluteOutDir, set)\n return set\n}\n\n/**\n * Invalidates the cached manifest destinations after a regeneration wrote\n * a new manifest.\n */\nexport function invalidateGeneratedDestinations(absoluteOutDir: string): void {\n generatedDestCache.delete(absoluteOutDir)\n}\n\nfunction isInside(parent: string, child: string): boolean {\n const rel = path.relative(parent, child)\n return !(rel.startsWith('..') || path.isAbsolute(rel))\n}\n\n/**\n * Layout classification for the overlapping specDir/outDir cases:\n * - 'equal': specDir and outDir are the same directory\n * - 'out-inside-spec': outDir is a proper child of specDir\n * - 'spec-inside-out': specDir is a proper child of outDir\n * - 'disjoint': no overlap\n */\nexport type LayoutRelation = 'equal' | 'out-inside-spec' | 'spec-inside-out' | 'disjoint'\n\nexport function classifyLayout(options: ResolvedOptions): LayoutRelation {\n if (options.specDir === options.absoluteOutDir) return 'equal'\n if (isInside(options.specDir, options.absoluteOutDir)) return 'out-inside-spec'\n if (isInside(options.absoluteOutDir, options.specDir)) return 'spec-inside-out'\n return 'disjoint'\n}\n\n/**\n * Whether a file inside the output tree was written by this plugin (as\n * opposed to an openspec source artifact that happens to live in the same\n * tree when specDir and outDir overlap).\n *\n * Layout rules (generated destinations never coincide with source files):\n * - 'equal': the shared tree only receives index.md/.gitignore/manifest\n * from the plugin; artifact-named files are sources.\n * - 'out-inside-spec' / 'disjoint': the plugin writes artifact copies into\n * the output tree; every known basename inside it is generated.\n * - 'spec-inside-out': source files live inside the output tree; files\n * inside specDir are sources, only files outside it are generated.\n */\nexport function isPluginGeneratedFile(options: ResolvedOptions, absFile: string): boolean {\n if (!isInside(options.absoluteOutDir, absFile)) return false\n // Only exact destinations recorded in the generation manifest are\n // generated output — never a basename heuristic. This keeps real source\n // artifacts inside an overlapping output tree watchable.\n if (generatedDestinations(options.absoluteOutDir).has(path.resolve(absFile))) return true\n const base = path.basename(absFile)\n switch (classifyLayout(options)) {\n case 'equal':\n return ALWAYS_GENERATED_BASENAMES.has(base)\n case 'out-inside-spec':\n // The output tree is nested inside specDir, so a basename match can\n // hit real source files too. Only the exact destinations recorded\n // in the manifest (checked above) plus the always-generated\n // top-level markers count as plugin output.\n return ALWAYS_GENERATED_BASENAMES.has(base) && !isInside(options.specDir, absFile)\n case 'disjoint':\n return ALWAYS_GENERATED_BASENAMES.has(base) || ARTIFACT_BASENAMES.has(base)\n case 'spec-inside-out':\n return !isInside(options.specDir, absFile) &&\n (ALWAYS_GENERATED_BASENAMES.has(base) || ARTIFACT_BASENAMES.has(base))\n }\n}\n\n/**\n * Whether a watch event for this file should trigger regeneration of the\n * openspec pages. True for openspec source files (including\n * `.openspec.yaml`), false for files the plugin itself generated.\n */\nexport function isSourceArtifactEvent(options: ResolvedOptions, absFile: string): boolean {\n if (!isInside(options.specDir, absFile)) return false\n return !isPluginGeneratedFile(options, absFile)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { load as yamlLoad } from 'js-yaml'\nimport type { CapabilitySpec, Change, ChangeArtifact, OpenSpecFolder } from '../types.js'\n\nconst ARTIFACT_NAMES: ChangeArtifact[] = ['proposal', 'design', 'tasks']\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\nexport function 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 return ARTIFACT_NAMES.filter((name) => fs.existsSync(path.join(dir, `${name}.md`)))\n}\n\nfunction isDirectory(dir: string, name: string): boolean {\n return fs.existsSync(path.join(dir, name, '.openspec.yaml'))\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 (!isDirectory(changeDir, '.')) 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 const meta = readOpenSpecYaml(changeDir)\n const match = entry.name.match(/^(\\d{4}-\\d{2}-\\d{2})-(.+)$/)\n archivedChanges.push({\n name: match?.[2] ?? entry.name,\n title: meta.title ? String(meta.title) : undefined,\n dir: changeDir,\n artifacts: readArtifacts(changeDir),\n createdDate: formatDate(meta.created),\n archivedDate: match?.[1],\n archiveFolderName: entry.name,\n })\n }\n }\n\n return { dir: resolved, specs, changes, archivedChanges }\n}\n","import path from 'node:path'\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 * Links that point outside the openspec root, absolute paths, HTTP URLs, and\n * anchor-only links are left unchanged.\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 return content.replace(\n /(\\[[^\\]]*\\])\\(([^)]+)\\)/g,\n (_match, linkText: string, urlPart: string) => {\n const titleMatch = urlPart.match(/^(.+?)(\\s+[\"'][^\"']*[\"'])?\\s*$/)\n if (!titleMatch) return _match\n const rawUrl = titleMatch[1].trim()\n const title = titleMatch[2] ?? ''\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 const hashIdx = rawUrl.indexOf('#')\n const urlWithoutFragment = hashIdx >= 0 ? rawUrl.slice(0, hashIdx) : rawUrl\n const fragment = hashIdx >= 0 ? rawUrl.slice(hashIdx) : ''\n if (!urlWithoutFragment) {\n return _match\n }\n const resolvedPath = path.resolve(srcDir, urlWithoutFragment)\n const relToOpenspec = path.relative(openspecRootDir, resolvedPath)\n if (relToOpenspec.startsWith('..') || path.isAbsolute(relToOpenspec)) {\n return _match\n }\n const vitePath = relToOpenspec.replace(/\\.md$/, '').replace(/\\\\/g, '/')\n const absoluteLink = `/${outDir}/${vitePath}${fragment}`\n return `${linkText}(${absoluteLink}${title})`\n },\n )\n}\n","import type { CapabilitySpec } from '../types.js'\nimport { humanizeLabel } from './reader.js'\n\nexport function 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, '\\\\$1')\n}\n\nexport function 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 return stripped.replace(/\\n{3,}/g, '\\n\\n')\n}\n\nexport function transformScenarios(content: string): string {\n const lines = content.split('\\n')\n const result: string[] = []\n let inScenario = false\n for (const line of lines) {\n const scenarioMatch = line.match(/^#### Scenario: (.+)$/)\n const isHeading = /^#{1,6} /.test(line)\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 if (inScenario) result.push(':::')\n return result.join('\\n')\n}\n\nexport function specTitle(spec: CapabilitySpec): string {\n return spec.title ?? humanizeLabel(spec.name)\n}\n","import type { CapabilitySpec, Change, OpenSpecFolder } from '../types.js'\nimport { humanizeLabel } from './reader.js'\nimport { extractSpecDescription, specTitle, stripDeltaMarkers, transformScenarios } from './markdown.js'\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(`# ${specTitle(spec)}`)\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(`- [${specTitle(spec)}](/${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 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 if (folder.archivedChanges.length > 0) {\n lines.push('')\n lines.push('## Archive')\n lines.push('')\n for (const change of folder.archivedChanges) {\n const date = change.archivedDate ? ` *(archived: ${change.archivedDate})*` : ''\n lines.push(\n `- [${change.title ?? humanizeLabel(change.name)}](/${outDir}/changes/archive/${change.archiveFolderName}/)${date}`,\n )\n }\n }\n lines.push('')\n return lines.join('\\n')\n}\n\n/**\n * Generates the root index page of the openspec documentation section.\n */\nexport function generateRootIndexPage(outDir: string): string {\n return [\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}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { invalidateGeneratedDestinations } from './watch.js'\nimport type { Change } from '../types.js'\nimport type { ResolvedOptions } from './options.js'\nimport { logError, logInfo, logWarn } from './logger.js'\nimport { readOpenSpecFolder } from './reader.js'\nimport { rewriteRelativeLinks } from './links.js'\nimport {\n generateChangeIndexPage,\n generateChangesIndexPage,\n generateRootIndexPage,\n generateSpecPage,\n generateSpecsIndexPage,\n} from './pages.js'\n\nexport const MANIFEST_FILE = '.openspec-manifest.json'\nconst GITIGNORE_CONTENT = '# Generated by vitepress-plugin-openspec — do not commit generated files.\\n*\\n!.gitignore\\n'\n\ninterface OutputFile {\n /** Path relative to absoluteOutDir, using forward slashes */\n rel: string\n content: string\n}\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 toRel(absoluteOutDir: string, filePath: string): string {\n return path.relative(absoluteOutDir, filePath).split(path.sep).join('/')\n}\n\nfunction pruneEmptyDirs(rootDir: string, startDir: string): void {\n let dir = startDir\n while (dir.startsWith(rootDir) && dir !== rootDir) {\n try {\n if (fs.readdirSync(dir).length > 0) break\n fs.rmdirSync(dir)\n } catch {\n break\n }\n dir = path.dirname(dir)\n }\n}\n\n/**\n * Reads the previous run's manifest and deletes all recorded files.\n * Runs only after the replacement generation has been fully read and\n * rendered in memory, so a failing source read never destroys the last\n * successful output. Because cleanup precedes writing the new files, a\n * stale entry can never resolve to a freshly written page, even for\n * case-only renames on case-insensitive filesystems.\n *\n * @returns entries whose deletion failed; they are retained in the next\n * manifest so cleanup retries instead of forgetting them.\n */\nfunction cleanupPreviousManifest(rootDir: string): string[] {\n const manifestPath = path.join(rootDir, MANIFEST_FILE)\n if (!fs.existsSync(manifestPath)) return []\n let previous: string[] = []\n try {\n const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as unknown\n if (Array.isArray(parsed)) previous = parsed.filter((f): f is string => typeof f === 'string')\n } catch {\n // Unreadable manifest: treat as empty\n return []\n }\n const retained: string[] = []\n for (const entry of previous) {\n const entryPath = path.resolve(rootDir, entry)\n const rel = path.relative(rootDir, entryPath)\n if (rel.startsWith('..') || path.isAbsolute(rel)) continue\n try {\n if (fs.existsSync(entryPath)) {\n fs.rmSync(entryPath)\n pruneEmptyDirs(rootDir, path.dirname(entryPath))\n }\n } catch {\n // Deletion failed (e.g. locked file): retry on the next run\n retained.push(entry)\n }\n }\n return retained\n}\n\nexport function readManifest(rootDir: string): string[] {\n try {\n const parsed = JSON.parse(fs.readFileSync(path.join(rootDir, MANIFEST_FILE), 'utf-8')) as unknown\n if (Array.isArray(parsed)) return parsed.filter((f): f is string => typeof f === 'string')\n } catch {\n // Unreadable or missing manifest: treat as empty\n }\n return []\n}\n\nfunction writeManifest(files: string[], rootDir: string): void {\n const manifestPath = path.join(rootDir, MANIFEST_FILE)\n try {\n writeFile(manifestPath, JSON.stringify(files, null, 2))\n invalidateGeneratedDestinations(rootDir)\n } catch {\n // Best-effort: never fail generation because of the manifest\n }\n}\n\nfunction renderChangePages(\n change: Change,\n options: ResolvedOptions,\n isArchived: boolean,\n): OutputFile[] {\n const subPath = isArchived\n ? path.join('changes', 'archive', change.archiveFolderName ?? change.name)\n : path.join('changes', change.name)\n const changeOutDir = path.join(options.absoluteOutDir, subPath)\n const files: OutputFile[] = []\n\n files.push({\n rel: toRel(options.absoluteOutDir, path.join(changeOutDir, 'index.md')),\n content: generateChangeIndexPage(change, options.outDir),\n })\n\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 // When specDir and outDir overlap, never copy a file onto itself\n if (path.resolve(srcFile) === path.resolve(destFile)) continue\n const content = fs.readFileSync(srcFile, 'utf-8')\n files.push({\n rel: toRel(options.absoluteOutDir, destFile),\n content: rewriteRelativeLinks(content, srcFile, options.specDir, options.outDir),\n })\n }\n return files\n}\n\n/**\n * Reads the openspec directory and renders every output page into memory.\n * All source file access happens here, before any destructive step, so\n * an inconsistent source tree cannot destroy the previous output.\n */\nfunction renderAllPages(options: ResolvedOptions): OutputFile[] {\n const folder = readOpenSpecFolder(options.specDir)\n const files: OutputFile[] = []\n\n for (const spec of folder.specs) {\n const dest = path.join(options.absoluteOutDir, 'specs', spec.name, 'index.md')\n files.push({ rel: toRel(options.absoluteOutDir, dest), content: generateSpecPage(spec) })\n }\n files.push({\n rel: 'specs/index.md',\n content: generateSpecsIndexPage(folder.specs, options.outDir),\n })\n\n for (const change of folder.changes) {\n files.push(...renderChangePages(change, options, false))\n }\n for (const change of folder.archivedChanges) {\n files.push(...renderChangePages(change, options, true))\n }\n\n files.push({\n rel: 'changes/index.md',\n content: generateChangesIndexPage(folder, options.outDir),\n })\n files.push({\n rel: 'index.md',\n content: generateRootIndexPage(options.outDir),\n })\n\n return files\n}\n\n/**\n * Synchronously generates all VitePress Markdown pages from the openspec/\n * directory and writes them to disk, removing stale output from previous runs.\n *\n * @returns true when pages were written; false when generation was skipped\n * (missing or unreadable source) or failed.\n */\nexport function generatePages(options: ResolvedOptions): boolean {\n // Remove stale output from the previous run even when the source\n // directory has disappeared, so published pages do not linger forever.\n if (!fs.existsSync(options.specDir)) {\n logWarn(\n `openspec directory not found: ${path.relative(options.srcDir, options.specDir)} — skipping page generation`,\n )\n const retained = cleanupPreviousManifest(options.absoluteOutDir)\n if (retained.length > 0 || fs.existsSync(options.absoluteOutDir)) {\n writeManifest(retained, options.absoluteOutDir)\n }\n return false\n }\n\n // Phase 1: read sources and render everything in memory. A failure here\n // leaves the last successful output untouched.\n let files: OutputFile[]\n try {\n files = renderAllPages(options)\n } catch (err) {\n logError(`Failed to process openspec directory \"${options.specDir}\": ${String(err)}`)\n return false\n }\n\n // Phase 2: destructive cleanup of the previous output, now that the\n // replacement generation is complete and safe to write.\n const retained = cleanupPreviousManifest(options.absoluteOutDir)\n\n // Phase 3: write the new pages. The self-managed .gitignore marker goes\n // first so even an interrupted run leaves the output recognizable as\n // generated output — never mistaken for the openspec source.\n try {\n writeFile(path.join(options.absoluteOutDir, '.gitignore'), GITIGNORE_CONTENT)\n for (const file of files) {\n writeFile(path.join(options.absoluteOutDir, file.rel), file.content)\n }\n writeManifest([...files.map((f) => f.rel), ...retained], options.absoluteOutDir)\n } catch (err) {\n logError(`Failed to write openspec pages: ${String(err)}`)\n return false\n }\n\n logInfo(`Generated docs from ${options.specDir}: ${files.length} file(s)`)\n return true\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { NavItem, SidebarItem } from '../types.js'\nimport { logWarn } from './logger.js'\nimport { humanizeLabel, readOpenSpecFolder } from './reader.js'\nimport { specTitle } from './markdown.js'\n\nfunction changeItems(change: { name: string; archiveFolderName?: string; artifacts: string[] }, 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 logWarn(\n `openspec directory not found: ${path.relative(process.cwd(), path.resolve(specDir))} — skipping sidebar generation`,\n )\n return []\n }\n const folder = readOpenSpecFolder(specDir)\n const groups: SidebarItem[] = []\n\n groups.push({\n text: 'Specifications',\n collapsed: false,\n items: [\n { text: 'Overview', link: `/${outDir}/specs/` },\n ...folder.specs.map((s) => ({ text: specTitle(s), link: `/${outDir}/specs/${s.name}/` })),\n ],\n })\n\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 if (folder.archivedChanges.length > 0) {\n groups.push({\n text: 'Archive',\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 logWarn(\n `openspec directory not found: ${path.relative(process.cwd(), path.resolve(specDir))} — skipping nav generation`,\n )\n return null\n }\n return {\n text: options.text ?? 'Docs',\n link: `/${outDir}/`,\n }\n}\n","import path from 'node:path'\nimport type { ViteDevServer } from 'vite'\nimport type { ResolvedOptions } from './options.js'\nimport { generatePages } from './generator.js'\nimport { readOpenSpecFolder } from './reader.js'\nimport { generateOpenSpecSidebar } from './navigation.js'\nimport { invalidateGeneratedDestinations } from './watch.js'\n\n/**\n * Compact fingerprint of everything that feeds the sidebar and nav:\n * spec and change names, titles, dates, and artifact lists. Comparing\n * signatures before and after an edit tells us whether the navigation\n * config changed and the dev server needs a full restart.\n */\nexport function readNavigationSignature(options: ResolvedOptions): string {\n try {\n const folder = readOpenSpecFolder(options.specDir)\n return JSON.stringify({\n specs: folder.specs.map((s) => [s.name, s.title ?? null]),\n changes: folder.changes.map((c) => [c.name, c.title ?? null, c.createdDate ?? null, c.artifacts]),\n archived: folder.archivedChanges.map((c) => [c.name, c.title ?? null, c.archivedDate ?? null, c.artifacts]),\n })\n } catch {\n return 'unreadable'\n }\n}\n\n/**\n * Updates the sidebar and nav entries inside the in-memory VitePress\n * theme config that `withOpenSpec()` created. `server.restart(true)` only\n * re-creates Vite from the already-resolved inline configuration, so it\n * never re-runs `withOpenSpec()`; mutating the live themeConfig object\n * before the restart is what actually refreshes the navigation.\n *\n * The live theme config lives on the VitePress `SiteConfig` object exposed\n * as `server.config.vitepress.site.themeConfig` (VitePress resolves its\n * site config before creating Vite). The flat `server.config.vitepress`\n * object only exists in unit tests that build a Vite config manually, so\n * both locations are supported.\n */\nexport function updateNavigationInMemory(\n options: ResolvedOptions,\n server: ViteDevServer,\n ownsSidebarEntry: boolean,\n): void {\n if (!ownsSidebarEntry) return\n const vp = (server.config as unknown as {\n vitepress?: {\n site?: { themeConfig?: Record<string, unknown> }\n themeConfig?: Record<string, unknown>\n }\n }).vitepress\n const themeConfig = vp?.site?.themeConfig ?? vp?.themeConfig\n if (!themeConfig) return\n const sidebarKey = `/${options.outDir}/`\n const items = generateOpenSpecSidebar(options.specDir, { outDir: options.outDir })\n const sidebar = (themeConfig.sidebar ?? {}) as Record<string, unknown>\n if (items.length > 0) {\n sidebar[sidebarKey] = items\n themeConfig.sidebar = sidebar\n } else {\n delete sidebar[sidebarKey]\n themeConfig.sidebar = sidebar\n }\n}\n\nexport function createScheduler() {\n let timer: ReturnType<typeof setTimeout> | undefined\n return {\n schedule(options: ResolvedOptions, server: ViteDevServer): void {\n // Debounce: editors and archive operations often emit event bursts\n if (timer) clearTimeout(timer)\n timer = setTimeout(() => {\n timer = undefined\n generatePages(options)\n invalidateGeneratedDestinations(options.absoluteOutDir)\n server.ws.send({ type: 'full-reload' })\n }, 100)\n },\n cancel(): void {\n if (timer) {\n clearTimeout(timer)\n timer = undefined\n }\n },\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { Plugin } from 'vite'\nimport type { ResolvedOptions } from './lib/options.js'\nimport type { OpenSpecPluginOptions, WithOpenSpecOptions } from './types.js'\nimport { PLUGIN_NAME, logWarn } from './lib/logger.js'\nimport { resolveOptions } from './lib/options.js'\nimport { generatePages } from './lib/generator.js'\nimport { openspecNav, generateOpenSpecSidebar } from './lib/navigation.js'\nimport { isSourceArtifactEvent } from './lib/watch.js'\nimport { createScheduler, readNavigationSignature, updateNavigationInMemory } from './lib/dev-server.js'\nimport { detectSrcDir, detectVitePressRoot } from './lib/detect.js'\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. In most cases `withOpenSpec()` (which calls this\n * internally) is the simpler integration point.\n *\n * @returns true when pages were written; false when generation was skipped\n * (missing or unreadable source, ambiguous source-directory detection) or\n * failed.\n * @throws if `outDir` is not a relative path inside `srcDir` (absolute,\n * traversal, or empty).\n */\nexport function generateOpenSpecPages(userOptions: OpenSpecPluginOptions = {}): boolean {\n // When source-directory detection is ambiguous (multiple .vitepress\n // folders at the same level), detectSrcDir has already warned; skip\n // generation instead of writing into the common parent.\n const detectedSrcDir = userOptions.srcDir ?? detectSrcDir(process.cwd())\n if (!detectedSrcDir) return false\n const options = resolveOptions(userOptions, detectedSrcDir)\n return generatePages(options)\n}\n\n/**\n * Vite plugin that regenerates the openspec documentation pages whenever a\n * file inside the openspec/ directory changes. This makes `vitepress dev`\n * pick up spec edits without a manual restart.\n *\n * For the pages to be available on the first build (including CI), the pages\n * are generated once in `configResolved`. When using `withOpenSpec()` this\n * plugin is wired up automatically.\n */\nexport function openspec(userOptions: OpenSpecPluginOptions = {}): Plugin {\n let resolvedOptions: ResolvedOptions | undefined\n let ownsSidebarEntry = false\n let detachListeners: (() => void) | undefined\n\n return {\n name: PLUGIN_NAME,\n enforce: 'pre',\n\n configResolved(resolvedConfig) {\n detachListeners?.()\n const vpConfig = (resolvedConfig as unknown as { vitepress?: { srcDir?: string } }).vitepress\n const srcDir =\n userOptions.srcDir ?? vpConfig?.srcDir ?? resolvedConfig.root ?? process.cwd()\n try {\n resolvedOptions = resolveOptions(userOptions, srcDir)\n } catch (err) {\n logWarn(String(err))\n return\n }\n if (!fs.existsSync(resolvedOptions.specDir)) {\n logWarn(\n `openspec directory not found: ${resolvedOptions.specDir} — skipping page generation`,\n )\n // Still run generatePages so previously generated pages recorded in\n // the manifest are cleaned up when the source directory disappears.\n generatePages(resolvedOptions)\n resolvedOptions = undefined\n return\n }\n generatePages(resolvedOptions)\n },\n\n configureServer(server) {\n if (!resolvedOptions || !fs.existsSync(resolvedOptions.specDir)) return\n const options = resolvedOptions\n // Use Vite's own watcher: it is supported on all Node versions and\n // platforms declared by this package (unlike recursive fs.watch).\n // Ensure the openspec directory is watched even when it lives outside\n // the Vite root (the documented docs/ + openspec/ layout).\n server.watcher.add(options.specDir)\n const scheduler = createScheduler()\n let navigationSignature = readNavigationSignature(options)\n const onWatchEvent = (event: 'change' | 'add' | 'unlink', file: string) => {\n const absFile = path.resolve(file)\n if (!isSourceArtifactEvent(options, absFile)) return\n // Structural changes (files added or removed) and metadata edits\n // (.openspec.yaml, spec/change titles) also alter the sidebar and\n // nav, which are derived from the config; a full server restart\n // regenerates both pages and navigation. Plain content edits take\n // the fast regenerate+reload path unless a title changed.\n const signature = readNavigationSignature(options)\n const affectsNavigation = event !== 'change' || signature !== navigationSignature\n if (affectsNavigation) {\n scheduler.cancel()\n updateNavigationInMemory(options, server, ownsSidebarEntry)\n navigationSignature = signature\n server.restart(true)\n } else {\n scheduler.schedule(options, server)\n }\n }\n const onChange = (f: string) => onWatchEvent('change', f)\n const onAdd = (f: string) => onWatchEvent('add', f)\n const onUnlink = (f: string) => onWatchEvent('unlink', f)\n server.watcher.on('change', onChange)\n server.watcher.on('add', onAdd)\n server.watcher.on('unlink', onUnlink)\n // Unregister listeners when the dev server shuts down. Closing the\n // shared chokidar instance would break Vite itself, so we only detach.\n // The same detach runs from closeBundle so consecutive builds\n // (e.g. `vitepress build --watch` or quick relaunches) cannot\n // accumulate duplicate listeners.\n detachListeners = () => {\n scheduler.cancel()\n server.watcher.off('change', onChange)\n server.watcher.off('add', onAdd)\n server.watcher.off('unlink', onUnlink)\n server.httpServer?.removeListener('close', detachListeners!)\n detachListeners = undefined\n }\n server.httpServer?.once('close', detachListeners)\n },\n\n closeBundle() {\n detachListeners?.()\n detachListeners = undefined\n },\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 * When the VitePress source directory cannot be detected unambiguously\n * (multiple `.vitepress` folders at the same level), a warning is emitted and\n * the config is returned with only the sidebar shape normalized — nothing is\n * generated or injected.\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 * @throws if `outDir` is not a relative path inside `srcDir` (absolute, traversal, or empty).\n */\nexport function withOpenSpec<T extends Record<string, unknown>>(\n config: T,\n options: WithOpenSpecOptions = {},\n): T {\n const cwd = process.cwd()\n // Resolve a relative srcDir from the wrapped config the same way\n // VitePress resolves it: against the detected project root.\n const configSrcDir =\n typeof config.srcDir === 'string' && config.srcDir\n ? path.resolve(detectVitePressRoot(cwd), config.srcDir)\n : undefined\n const detectedSrcDir = options.srcDir ?? configSrcDir ?? detectSrcDir(cwd)\n const result = { ...config } as Record<string, unknown>\n const themeConfig = (result.themeConfig ?? {}) as Record<string, unknown>\n // Normalize an array-based (single-sidebar) config to the object form so\n // the injected section always lands under its route key — also when\n // generation is skipped below.\n if (Array.isArray(themeConfig.sidebar)) {\n themeConfig.sidebar = { '/': themeConfig.sidebar }\n }\n result.themeConfig = themeConfig\n // When source-directory detection is ambiguous, detectSrcDir has already\n // warned; skip generation and integration instead of writing into the\n // common parent of multiple VitePress sites.\n if (detectedSrcDir === undefined) return result as T\n\n let resolved: ResolvedOptions\n try {\n resolved = resolveOptions(options, detectedSrcDir)\n } catch (err) {\n logWarn(String(err))\n return result as T\n }\n\n const generated = generatePages(resolved)\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({ ...options })] }\n\n // --- Nav ---\n if (generated && options.nav !== false) {\n const navEntry = openspecNav(resolved.specDir, {\n outDir: resolved.outDir,\n text: options.navText,\n })\n const existingNav = (themeConfig.nav as unknown[]) ?? []\n themeConfig.nav = navEntry ? [navEntry, ...existingNav] : existingNav\n }\n\n // --- Sidebar ---\n const sidebarKey = `/${resolved.outDir}/`\n const existingSidebar = (themeConfig.sidebar ?? {}) as Record<string, unknown>\n // The plugin only owns (and the watcher only updates) an entry it created\n // itself; a pre-existing custom entry for this route is preserved as-is.\n const pluginOwnsSidebarEntry = generated && options.sidebar !== false && !existingSidebar[sidebarKey]\n if (pluginOwnsSidebarEntry) {\n const items = generateOpenSpecSidebar(resolved.specDir, { outDir: resolved.outDir })\n if (items.length > 0) {\n themeConfig.sidebar = { ...existingSidebar, [sidebarKey]: items }\n }\n }\n\n result.themeConfig = themeConfig\n return result as T\n}\n\nexport default openspec\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/logger.ts","../src/lib/detect.ts","../src/lib/options.ts","../src/lib/watch.ts","../src/lib/reader.ts","../src/lib/links.ts","../src/lib/markdown.ts","../src/lib/pages.ts","../src/lib/generator.ts","../src/lib/navigation.ts","../src/types.ts","../src/lib/dev-server.ts","../src/plugin.ts"],"names":["pc","path","fs","parent","yamlLoad","prefix","retained"],"mappings":"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","file":"index.cjs","sourcesContent":["import pc from 'picocolors'\n\nexport const PLUGIN_NAME = 'vitepress-plugin-openspec'\n\nfunction prefix(color: (s: string) => string): string {\n return pc.bold(color(`[${PLUGIN_NAME}]`))\n}\n\nexport function logWarn(message: string): void {\n console.warn(`${prefix(pc.yellow)} ${message}`)\n}\n\nexport function logInfo(message: string): void {\n console.log(`${prefix(pc.cyan)} ${message}`)\n}\n\nexport function logError(message: string): void {\n console.error(`${prefix(pc.red)} ${message}`)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { PLUGIN_NAME, logWarn } from './logger.js'\n\nconst GENERATED_MARKER = '# Generated by vitepress-plugin-openspec'\n\n/**\n * Returns how strongly a directory looks like a real openspec/ source folder.\n * - 'strong': unambiguous markers (project.md, config file, spec.md, change yaml)\n * - 'weak': only an archive layout — valid for real sources that contain only\n * archived changes, but also matches unmarked generated output, so it is\n * only used when no strong candidate exists anywhere up the tree\n * - false: generated output (identified via its generated .gitignore marker)\n * or no openspec structure at all\n */\nexport function looksLikeOpenSpecDir(dir: string): 'strong' | 'weak' | false {\n const gitignore = path.join(dir, '.gitignore')\n if (fs.existsSync(gitignore)) {\n try {\n if (fs.readFileSync(gitignore, 'utf-8').startsWith(GENERATED_MARKER)) return false\n } catch {\n // ignore unreadable files\n }\n }\n if (fs.existsSync(path.join(dir, 'project.md'))) return 'strong'\n if (fs.existsSync(path.join(dir, 'config.yaml')) || fs.existsSync(path.join(dir, 'config.yml'))) return 'strong'\n const changesDir = path.join(dir, 'changes')\n if (fs.existsSync(changesDir)) {\n try {\n for (const entry of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!entry.isDirectory() && !entry.name.endsWith('.yaml')) continue\n const marker = path.join(changesDir, entry.name, '.openspec.yaml')\n const yaml = path.join(changesDir, `${entry.name}.yaml`)\n if (fs.existsSync(marker) || fs.existsSync(yaml)) return 'strong'\n }\n } catch {\n // ignore unreadable directories\n }\n }\n const specsDir = path.join(dir, 'specs')\n if (fs.existsSync(specsDir)) {\n try {\n for (const entry of fs.readdirSync(specsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n if (fs.existsSync(path.join(specsDir, entry.name, 'spec.md'))) return 'strong'\n }\n } catch {\n // ignore unreadable directories\n }\n }\n const archiveDir = path.join(changesDir, 'archive')\n if (fs.existsSync(archiveDir)) {\n try {\n if (fs.readdirSync(archiveDir, { withFileTypes: true }).some((e) => e.isDirectory())) return 'weak'\n } catch {\n // ignore unreadable directories\n }\n }\n return false\n}\n\n/**\n * Walks up from `start` looking for a real `openspec/` folder. The nearest\n * valid source wins: an archive-only (weak) source found on the way up is\n * preferred over any strong source further up the tree, while unmarked\n * generated output at the output location is skipped as interrupted output.\n * This keeps the plugin zero-config: users do not need to pass `specDir` when\n * `openspec/` lives at the project root, even when VitePress is invoked from\n * a subfolder.\n */\nexport function findOpenSpecDir(start: string, generatedOutputDir?: string): string | undefined {\n let current = path.resolve(start)\n for (;;) {\n const candidate = path.join(current, 'openspec')\n if (fs.existsSync(candidate)) {\n const match = looksLikeOpenSpecDir(candidate)\n // A weak match at the generated output location is unmarked output\n // from an interrupted run — keep searching for the real source.\n if (match === 'weak' && generatedOutputDir && realPath(candidate) === realPath(generatedOutputDir)) {\n const parent = path.dirname(current)\n if (parent === current) return undefined\n current = parent\n continue\n }\n if (match === 'strong' || match === 'weak') return candidate\n }\n const parent = path.dirname(current)\n if (parent === current) return undefined\n current = parent\n }\n}\n\n/**\n * Resolves a path to its canonical form, following symlinks of the deepest\n * existing ancestor so containment checks are not defeated by symlinked\n * output directories.\n */\nexport function realPath(target: string): string {\n let current = path.resolve(target)\n const suffix: string[] = []\n for (;;) {\n if (fs.existsSync(current)) break\n const parent = path.dirname(current)\n if (parent === current) return path.resolve(target)\n suffix.unshift(path.basename(current))\n current = parent\n }\n try {\n current = fs.realpathSync(current)\n } catch {\n return path.resolve(target)\n }\n return suffix.length ? path.join(current, ...suffix) : current\n}\n\nconst srcDirCache = new Map<string, string | undefined>()\n\n/**\n * Detects the VitePress source directory (the folder containing `.vitepress`)\n * by checking the current working directory and its first-level subdirectories\n * (e.g. `docs/.vitepress`). Falls back to the working directory itself.\n *\n * Cached per working directory so repeated calls (e.g. from both\n * `withOpenSpec` and `generateOpenSpecPages` during one config load) do not\n * re-run detection or repeat ambiguity warnings.\n */\nexport function detectSrcDir(cwd: string): string | undefined {\n const key = path.resolve(cwd)\n if (srcDirCache.has(key)) return srcDirCache.get(key)\n const result = resolveSrcDir(key)\n srcDirCache.set(key, result)\n return result\n}\n\nfunction resolveSrcDir(cwd: string): string | undefined {\n if (path.basename(cwd) === '.vitepress') return path.dirname(cwd)\n if (fs.existsSync(path.join(cwd, '.vitepress'))) return cwd\n const matches: string[] = []\n try {\n for (const entry of fs.readdirSync(cwd, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const subDir = path.join(cwd, entry.name)\n if (fs.existsSync(path.join(subDir, '.vitepress'))) matches.push(subDir)\n }\n } catch {\n // ignore unreadable directories\n }\n if (matches.length === 1) return matches[0]\n if (matches.length > 1) {\n const docsMatch = matches.find((m) => path.basename(m) === 'docs')\n if (docsMatch) return docsMatch\n logWarn(\n `Multiple VitePress source directories found (${matches\n .map((m) => path.relative(cwd, m))\n .join(', ')}) — pass an explicit \\`srcDir\\` option. Skipping page generation.`,\n )\n return undefined\n }\n return cwd\n}\n\n/**\n * Detects the VitePress project root — the directory containing the\n * `.vitepress` folder — so a relative `srcDir` from the wrapped config can be\n * resolved the same way VitePress resolves it.\n */\nexport function detectVitePressRoot(cwd: string): string {\n const srcDir = detectSrcDir(cwd)\n return srcDir && fs.existsSync(path.join(srcDir, '.vitepress')) ? srcDir : cwd\n}\n","import path from 'node:path'\nimport type { OpenSpecPluginOptions } from '../types.js'\nimport { detectSrcDir, findOpenSpecDir } from './detect.js'\n\n/**\n * Fully resolved and validated plugin options.\n */\nexport interface ResolvedOptions {\n /** Absolute path to the openspec/ directory */\n specDir: string\n /** Output directory name relative to srcDir (e.g. \"openspec\") */\n outDir: string\n /** Absolute VitePress source directory */\n srcDir: string\n /** Absolute output directory inside srcDir */\n absoluteOutDir: string\n}\n\n/**\n * Centralizes default resolution for all plugin entry points so\n * `generateOpenSpecPages()`, `openspec()` and `withOpenSpec()` behave\n * identically.\n *\n * Defaults are zero-config: `srcDir` falls back to the auto-detected\n * VitePress source directory (the folder containing `.vitepress`), and\n * `specDir` falls back to the nearest ancestor `openspec/` folder,\n * skipping generated output recognized by its marker.\n *\n * @throws if `outDir` is not a relative path inside `srcDir`.\n */\nexport function resolveOptions(\n userOptions: OpenSpecPluginOptions = {},\n fallbackSrcDir?: string,\n): ResolvedOptions {\n // Normalize Windows-style separators so traversal variants like\n // \"nested\\\\..\\\\..\\\\outside\" cannot bypass the containment check.\n const outDir = (userOptions.outDir ?? 'openspec').replace(/\\\\/g, '/')\n if (path.isAbsolute(outDir) || outDir === '' || outDir === '.' || outDir === '..') {\n throw new Error(\n `[vitepress-plugin-openspec] Invalid outDir \"${outDir}\": it must be a relative path inside the VitePress srcDir.`,\n )\n }\n const srcDir = userOptions.srcDir ?? fallbackSrcDir ?? detectSrcDir(process.cwd()) ?? process.cwd()\n const absoluteSrcDir = path.resolve(srcDir)\n const absoluteOutDir = path.resolve(absoluteSrcDir, outDir)\n const rel = path.relative(absoluteSrcDir, absoluteOutDir)\n if (rel.startsWith('..') || path.isAbsolute(rel) || rel === '') {\n throw new Error(\n `[vitepress-plugin-openspec] Invalid outDir \"${outDir}\": it resolves outside the VitePress srcDir.`,\n )\n }\n const specDir = userOptions.specDir ?? findOpenSpecDir(process.cwd(), absoluteOutDir) ?? './openspec'\n return {\n specDir: path.resolve(specDir),\n outDir,\n srcDir: absoluteSrcDir,\n absoluteOutDir,\n }\n}\n","import path from 'node:path'\nimport type { ResolvedOptions } from './options.js'\nimport { readManifest } from './generator.js'\n\n// Basenames of files the plugin always writes into the output tree.\nconst ALWAYS_GENERATED_BASENAMES = new Set(['index.md', '.gitignore', '.openspec-manifest.json'])\n// Artifact copies the plugin writes when the output tree is distinct\n// from the openspec source tree.\nconst ARTIFACT_BASENAMES = new Set(['proposal.md', 'design.md', 'tasks.md'])\n\nconst generatedDestCache = new Map<string, Set<string>>()\n\n/**\n * Resolved absolute destinations of all files recorded in the previous\n * run's manifest — i.e. paths the plugin itself wrote. Only these exact\n * destinations count as generated, never a basename heuristic, so real\n * source artifacts that live inside the output tree remain watchable.\n */\nfunction generatedDestinations(absoluteOutDir: string): Set<string> {\n const cached = generatedDestCache.get(absoluteOutDir)\n if (cached) return cached\n const set = new Set<string>()\n for (const entry of readManifest(absoluteOutDir)) {\n set.add(path.resolve(absoluteOutDir, entry))\n }\n generatedDestCache.set(absoluteOutDir, set)\n return set\n}\n\n/**\n * Invalidates the cached manifest destinations after a regeneration wrote\n * a new manifest.\n */\nexport function invalidateGeneratedDestinations(absoluteOutDir: string): void {\n generatedDestCache.delete(absoluteOutDir)\n}\n\nfunction isInside(parent: string, child: string): boolean {\n const rel = path.relative(parent, child)\n return !(rel.startsWith('..') || path.isAbsolute(rel))\n}\n\n/**\n * Layout classification for the overlapping specDir/outDir cases:\n * - 'equal': specDir and outDir are the same directory\n * - 'out-inside-spec': outDir is a proper child of specDir\n * - 'spec-inside-out': specDir is a proper child of outDir\n * - 'disjoint': no overlap\n */\nexport type LayoutRelation = 'equal' | 'out-inside-spec' | 'spec-inside-out' | 'disjoint'\n\nexport function classifyLayout(options: ResolvedOptions): LayoutRelation {\n if (options.specDir === options.absoluteOutDir) return 'equal'\n if (isInside(options.specDir, options.absoluteOutDir)) return 'out-inside-spec'\n if (isInside(options.absoluteOutDir, options.specDir)) return 'spec-inside-out'\n return 'disjoint'\n}\n\n/**\n * Whether a file inside the output tree was written by this plugin (as\n * opposed to an openspec source artifact that happens to live in the same\n * tree when specDir and outDir overlap).\n *\n * Layout rules (generated destinations never coincide with source files):\n * - 'equal': the shared tree only receives index.md/.gitignore/manifest\n * from the plugin; artifact-named files are sources.\n * - 'out-inside-spec' / 'disjoint': the plugin writes artifact copies into\n * the output tree; every known basename inside it is generated.\n * - 'spec-inside-out': source files live inside the output tree; files\n * inside specDir are sources, only files outside it are generated.\n */\nexport function isPluginGeneratedFile(options: ResolvedOptions, absFile: string): boolean {\n if (!isInside(options.absoluteOutDir, absFile)) return false\n // Only exact destinations recorded in the generation manifest are\n // generated output — never a basename heuristic. This keeps real source\n // artifacts inside an overlapping output tree watchable.\n if (generatedDestinations(options.absoluteOutDir).has(path.resolve(absFile))) return true\n const base = path.basename(absFile)\n switch (classifyLayout(options)) {\n case 'equal':\n return ALWAYS_GENERATED_BASENAMES.has(base)\n case 'out-inside-spec':\n // The output tree is nested inside specDir, so a basename match can\n // hit real source files too. Only the exact destinations recorded\n // in the manifest (checked above) plus the always-generated\n // top-level markers count as plugin output.\n return ALWAYS_GENERATED_BASENAMES.has(base) && !isInside(options.specDir, absFile)\n case 'disjoint':\n return ALWAYS_GENERATED_BASENAMES.has(base) || ARTIFACT_BASENAMES.has(base)\n case 'spec-inside-out':\n return !isInside(options.specDir, absFile) &&\n (ALWAYS_GENERATED_BASENAMES.has(base) || ARTIFACT_BASENAMES.has(base))\n }\n}\n\n/**\n * Whether a watch event for this file should trigger regeneration of the\n * openspec pages. True for openspec source files (including\n * `.openspec.yaml`), false for files the plugin itself generated.\n */\nexport function isSourceArtifactEvent(options: ResolvedOptions, absFile: string): boolean {\n if (!isInside(options.specDir, absFile)) return false\n return !isPluginGeneratedFile(options, absFile)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { load as yamlLoad } from 'js-yaml'\nimport type { CapabilitySpec, Change, ChangeArtifact, OpenSpecFolder } from '../types.js'\n\nconst ARTIFACT_NAMES: ChangeArtifact[] = ['proposal', 'design', 'tasks']\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\nexport function 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 return ARTIFACT_NAMES.filter((name) => fs.existsSync(path.join(dir, `${name}.md`)))\n}\n\nfunction isDirectory(dir: string, name: string): boolean {\n return fs.existsSync(path.join(dir, name, '.openspec.yaml'))\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 (!isDirectory(changeDir, '.')) 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 const meta = readOpenSpecYaml(changeDir)\n const match = entry.name.match(/^(\\d{4}-\\d{2}-\\d{2})-(.+)$/)\n archivedChanges.push({\n name: match?.[2] ?? entry.name,\n title: meta.title ? String(meta.title) : undefined,\n dir: changeDir,\n artifacts: readArtifacts(changeDir),\n createdDate: formatDate(meta.created),\n archivedDate: match?.[1],\n archiveFolderName: entry.name,\n })\n }\n }\n\n return { dir: resolved, specs, changes, archivedChanges }\n}\n","import path from 'node:path'\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 * Links that point outside the openspec root, absolute paths, HTTP URLs, and\n * anchor-only links are left unchanged.\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 return content.replace(\n /(\\[[^\\]]*\\])\\(([^)]+)\\)/g,\n (_match, linkText: string, urlPart: string) => {\n const titleMatch = urlPart.match(/^(.+?)(\\s+[\"'][^\"']*[\"'])?\\s*$/)\n if (!titleMatch) return _match\n const rawUrl = titleMatch[1].trim()\n const title = titleMatch[2] ?? ''\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 const hashIdx = rawUrl.indexOf('#')\n const urlWithoutFragment = hashIdx >= 0 ? rawUrl.slice(0, hashIdx) : rawUrl\n const fragment = hashIdx >= 0 ? rawUrl.slice(hashIdx) : ''\n if (!urlWithoutFragment) {\n return _match\n }\n const resolvedPath = path.resolve(srcDir, urlWithoutFragment)\n const relToOpenspec = path.relative(openspecRootDir, resolvedPath)\n if (relToOpenspec.startsWith('..') || path.isAbsolute(relToOpenspec)) {\n return _match\n }\n const vitePath = relToOpenspec.replace(/\\.md$/, '').replace(/\\\\/g, '/')\n const absoluteLink = `/${outDir}/${vitePath}${fragment}`\n return `${linkText}(${absoluteLink}${title})`\n },\n )\n}\n","import type { CapabilitySpec } from '../types.js'\nimport { humanizeLabel } from './reader.js'\n\nexport function 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, '\\\\$1')\n}\n\nexport function 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 return stripped.replace(/\\n{3,}/g, '\\n\\n')\n}\n\nexport function transformScenarios(content: string): string {\n const lines = content.split('\\n')\n const result: string[] = []\n let inScenario = false\n for (const line of lines) {\n const scenarioMatch = line.match(/^#### Scenario: (.+)$/)\n const isHeading = /^#{1,6} /.test(line)\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 if (inScenario) result.push(':::')\n return result.join('\\n')\n}\n\nexport function specTitle(spec: CapabilitySpec): string {\n return spec.title ?? humanizeLabel(spec.name)\n}\n","import type { CapabilitySpec, Change, OpenSpecFolder } from '../types.js'\nimport { humanizeLabel } from './reader.js'\nimport { extractSpecDescription, specTitle, stripDeltaMarkers, transformScenarios } from './markdown.js'\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(`# ${specTitle(spec)}`)\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(`- [${specTitle(spec)}](/${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 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 if (folder.archivedChanges.length > 0) {\n lines.push('')\n lines.push('## Archive')\n lines.push('')\n for (const change of folder.archivedChanges) {\n const date = change.archivedDate ? ` *(archived: ${change.archivedDate})*` : ''\n lines.push(\n `- [${change.title ?? humanizeLabel(change.name)}](/${outDir}/changes/archive/${change.archiveFolderName}/)${date}`,\n )\n }\n }\n lines.push('')\n return lines.join('\\n')\n}\n\n/**\n * Generates the root index page of the openspec documentation section.\n */\nexport function generateRootIndexPage(outDir: string): string {\n return [\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}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { invalidateGeneratedDestinations } from './watch.js'\nimport type { Change } from '../types.js'\nimport type { ResolvedOptions } from './options.js'\nimport { logError, logInfo, logWarn } from './logger.js'\nimport { readOpenSpecFolder } from './reader.js'\nimport { rewriteRelativeLinks } from './links.js'\nimport {\n generateChangeIndexPage,\n generateChangesIndexPage,\n generateRootIndexPage,\n generateSpecPage,\n generateSpecsIndexPage,\n} from './pages.js'\n\nexport const MANIFEST_FILE = '.openspec-manifest.json'\nconst GITIGNORE_CONTENT = '# Generated by vitepress-plugin-openspec — do not commit generated files.\\n*\\n!.gitignore\\n'\n\ninterface OutputFile {\n /** Path relative to absoluteOutDir, using forward slashes */\n rel: string\n content: string\n}\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 toRel(absoluteOutDir: string, filePath: string): string {\n return path.relative(absoluteOutDir, filePath).split(path.sep).join('/')\n}\n\nfunction pruneEmptyDirs(rootDir: string, startDir: string): void {\n let dir = startDir\n while (dir.startsWith(rootDir) && dir !== rootDir) {\n try {\n if (fs.readdirSync(dir).length > 0) break\n fs.rmdirSync(dir)\n } catch {\n break\n }\n dir = path.dirname(dir)\n }\n}\n\n/**\n * Reads the previous run's manifest and deletes all recorded files.\n * Runs only after the replacement generation has been fully read and\n * rendered in memory, so a failing source read never destroys the last\n * successful output. Because cleanup precedes writing the new files, a\n * stale entry can never resolve to a freshly written page, even for\n * case-only renames on case-insensitive filesystems.\n *\n * @returns entries whose deletion failed; they are retained in the next\n * manifest so cleanup retries instead of forgetting them.\n */\nfunction cleanupPreviousManifest(rootDir: string): string[] {\n const manifestPath = path.join(rootDir, MANIFEST_FILE)\n if (!fs.existsSync(manifestPath)) return []\n let previous: string[] = []\n try {\n const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as unknown\n if (Array.isArray(parsed)) previous = parsed.filter((f): f is string => typeof f === 'string')\n } catch {\n // Unreadable manifest: treat as empty\n return []\n }\n const retained: string[] = []\n for (const entry of previous) {\n const entryPath = path.resolve(rootDir, entry)\n const rel = path.relative(rootDir, entryPath)\n if (rel.startsWith('..') || path.isAbsolute(rel)) continue\n try {\n if (fs.existsSync(entryPath)) {\n fs.rmSync(entryPath)\n pruneEmptyDirs(rootDir, path.dirname(entryPath))\n }\n } catch {\n // Deletion failed (e.g. locked file): retry on the next run\n retained.push(entry)\n }\n }\n return retained\n}\n\nexport function readManifest(rootDir: string): string[] {\n try {\n const parsed = JSON.parse(fs.readFileSync(path.join(rootDir, MANIFEST_FILE), 'utf-8')) as unknown\n if (Array.isArray(parsed)) return parsed.filter((f): f is string => typeof f === 'string')\n } catch {\n // Unreadable or missing manifest: treat as empty\n }\n return []\n}\n\nfunction writeManifest(files: string[], rootDir: string): void {\n const manifestPath = path.join(rootDir, MANIFEST_FILE)\n try {\n writeFile(manifestPath, JSON.stringify(files, null, 2))\n invalidateGeneratedDestinations(rootDir)\n } catch {\n // Best-effort: never fail generation because of the manifest\n }\n}\n\nfunction renderChangePages(\n change: Change,\n options: ResolvedOptions,\n isArchived: boolean,\n): OutputFile[] {\n const subPath = isArchived\n ? path.join('changes', 'archive', change.archiveFolderName ?? change.name)\n : path.join('changes', change.name)\n const changeOutDir = path.join(options.absoluteOutDir, subPath)\n const files: OutputFile[] = []\n\n files.push({\n rel: toRel(options.absoluteOutDir, path.join(changeOutDir, 'index.md')),\n content: generateChangeIndexPage(change, options.outDir),\n })\n\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 // When specDir and outDir overlap, never copy a file onto itself\n if (path.resolve(srcFile) === path.resolve(destFile)) continue\n const content = fs.readFileSync(srcFile, 'utf-8')\n files.push({\n rel: toRel(options.absoluteOutDir, destFile),\n content: rewriteRelativeLinks(content, srcFile, options.specDir, options.outDir),\n })\n }\n return files\n}\n\n/**\n * Reads the openspec directory and renders every output page into memory.\n * All source file access happens here, before any destructive step, so\n * an inconsistent source tree cannot destroy the previous output.\n */\nfunction renderAllPages(options: ResolvedOptions): OutputFile[] {\n const folder = readOpenSpecFolder(options.specDir)\n const files: OutputFile[] = []\n\n for (const spec of folder.specs) {\n const dest = path.join(options.absoluteOutDir, 'specs', spec.name, 'index.md')\n files.push({ rel: toRel(options.absoluteOutDir, dest), content: generateSpecPage(spec) })\n }\n files.push({\n rel: 'specs/index.md',\n content: generateSpecsIndexPage(folder.specs, options.outDir),\n })\n\n for (const change of folder.changes) {\n files.push(...renderChangePages(change, options, false))\n }\n for (const change of folder.archivedChanges) {\n files.push(...renderChangePages(change, options, true))\n }\n\n files.push({\n rel: 'changes/index.md',\n content: generateChangesIndexPage(folder, options.outDir),\n })\n files.push({\n rel: 'index.md',\n content: generateRootIndexPage(options.outDir),\n })\n\n return files\n}\n\n/**\n * Synchronously generates all VitePress Markdown pages from the openspec/\n * directory and writes them to disk, removing stale output from previous runs.\n *\n * @returns true when pages were written; false when generation was skipped\n * (missing or unreadable source) or failed.\n */\nexport function generatePages(options: ResolvedOptions): boolean {\n // Remove stale output from the previous run even when the source\n // directory has disappeared, so published pages do not linger forever.\n if (!fs.existsSync(options.specDir)) {\n logWarn(\n `openspec directory not found: ${path.relative(options.srcDir, options.specDir)} — skipping page generation`,\n )\n const retained = cleanupPreviousManifest(options.absoluteOutDir)\n if (retained.length > 0 || fs.existsSync(options.absoluteOutDir)) {\n writeManifest(retained, options.absoluteOutDir)\n }\n return false\n }\n\n // Phase 1: read sources and render everything in memory. A failure here\n // leaves the last successful output untouched.\n let files: OutputFile[]\n try {\n files = renderAllPages(options)\n } catch (err) {\n logError(`Failed to process openspec directory \"${options.specDir}\": ${String(err)}`)\n return false\n }\n\n // Phase 2: destructive cleanup of the previous output, now that the\n // replacement generation is complete and safe to write.\n const retained = cleanupPreviousManifest(options.absoluteOutDir)\n\n // Phase 3: write the new pages. The self-managed .gitignore marker goes\n // first so even an interrupted run leaves the output recognizable as\n // generated output — never mistaken for the openspec source.\n try {\n writeFile(path.join(options.absoluteOutDir, '.gitignore'), GITIGNORE_CONTENT)\n for (const file of files) {\n writeFile(path.join(options.absoluteOutDir, file.rel), file.content)\n }\n writeManifest([...files.map((f) => f.rel), ...retained], options.absoluteOutDir)\n } catch (err) {\n logError(`Failed to write openspec pages: ${String(err)}`)\n return false\n }\n\n logInfo(`Generated docs from ${options.specDir}: ${files.length} file(s)`)\n return true\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { NavItem, SidebarItem } from '../types.js'\nimport { logWarn } from './logger.js'\nimport { humanizeLabel, readOpenSpecFolder } from './reader.js'\nimport { specTitle } from './markdown.js'\n\nfunction changeItems(change: { name: string; archiveFolderName?: string; artifacts: string[] }, 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 logWarn(\n `openspec directory not found: ${path.relative(process.cwd(), path.resolve(specDir))} — skipping sidebar generation`,\n )\n return []\n }\n const folder = readOpenSpecFolder(specDir)\n const groups: SidebarItem[] = []\n\n groups.push({\n text: 'Specifications',\n collapsed: false,\n items: [\n { text: 'Overview', link: `/${outDir}/specs/` },\n ...folder.specs.map((s) => ({ text: specTitle(s), link: `/${outDir}/specs/${s.name}/` })),\n ],\n })\n\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 if (folder.archivedChanges.length > 0) {\n groups.push({\n text: 'Archive',\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 logWarn(\n `openspec directory not found: ${path.relative(process.cwd(), path.resolve(specDir))} — skipping nav generation`,\n )\n return null\n }\n return {\n text: options.text ?? 'Docs',\n link: `/${outDir}/`,\n }\n}\n","/**\n * Options for the `withOpenSpec()` config helper.\n * Extends `OpenSpecPluginOptions` with optional nav/sidebar merge controls.\n */\nexport interface WithOpenSpecOptions extends OpenSpecPluginOptions {\n /**\n * Whether to prepend an openspec nav entry to `themeConfig.nav`.\n * @default true\n */\n nav?: boolean\n\n /**\n * Whether to inject the openspec sidebar section into `themeConfig.sidebar`.\n * @default true\n */\n sidebar?: boolean\n /**\n * Label for the nav entry injected into `themeConfig.nav`.\n * @default 'Docs'\n */\n navText?: string\n}\n\n/**\n * Configuration options for the vitepress-plugin-openspec plugin.\n */\nexport interface OpenSpecPluginOptions {\n /**\n * Path to the openspec/ directory of the project.\n *\n * By default the plugin walks up from the current working directory looking\n * for an `openspec/` folder (skipping generated output recognized by its\n * marker), so no configuration is needed when it lives at the project root.\n * Set an explicit path only for custom locations.\n *\n * If the directory does not exist a warning is printed and the build continues\n * without generating any pages or nav/sidebar entries — no error is thrown.\n * An invalid `outDir` (absolute, empty, or escaping `srcDir`) throws instead.\n *\n * @default auto-detected (`<nearest ancestor>/openspec`, falling back to `'./openspec'`)\n * @example\n * // Resolving from docs/.vitepress/config.ts\n * import path from 'node:path'\n * import { fileURLToPath } from 'node:url'\n * const __dirname = path.dirname(fileURLToPath(import.meta.url))\n * const specDir = path.resolve(__dirname, '../../openspec')\n */\n specDir?: string\n\n /**\n * Output directory (relative to VitePress `srcDir`) where the generated\n * Markdown pages will be written.\n * @default 'openspec'\n */\n outDir?: string\n\n /**\n * VitePress source directory — the directory containing your `.md` files\n * (i.e. the `docs/` folder). By default the plugin detects the directory that\n * contains `.vitepress` (the working directory, a first-level subdirectory\n * such as `docs/`, or the parent when the config is evaluated from inside\n * `docs/.vitepress/`), so no configuration is needed for standard layouts.\n *\n * @default auto-detected (directory containing `.vitepress`, falling back to the working directory)\n * @example path.resolve(__dirname, '..') // from docs/.vitepress/config.ts\n */\n srcDir?: string\n}\n\n/**\n * A canonical capability specification from openspec/specs/<name>/spec.md\n */\nexport interface CapabilitySpec {\n /** Folder name (kebab-case capability identifier) */\n name: string\n /** Optional display title from spec.md frontmatter. Overrides humanized name. */\n title?: string\n /** Absolute path to the spec.md file */\n specPath: string\n /** Raw Markdown content of the spec */\n content: string\n}\n\n/**\n * A single artifact (file) belonging to a Change.\n */\nexport type ChangeArtifact = 'proposal' | 'design' | 'tasks'\n\n/**\n * An OpenSpec change (active or archived).\n */\nexport interface Change {\n /** Change directory name (e.g. \"my-feature\" or for archived: \"my-feature\" extracted from \"2026-03-10-my-feature\") */\n name: string\n /** Optional display title from .openspec.yaml. Overrides humanized name. */\n title?: string\n /** Absolute path to the change directory */\n dir: string\n /** Which artifact files are present */\n artifacts: ChangeArtifact[]\n /** Creation date from .openspec.yaml, if available */\n createdDate?: string\n /** For archived changes: the archive date (YYYY-MM-DD) parsed from directory name */\n archivedDate?: string\n /**\n * For archived changes: the original archive folder name (e.g. \"2026-01-15-my-feature\" or\n * \"legacy-feature\" for non-standard names). Used to build correct archive URLs.\n */\n archiveFolderName?: string\n}\n\n/**\n * The full parsed structure of an openspec/ directory.\n */\nexport interface OpenSpecFolder {\n /** Absolute path to the openspec/ root */\n dir: string\n /** Canonical capability specs from openspec/specs/ */\n specs: CapabilitySpec[]\n /** Active changes from openspec/changes/ (excluding archive/) */\n changes: Change[]\n /** Archived changes from openspec/changes/archive/ */\n archivedChanges: Change[]\n}\n\n/**\n * A nav item compatible with VitePress `DefaultTheme.NavItem`.\n */\nexport interface NavItem {\n text: string\n link: string\n}\n\n/**\n * A sidebar item compatible with VitePress `DefaultTheme.SidebarItem`.\n */\nexport interface SidebarItem {\n text: string\n link?: string\n collapsed?: boolean\n items?: SidebarItem[]\n}\n\n/**\n * Shape of the VitePress extension that Vite attaches to the resolved\n * config object (`server.config.vitepress`). VitePress itself attaches its\n * resolved `SiteConfig` under `vitepress.site`; the flat `themeConfig`\n * variant only exists in manually built Vite configs (unit tests), so both\n * locations are supported.\n */\nexport interface VitepressExtension {\n /** VitePress srcDir, when resolved from a real VitePress context */\n srcDir?: string\n /** Resolved VitePress site config (production and dev server) */\n site?: { themeConfig?: Record<string, unknown> }\n /** Flat theme config as built by unit tests constructing a Vite config manually */\n themeConfig?: Record<string, unknown>\n}\n\n/** Extracts the VitePress extension from a Vite `ResolvedConfig`-like object. */\nexport function getVitepressExtension(\n resolvedConfig: unknown,\n): VitepressExtension | undefined {\n return (resolvedConfig as { vitepress?: VitepressExtension }).vitepress\n}\n","import path from 'node:path'\nimport type { ViteDevServer } from 'vite'\nimport type { ResolvedOptions } from './options.js'\nimport { generatePages } from './generator.js'\nimport { readOpenSpecFolder } from './reader.js'\nimport { generateOpenSpecSidebar } from './navigation.js'\nimport { invalidateGeneratedDestinations } from './watch.js'\nimport { getVitepressExtension } from '../types.js'\n\n/**\n * Compact fingerprint of everything that feeds the sidebar and nav:\n * spec and change names, titles, dates, and artifact lists. Comparing\n * signatures before and after an edit tells us whether the navigation\n * config changed and the dev server needs a full restart.\n */\nexport function readNavigationSignature(options: ResolvedOptions): string {\n try {\n const folder = readOpenSpecFolder(options.specDir)\n return JSON.stringify({\n specs: folder.specs.map((s) => [s.name, s.title ?? null]),\n changes: folder.changes.map((c) => [c.name, c.title ?? null, c.createdDate ?? null, c.artifacts]),\n archived: folder.archivedChanges.map((c) => [c.name, c.title ?? null, c.archivedDate ?? null, c.artifacts]),\n })\n } catch {\n return 'unreadable'\n }\n}\n\n/**\n * Updates the sidebar and nav entries inside the in-memory VitePress\n * theme config that `withOpenSpec()` created. `server.restart(true)` only\n * re-creates Vite from the already-resolved inline configuration, so it\n * never re-runs `withOpenSpec()`; mutating the live themeConfig object\n * before the restart is what actually refreshes the navigation.\n *\n * The live theme config lives on the VitePress `SiteConfig` object exposed\n * as `server.config.vitepress.site.themeConfig` (VitePress resolves its\n * site config before creating Vite). The flat `server.config.vitepress`\n * object only exists in unit tests that build a Vite config manually, so\n * both locations are supported.\n */\nexport function updateNavigationInMemory(\n options: ResolvedOptions,\n server: ViteDevServer,\n ownsSidebarEntry: boolean,\n): void {\n if (!ownsSidebarEntry) return\n const vp = getVitepressExtension(server.config)\n const themeConfig = vp?.site?.themeConfig ?? vp?.themeConfig\n if (!themeConfig) return\n const sidebarKey = `/${options.outDir}/`\n const items = generateOpenSpecSidebar(options.specDir, { outDir: options.outDir })\n const sidebar = (themeConfig.sidebar ?? {}) as Record<string, unknown>\n if (items.length > 0) {\n sidebar[sidebarKey] = items\n themeConfig.sidebar = sidebar\n } else {\n delete sidebar[sidebarKey]\n themeConfig.sidebar = sidebar\n }\n}\n\nexport function createScheduler() {\n let timer: ReturnType<typeof setTimeout> | undefined\n return {\n schedule(options: ResolvedOptions, server: ViteDevServer): void {\n // Debounce: editors and archive operations often emit event bursts\n if (timer) clearTimeout(timer)\n timer = setTimeout(() => {\n timer = undefined\n generatePages(options)\n invalidateGeneratedDestinations(options.absoluteOutDir)\n server.ws.send({ type: 'full-reload' })\n }, 100)\n },\n cancel(): void {\n if (timer) {\n clearTimeout(timer)\n timer = undefined\n }\n },\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { Plugin } from 'vite'\nimport type { ResolvedOptions } from './lib/options.js'\nimport type { OpenSpecPluginOptions, WithOpenSpecOptions } from './types.js'\nimport { PLUGIN_NAME, logWarn } from './lib/logger.js'\nimport { resolveOptions } from './lib/options.js'\nimport { generatePages } from './lib/generator.js'\nimport { openspecNav, generateOpenSpecSidebar } from './lib/navigation.js'\nimport { isSourceArtifactEvent } from './lib/watch.js'\nimport { createScheduler, readNavigationSignature, updateNavigationInMemory } from './lib/dev-server.js'\nimport { detectSrcDir, detectVitePressRoot } from './lib/detect.js'\nimport { getVitepressExtension } from './types.js'\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. In most cases `withOpenSpec()` (which calls this\n * internally) is the simpler integration point.\n *\n * @returns true when pages were written; false when generation was skipped\n * (missing or unreadable source, ambiguous source-directory detection) or\n * failed.\n * @throws if `outDir` is not a relative path inside `srcDir` (absolute,\n * traversal, or empty).\n */\nexport function generateOpenSpecPages(userOptions: OpenSpecPluginOptions = {}): boolean {\n // When source-directory detection is ambiguous (multiple .vitepress\n // folders at the same level), detectSrcDir has already warned; skip\n // generation instead of writing into the common parent.\n const detectedSrcDir = userOptions.srcDir ?? detectSrcDir(process.cwd())\n if (!detectedSrcDir) return false\n const options = resolveOptions(userOptions, detectedSrcDir)\n return generatePages(options)\n}\n\n/**\n * Vite plugin that regenerates the openspec documentation pages whenever a\n * file inside the openspec/ directory changes. This makes `vitepress dev`\n * pick up spec edits without a manual restart.\n *\n * For the pages to be available on the first build (including CI), the pages\n * are generated once in `configResolved`. When using `withOpenSpec()` this\n * plugin is wired up automatically.\n */\nexport function openspec(userOptions: OpenSpecPluginOptions = {}): Plugin {\n let resolvedOptions: ResolvedOptions | undefined\n let ownsSidebarEntry = false\n let detachListeners: (() => void) | undefined\n\n return {\n name: PLUGIN_NAME,\n enforce: 'pre',\n\n configResolved(resolvedConfig) {\n detachListeners?.()\n const vpConfig = getVitepressExtension(resolvedConfig)\n const srcDir =\n userOptions.srcDir ?? vpConfig?.srcDir ?? resolvedConfig.root ?? process.cwd()\n try {\n resolvedOptions = resolveOptions(userOptions, srcDir)\n } catch (err) {\n logWarn(String(err))\n return\n }\n if (!fs.existsSync(resolvedOptions.specDir)) {\n logWarn(\n `openspec directory not found: ${resolvedOptions.specDir} — skipping page generation`,\n )\n // Still run generatePages so previously generated pages recorded in\n // the manifest are cleaned up when the source directory disappears.\n generatePages(resolvedOptions)\n resolvedOptions = undefined\n return\n }\n generatePages(resolvedOptions)\n },\n\n configureServer(server) {\n if (!resolvedOptions || !fs.existsSync(resolvedOptions.specDir)) return\n const options = resolvedOptions\n // Use Vite's own watcher: it is supported on all Node versions and\n // platforms declared by this package (unlike recursive fs.watch).\n // Ensure the openspec directory is watched even when it lives outside\n // the Vite root (the documented docs/ + openspec/ layout).\n server.watcher.add(options.specDir)\n const scheduler = createScheduler()\n let navigationSignature = readNavigationSignature(options)\n const onWatchEvent = (event: 'change' | 'add' | 'unlink', file: string) => {\n const absFile = path.resolve(file)\n if (!isSourceArtifactEvent(options, absFile)) return\n // Structural changes (files added or removed) and metadata edits\n // (.openspec.yaml, spec/change titles) also alter the sidebar and\n // nav, which are derived from the config; a full server restart\n // regenerates both pages and navigation. Plain content edits take\n // the fast regenerate+reload path unless a title changed.\n const signature = readNavigationSignature(options)\n const affectsNavigation = event !== 'change' || signature !== navigationSignature\n if (affectsNavigation) {\n scheduler.cancel()\n updateNavigationInMemory(options, server, ownsSidebarEntry)\n navigationSignature = signature\n server.restart(true)\n } else {\n scheduler.schedule(options, server)\n }\n }\n const onChange = (f: string) => onWatchEvent('change', f)\n const onAdd = (f: string) => onWatchEvent('add', f)\n const onUnlink = (f: string) => onWatchEvent('unlink', f)\n server.watcher.on('change', onChange)\n server.watcher.on('add', onAdd)\n server.watcher.on('unlink', onUnlink)\n // Unregister listeners when the dev server shuts down. Closing the\n // shared chokidar instance would break Vite itself, so we only detach.\n // The same detach runs from closeBundle so consecutive builds\n // (e.g. `vitepress build --watch` or quick relaunches) cannot\n // accumulate duplicate listeners.\n detachListeners = () => {\n scheduler.cancel()\n server.watcher.off('change', onChange)\n server.watcher.off('add', onAdd)\n server.watcher.off('unlink', onUnlink)\n server.httpServer?.removeListener('close', detachListeners!)\n detachListeners = undefined\n }\n server.httpServer?.once('close', detachListeners)\n },\n\n closeBundle() {\n detachListeners?.()\n detachListeners = undefined\n },\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 * When the VitePress source directory cannot be detected unambiguously\n * (multiple `.vitepress` folders at the same level), a warning is emitted and\n * the config is returned with only the sidebar shape normalized — nothing is\n * generated or injected.\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 * @throws if `outDir` is not a relative path inside `srcDir` (absolute, traversal, or empty).\n */\nexport function withOpenSpec<T extends Record<string, unknown>>(\n config: T,\n options: WithOpenSpecOptions = {},\n): T {\n const cwd = process.cwd()\n // Resolve a relative srcDir from the wrapped config the same way\n // VitePress resolves it: against the detected project root.\n const configSrcDir =\n typeof config.srcDir === 'string' && config.srcDir\n ? path.resolve(detectVitePressRoot(cwd), config.srcDir)\n : undefined\n const detectedSrcDir = options.srcDir ?? configSrcDir ?? detectSrcDir(cwd)\n const result = { ...config } as Record<string, unknown>\n const themeConfig = (result.themeConfig ?? {}) as Record<string, unknown>\n // Normalize an array-based (single-sidebar) config to the object form so\n // the injected section always lands under its route key — also when\n // generation is skipped below.\n if (Array.isArray(themeConfig.sidebar)) {\n themeConfig.sidebar = { '/': themeConfig.sidebar }\n }\n result.themeConfig = themeConfig\n // When source-directory detection is ambiguous, detectSrcDir has already\n // warned; skip generation and integration instead of writing into the\n // common parent of multiple VitePress sites.\n if (detectedSrcDir === undefined) return result as T\n\n let resolved: ResolvedOptions\n try {\n resolved = resolveOptions(options, detectedSrcDir)\n } catch (err) {\n logWarn(String(err))\n return result as T\n }\n\n const generated = generatePages(resolved)\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({ ...options })] }\n\n // --- Nav ---\n if (generated && options.nav !== false) {\n const navEntry = openspecNav(resolved.specDir, {\n outDir: resolved.outDir,\n text: options.navText,\n })\n const existingNav = (themeConfig.nav as unknown[]) ?? []\n themeConfig.nav = navEntry ? [navEntry, ...existingNav] : existingNav\n }\n\n // --- Sidebar ---\n const sidebarKey = `/${resolved.outDir}/`\n const existingSidebar = (themeConfig.sidebar ?? {}) as Record<string, unknown>\n // The plugin only owns (and the watcher only updates) an entry it created\n // itself; a pre-existing custom entry for this route is preserved as-is.\n const pluginOwnsSidebarEntry = generated && options.sidebar !== false && !existingSidebar[sidebarKey]\n if (pluginOwnsSidebarEntry) {\n const items = generateOpenSpecSidebar(resolved.specDir, { outDir: resolved.outDir })\n if (items.length > 0) {\n themeConfig.sidebar = { ...existingSidebar, [sidebarKey]: items }\n }\n }\n\n result.themeConfig = themeConfig\n return result as T\n}\n\nexport default openspec\n"]}
|
package/dist/index.js
CHANGED
|
@@ -699,6 +699,11 @@ function openspecNav(specDir, options = {}) {
|
|
|
699
699
|
};
|
|
700
700
|
}
|
|
701
701
|
|
|
702
|
+
// src/types.ts
|
|
703
|
+
function getVitepressExtension(resolvedConfig) {
|
|
704
|
+
return resolvedConfig.vitepress;
|
|
705
|
+
}
|
|
706
|
+
|
|
702
707
|
// src/lib/dev-server.ts
|
|
703
708
|
function readNavigationSignature(options) {
|
|
704
709
|
try {
|
|
@@ -748,7 +753,7 @@ function openspec(userOptions = {}) {
|
|
|
748
753
|
enforce: "pre",
|
|
749
754
|
configResolved(resolvedConfig) {
|
|
750
755
|
detachListeners?.();
|
|
751
|
-
const vpConfig = resolvedConfig
|
|
756
|
+
const vpConfig = getVitepressExtension(resolvedConfig);
|
|
752
757
|
const srcDir = userOptions.srcDir ?? vpConfig?.srcDir ?? resolvedConfig.root ?? process.cwd();
|
|
753
758
|
try {
|
|
754
759
|
resolvedOptions = resolveOptions(userOptions, srcDir);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/logger.ts","../src/lib/detect.ts","../src/lib/options.ts","../src/lib/watch.ts","../src/lib/reader.ts","../src/lib/links.ts","../src/lib/markdown.ts","../src/lib/pages.ts","../src/lib/generator.ts","../src/lib/navigation.ts","../src/lib/dev-server.ts","../src/plugin.ts"],"names":["parent","path","fs","yamlLoad","prefix","retained"],"mappings":"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","file":"index.js","sourcesContent":["import pc from 'picocolors'\n\nexport const PLUGIN_NAME = 'vitepress-plugin-openspec'\n\nfunction prefix(color: (s: string) => string): string {\n return pc.bold(color(`[${PLUGIN_NAME}]`))\n}\n\nexport function logWarn(message: string): void {\n console.warn(`${prefix(pc.yellow)} ${message}`)\n}\n\nexport function logInfo(message: string): void {\n console.log(`${prefix(pc.cyan)} ${message}`)\n}\n\nexport function logError(message: string): void {\n console.error(`${prefix(pc.red)} ${message}`)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { PLUGIN_NAME, logWarn } from './logger.js'\n\nconst GENERATED_MARKER = '# Generated by vitepress-plugin-openspec'\n\n/**\n * Returns how strongly a directory looks like a real openspec/ source folder.\n * - 'strong': unambiguous markers (project.md, config file, spec.md, change yaml)\n * - 'weak': only an archive layout — valid for real sources that contain only\n * archived changes, but also matches unmarked generated output, so it is\n * only used when no strong candidate exists anywhere up the tree\n * - false: generated output (identified via its generated .gitignore marker)\n * or no openspec structure at all\n */\nexport function looksLikeOpenSpecDir(dir: string): 'strong' | 'weak' | false {\n const gitignore = path.join(dir, '.gitignore')\n if (fs.existsSync(gitignore)) {\n try {\n if (fs.readFileSync(gitignore, 'utf-8').startsWith(GENERATED_MARKER)) return false\n } catch {\n // ignore unreadable files\n }\n }\n if (fs.existsSync(path.join(dir, 'project.md'))) return 'strong'\n if (fs.existsSync(path.join(dir, 'config.yaml')) || fs.existsSync(path.join(dir, 'config.yml'))) return 'strong'\n const changesDir = path.join(dir, 'changes')\n if (fs.existsSync(changesDir)) {\n try {\n for (const entry of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!entry.isDirectory() && !entry.name.endsWith('.yaml')) continue\n const marker = path.join(changesDir, entry.name, '.openspec.yaml')\n const yaml = path.join(changesDir, `${entry.name}.yaml`)\n if (fs.existsSync(marker) || fs.existsSync(yaml)) return 'strong'\n }\n } catch {\n // ignore unreadable directories\n }\n }\n const specsDir = path.join(dir, 'specs')\n if (fs.existsSync(specsDir)) {\n try {\n for (const entry of fs.readdirSync(specsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n if (fs.existsSync(path.join(specsDir, entry.name, 'spec.md'))) return 'strong'\n }\n } catch {\n // ignore unreadable directories\n }\n }\n const archiveDir = path.join(changesDir, 'archive')\n if (fs.existsSync(archiveDir)) {\n try {\n if (fs.readdirSync(archiveDir, { withFileTypes: true }).some((e) => e.isDirectory())) return 'weak'\n } catch {\n // ignore unreadable directories\n }\n }\n return false\n}\n\n/**\n * Walks up from `start` looking for a real `openspec/` folder. The nearest\n * valid source wins: an archive-only (weak) source found on the way up is\n * preferred over any strong source further up the tree, while unmarked\n * generated output at the output location is skipped as interrupted output.\n * This keeps the plugin zero-config: users do not need to pass `specDir` when\n * `openspec/` lives at the project root, even when VitePress is invoked from\n * a subfolder.\n */\nexport function findOpenSpecDir(start: string, generatedOutputDir?: string): string | undefined {\n let current = path.resolve(start)\n for (;;) {\n const candidate = path.join(current, 'openspec')\n if (fs.existsSync(candidate)) {\n const match = looksLikeOpenSpecDir(candidate)\n // A weak match at the generated output location is unmarked output\n // from an interrupted run — keep searching for the real source.\n if (match === 'weak' && generatedOutputDir && realPath(candidate) === realPath(generatedOutputDir)) {\n const parent = path.dirname(current)\n if (parent === current) return undefined\n current = parent\n continue\n }\n if (match === 'strong' || match === 'weak') return candidate\n }\n const parent = path.dirname(current)\n if (parent === current) return undefined\n current = parent\n }\n}\n\n/**\n * Resolves a path to its canonical form, following symlinks of the deepest\n * existing ancestor so containment checks are not defeated by symlinked\n * output directories.\n */\nexport function realPath(target: string): string {\n let current = path.resolve(target)\n const suffix: string[] = []\n for (;;) {\n if (fs.existsSync(current)) break\n const parent = path.dirname(current)\n if (parent === current) return path.resolve(target)\n suffix.unshift(path.basename(current))\n current = parent\n }\n try {\n current = fs.realpathSync(current)\n } catch {\n return path.resolve(target)\n }\n return suffix.length ? path.join(current, ...suffix) : current\n}\n\nconst srcDirCache = new Map<string, string | undefined>()\n\n/**\n * Detects the VitePress source directory (the folder containing `.vitepress`)\n * by checking the current working directory and its first-level subdirectories\n * (e.g. `docs/.vitepress`). Falls back to the working directory itself.\n *\n * Cached per working directory so repeated calls (e.g. from both\n * `withOpenSpec` and `generateOpenSpecPages` during one config load) do not\n * re-run detection or repeat ambiguity warnings.\n */\nexport function detectSrcDir(cwd: string): string | undefined {\n const key = path.resolve(cwd)\n if (srcDirCache.has(key)) return srcDirCache.get(key)\n const result = resolveSrcDir(key)\n srcDirCache.set(key, result)\n return result\n}\n\nfunction resolveSrcDir(cwd: string): string | undefined {\n if (path.basename(cwd) === '.vitepress') return path.dirname(cwd)\n if (fs.existsSync(path.join(cwd, '.vitepress'))) return cwd\n const matches: string[] = []\n try {\n for (const entry of fs.readdirSync(cwd, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const subDir = path.join(cwd, entry.name)\n if (fs.existsSync(path.join(subDir, '.vitepress'))) matches.push(subDir)\n }\n } catch {\n // ignore unreadable directories\n }\n if (matches.length === 1) return matches[0]\n if (matches.length > 1) {\n const docsMatch = matches.find((m) => path.basename(m) === 'docs')\n if (docsMatch) return docsMatch\n logWarn(\n `Multiple VitePress source directories found (${matches\n .map((m) => path.relative(cwd, m))\n .join(', ')}) — pass an explicit \\`srcDir\\` option. Skipping page generation.`,\n )\n return undefined\n }\n return cwd\n}\n\n/**\n * Detects the VitePress project root — the directory containing the\n * `.vitepress` folder — so a relative `srcDir` from the wrapped config can be\n * resolved the same way VitePress resolves it.\n */\nexport function detectVitePressRoot(cwd: string): string {\n const srcDir = detectSrcDir(cwd)\n return srcDir && fs.existsSync(path.join(srcDir, '.vitepress')) ? srcDir : cwd\n}\n","import path from 'node:path'\nimport type { OpenSpecPluginOptions } from '../types.js'\nimport { detectSrcDir, findOpenSpecDir } from './detect.js'\n\n/**\n * Fully resolved and validated plugin options.\n */\nexport interface ResolvedOptions {\n /** Absolute path to the openspec/ directory */\n specDir: string\n /** Output directory name relative to srcDir (e.g. \"openspec\") */\n outDir: string\n /** Absolute VitePress source directory */\n srcDir: string\n /** Absolute output directory inside srcDir */\n absoluteOutDir: string\n}\n\n/**\n * Centralizes default resolution for all plugin entry points so\n * `generateOpenSpecPages()`, `openspec()` and `withOpenSpec()` behave\n * identically.\n *\n * Defaults are zero-config: `srcDir` falls back to the auto-detected\n * VitePress source directory (the folder containing `.vitepress`), and\n * `specDir` falls back to the nearest ancestor `openspec/` folder,\n * skipping generated output recognized by its marker.\n *\n * @throws if `outDir` is not a relative path inside `srcDir`.\n */\nexport function resolveOptions(\n userOptions: OpenSpecPluginOptions = {},\n fallbackSrcDir?: string,\n): ResolvedOptions {\n // Normalize Windows-style separators so traversal variants like\n // \"nested\\\\..\\\\..\\\\outside\" cannot bypass the containment check.\n const outDir = (userOptions.outDir ?? 'openspec').replace(/\\\\/g, '/')\n if (path.isAbsolute(outDir) || outDir === '' || outDir === '.' || outDir === '..') {\n throw new Error(\n `[vitepress-plugin-openspec] Invalid outDir \"${outDir}\": it must be a relative path inside the VitePress srcDir.`,\n )\n }\n const srcDir = userOptions.srcDir ?? fallbackSrcDir ?? detectSrcDir(process.cwd()) ?? process.cwd()\n const absoluteSrcDir = path.resolve(srcDir)\n const absoluteOutDir = path.resolve(absoluteSrcDir, outDir)\n const rel = path.relative(absoluteSrcDir, absoluteOutDir)\n if (rel.startsWith('..') || path.isAbsolute(rel) || rel === '') {\n throw new Error(\n `[vitepress-plugin-openspec] Invalid outDir \"${outDir}\": it resolves outside the VitePress srcDir.`,\n )\n }\n const specDir = userOptions.specDir ?? findOpenSpecDir(process.cwd(), absoluteOutDir) ?? './openspec'\n return {\n specDir: path.resolve(specDir),\n outDir,\n srcDir: absoluteSrcDir,\n absoluteOutDir,\n }\n}\n","import path from 'node:path'\nimport type { ResolvedOptions } from './options.js'\nimport { readManifest } from './generator.js'\n\n// Basenames of files the plugin always writes into the output tree.\nconst ALWAYS_GENERATED_BASENAMES = new Set(['index.md', '.gitignore', '.openspec-manifest.json'])\n// Artifact copies the plugin writes when the output tree is distinct\n// from the openspec source tree.\nconst ARTIFACT_BASENAMES = new Set(['proposal.md', 'design.md', 'tasks.md'])\n\nconst generatedDestCache = new Map<string, Set<string>>()\n\n/**\n * Resolved absolute destinations of all files recorded in the previous\n * run's manifest — i.e. paths the plugin itself wrote. Only these exact\n * destinations count as generated, never a basename heuristic, so real\n * source artifacts that live inside the output tree remain watchable.\n */\nfunction generatedDestinations(absoluteOutDir: string): Set<string> {\n const cached = generatedDestCache.get(absoluteOutDir)\n if (cached) return cached\n const set = new Set<string>()\n for (const entry of readManifest(absoluteOutDir)) {\n set.add(path.resolve(absoluteOutDir, entry))\n }\n generatedDestCache.set(absoluteOutDir, set)\n return set\n}\n\n/**\n * Invalidates the cached manifest destinations after a regeneration wrote\n * a new manifest.\n */\nexport function invalidateGeneratedDestinations(absoluteOutDir: string): void {\n generatedDestCache.delete(absoluteOutDir)\n}\n\nfunction isInside(parent: string, child: string): boolean {\n const rel = path.relative(parent, child)\n return !(rel.startsWith('..') || path.isAbsolute(rel))\n}\n\n/**\n * Layout classification for the overlapping specDir/outDir cases:\n * - 'equal': specDir and outDir are the same directory\n * - 'out-inside-spec': outDir is a proper child of specDir\n * - 'spec-inside-out': specDir is a proper child of outDir\n * - 'disjoint': no overlap\n */\nexport type LayoutRelation = 'equal' | 'out-inside-spec' | 'spec-inside-out' | 'disjoint'\n\nexport function classifyLayout(options: ResolvedOptions): LayoutRelation {\n if (options.specDir === options.absoluteOutDir) return 'equal'\n if (isInside(options.specDir, options.absoluteOutDir)) return 'out-inside-spec'\n if (isInside(options.absoluteOutDir, options.specDir)) return 'spec-inside-out'\n return 'disjoint'\n}\n\n/**\n * Whether a file inside the output tree was written by this plugin (as\n * opposed to an openspec source artifact that happens to live in the same\n * tree when specDir and outDir overlap).\n *\n * Layout rules (generated destinations never coincide with source files):\n * - 'equal': the shared tree only receives index.md/.gitignore/manifest\n * from the plugin; artifact-named files are sources.\n * - 'out-inside-spec' / 'disjoint': the plugin writes artifact copies into\n * the output tree; every known basename inside it is generated.\n * - 'spec-inside-out': source files live inside the output tree; files\n * inside specDir are sources, only files outside it are generated.\n */\nexport function isPluginGeneratedFile(options: ResolvedOptions, absFile: string): boolean {\n if (!isInside(options.absoluteOutDir, absFile)) return false\n // Only exact destinations recorded in the generation manifest are\n // generated output — never a basename heuristic. This keeps real source\n // artifacts inside an overlapping output tree watchable.\n if (generatedDestinations(options.absoluteOutDir).has(path.resolve(absFile))) return true\n const base = path.basename(absFile)\n switch (classifyLayout(options)) {\n case 'equal':\n return ALWAYS_GENERATED_BASENAMES.has(base)\n case 'out-inside-spec':\n // The output tree is nested inside specDir, so a basename match can\n // hit real source files too. Only the exact destinations recorded\n // in the manifest (checked above) plus the always-generated\n // top-level markers count as plugin output.\n return ALWAYS_GENERATED_BASENAMES.has(base) && !isInside(options.specDir, absFile)\n case 'disjoint':\n return ALWAYS_GENERATED_BASENAMES.has(base) || ARTIFACT_BASENAMES.has(base)\n case 'spec-inside-out':\n return !isInside(options.specDir, absFile) &&\n (ALWAYS_GENERATED_BASENAMES.has(base) || ARTIFACT_BASENAMES.has(base))\n }\n}\n\n/**\n * Whether a watch event for this file should trigger regeneration of the\n * openspec pages. True for openspec source files (including\n * `.openspec.yaml`), false for files the plugin itself generated.\n */\nexport function isSourceArtifactEvent(options: ResolvedOptions, absFile: string): boolean {\n if (!isInside(options.specDir, absFile)) return false\n return !isPluginGeneratedFile(options, absFile)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { load as yamlLoad } from 'js-yaml'\nimport type { CapabilitySpec, Change, ChangeArtifact, OpenSpecFolder } from '../types.js'\n\nconst ARTIFACT_NAMES: ChangeArtifact[] = ['proposal', 'design', 'tasks']\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\nexport function 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 return ARTIFACT_NAMES.filter((name) => fs.existsSync(path.join(dir, `${name}.md`)))\n}\n\nfunction isDirectory(dir: string, name: string): boolean {\n return fs.existsSync(path.join(dir, name, '.openspec.yaml'))\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 (!isDirectory(changeDir, '.')) 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 const meta = readOpenSpecYaml(changeDir)\n const match = entry.name.match(/^(\\d{4}-\\d{2}-\\d{2})-(.+)$/)\n archivedChanges.push({\n name: match?.[2] ?? entry.name,\n title: meta.title ? String(meta.title) : undefined,\n dir: changeDir,\n artifacts: readArtifacts(changeDir),\n createdDate: formatDate(meta.created),\n archivedDate: match?.[1],\n archiveFolderName: entry.name,\n })\n }\n }\n\n return { dir: resolved, specs, changes, archivedChanges }\n}\n","import path from 'node:path'\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 * Links that point outside the openspec root, absolute paths, HTTP URLs, and\n * anchor-only links are left unchanged.\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 return content.replace(\n /(\\[[^\\]]*\\])\\(([^)]+)\\)/g,\n (_match, linkText: string, urlPart: string) => {\n const titleMatch = urlPart.match(/^(.+?)(\\s+[\"'][^\"']*[\"'])?\\s*$/)\n if (!titleMatch) return _match\n const rawUrl = titleMatch[1].trim()\n const title = titleMatch[2] ?? ''\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 const hashIdx = rawUrl.indexOf('#')\n const urlWithoutFragment = hashIdx >= 0 ? rawUrl.slice(0, hashIdx) : rawUrl\n const fragment = hashIdx >= 0 ? rawUrl.slice(hashIdx) : ''\n if (!urlWithoutFragment) {\n return _match\n }\n const resolvedPath = path.resolve(srcDir, urlWithoutFragment)\n const relToOpenspec = path.relative(openspecRootDir, resolvedPath)\n if (relToOpenspec.startsWith('..') || path.isAbsolute(relToOpenspec)) {\n return _match\n }\n const vitePath = relToOpenspec.replace(/\\.md$/, '').replace(/\\\\/g, '/')\n const absoluteLink = `/${outDir}/${vitePath}${fragment}`\n return `${linkText}(${absoluteLink}${title})`\n },\n )\n}\n","import type { CapabilitySpec } from '../types.js'\nimport { humanizeLabel } from './reader.js'\n\nexport function 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, '\\\\$1')\n}\n\nexport function 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 return stripped.replace(/\\n{3,}/g, '\\n\\n')\n}\n\nexport function transformScenarios(content: string): string {\n const lines = content.split('\\n')\n const result: string[] = []\n let inScenario = false\n for (const line of lines) {\n const scenarioMatch = line.match(/^#### Scenario: (.+)$/)\n const isHeading = /^#{1,6} /.test(line)\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 if (inScenario) result.push(':::')\n return result.join('\\n')\n}\n\nexport function specTitle(spec: CapabilitySpec): string {\n return spec.title ?? humanizeLabel(spec.name)\n}\n","import type { CapabilitySpec, Change, OpenSpecFolder } from '../types.js'\nimport { humanizeLabel } from './reader.js'\nimport { extractSpecDescription, specTitle, stripDeltaMarkers, transformScenarios } from './markdown.js'\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(`# ${specTitle(spec)}`)\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(`- [${specTitle(spec)}](/${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 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 if (folder.archivedChanges.length > 0) {\n lines.push('')\n lines.push('## Archive')\n lines.push('')\n for (const change of folder.archivedChanges) {\n const date = change.archivedDate ? ` *(archived: ${change.archivedDate})*` : ''\n lines.push(\n `- [${change.title ?? humanizeLabel(change.name)}](/${outDir}/changes/archive/${change.archiveFolderName}/)${date}`,\n )\n }\n }\n lines.push('')\n return lines.join('\\n')\n}\n\n/**\n * Generates the root index page of the openspec documentation section.\n */\nexport function generateRootIndexPage(outDir: string): string {\n return [\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}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { invalidateGeneratedDestinations } from './watch.js'\nimport type { Change } from '../types.js'\nimport type { ResolvedOptions } from './options.js'\nimport { logError, logInfo, logWarn } from './logger.js'\nimport { readOpenSpecFolder } from './reader.js'\nimport { rewriteRelativeLinks } from './links.js'\nimport {\n generateChangeIndexPage,\n generateChangesIndexPage,\n generateRootIndexPage,\n generateSpecPage,\n generateSpecsIndexPage,\n} from './pages.js'\n\nexport const MANIFEST_FILE = '.openspec-manifest.json'\nconst GITIGNORE_CONTENT = '# Generated by vitepress-plugin-openspec — do not commit generated files.\\n*\\n!.gitignore\\n'\n\ninterface OutputFile {\n /** Path relative to absoluteOutDir, using forward slashes */\n rel: string\n content: string\n}\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 toRel(absoluteOutDir: string, filePath: string): string {\n return path.relative(absoluteOutDir, filePath).split(path.sep).join('/')\n}\n\nfunction pruneEmptyDirs(rootDir: string, startDir: string): void {\n let dir = startDir\n while (dir.startsWith(rootDir) && dir !== rootDir) {\n try {\n if (fs.readdirSync(dir).length > 0) break\n fs.rmdirSync(dir)\n } catch {\n break\n }\n dir = path.dirname(dir)\n }\n}\n\n/**\n * Reads the previous run's manifest and deletes all recorded files.\n * Runs only after the replacement generation has been fully read and\n * rendered in memory, so a failing source read never destroys the last\n * successful output. Because cleanup precedes writing the new files, a\n * stale entry can never resolve to a freshly written page, even for\n * case-only renames on case-insensitive filesystems.\n *\n * @returns entries whose deletion failed; they are retained in the next\n * manifest so cleanup retries instead of forgetting them.\n */\nfunction cleanupPreviousManifest(rootDir: string): string[] {\n const manifestPath = path.join(rootDir, MANIFEST_FILE)\n if (!fs.existsSync(manifestPath)) return []\n let previous: string[] = []\n try {\n const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as unknown\n if (Array.isArray(parsed)) previous = parsed.filter((f): f is string => typeof f === 'string')\n } catch {\n // Unreadable manifest: treat as empty\n return []\n }\n const retained: string[] = []\n for (const entry of previous) {\n const entryPath = path.resolve(rootDir, entry)\n const rel = path.relative(rootDir, entryPath)\n if (rel.startsWith('..') || path.isAbsolute(rel)) continue\n try {\n if (fs.existsSync(entryPath)) {\n fs.rmSync(entryPath)\n pruneEmptyDirs(rootDir, path.dirname(entryPath))\n }\n } catch {\n // Deletion failed (e.g. locked file): retry on the next run\n retained.push(entry)\n }\n }\n return retained\n}\n\nexport function readManifest(rootDir: string): string[] {\n try {\n const parsed = JSON.parse(fs.readFileSync(path.join(rootDir, MANIFEST_FILE), 'utf-8')) as unknown\n if (Array.isArray(parsed)) return parsed.filter((f): f is string => typeof f === 'string')\n } catch {\n // Unreadable or missing manifest: treat as empty\n }\n return []\n}\n\nfunction writeManifest(files: string[], rootDir: string): void {\n const manifestPath = path.join(rootDir, MANIFEST_FILE)\n try {\n writeFile(manifestPath, JSON.stringify(files, null, 2))\n invalidateGeneratedDestinations(rootDir)\n } catch {\n // Best-effort: never fail generation because of the manifest\n }\n}\n\nfunction renderChangePages(\n change: Change,\n options: ResolvedOptions,\n isArchived: boolean,\n): OutputFile[] {\n const subPath = isArchived\n ? path.join('changes', 'archive', change.archiveFolderName ?? change.name)\n : path.join('changes', change.name)\n const changeOutDir = path.join(options.absoluteOutDir, subPath)\n const files: OutputFile[] = []\n\n files.push({\n rel: toRel(options.absoluteOutDir, path.join(changeOutDir, 'index.md')),\n content: generateChangeIndexPage(change, options.outDir),\n })\n\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 // When specDir and outDir overlap, never copy a file onto itself\n if (path.resolve(srcFile) === path.resolve(destFile)) continue\n const content = fs.readFileSync(srcFile, 'utf-8')\n files.push({\n rel: toRel(options.absoluteOutDir, destFile),\n content: rewriteRelativeLinks(content, srcFile, options.specDir, options.outDir),\n })\n }\n return files\n}\n\n/**\n * Reads the openspec directory and renders every output page into memory.\n * All source file access happens here, before any destructive step, so\n * an inconsistent source tree cannot destroy the previous output.\n */\nfunction renderAllPages(options: ResolvedOptions): OutputFile[] {\n const folder = readOpenSpecFolder(options.specDir)\n const files: OutputFile[] = []\n\n for (const spec of folder.specs) {\n const dest = path.join(options.absoluteOutDir, 'specs', spec.name, 'index.md')\n files.push({ rel: toRel(options.absoluteOutDir, dest), content: generateSpecPage(spec) })\n }\n files.push({\n rel: 'specs/index.md',\n content: generateSpecsIndexPage(folder.specs, options.outDir),\n })\n\n for (const change of folder.changes) {\n files.push(...renderChangePages(change, options, false))\n }\n for (const change of folder.archivedChanges) {\n files.push(...renderChangePages(change, options, true))\n }\n\n files.push({\n rel: 'changes/index.md',\n content: generateChangesIndexPage(folder, options.outDir),\n })\n files.push({\n rel: 'index.md',\n content: generateRootIndexPage(options.outDir),\n })\n\n return files\n}\n\n/**\n * Synchronously generates all VitePress Markdown pages from the openspec/\n * directory and writes them to disk, removing stale output from previous runs.\n *\n * @returns true when pages were written; false when generation was skipped\n * (missing or unreadable source) or failed.\n */\nexport function generatePages(options: ResolvedOptions): boolean {\n // Remove stale output from the previous run even when the source\n // directory has disappeared, so published pages do not linger forever.\n if (!fs.existsSync(options.specDir)) {\n logWarn(\n `openspec directory not found: ${path.relative(options.srcDir, options.specDir)} — skipping page generation`,\n )\n const retained = cleanupPreviousManifest(options.absoluteOutDir)\n if (retained.length > 0 || fs.existsSync(options.absoluteOutDir)) {\n writeManifest(retained, options.absoluteOutDir)\n }\n return false\n }\n\n // Phase 1: read sources and render everything in memory. A failure here\n // leaves the last successful output untouched.\n let files: OutputFile[]\n try {\n files = renderAllPages(options)\n } catch (err) {\n logError(`Failed to process openspec directory \"${options.specDir}\": ${String(err)}`)\n return false\n }\n\n // Phase 2: destructive cleanup of the previous output, now that the\n // replacement generation is complete and safe to write.\n const retained = cleanupPreviousManifest(options.absoluteOutDir)\n\n // Phase 3: write the new pages. The self-managed .gitignore marker goes\n // first so even an interrupted run leaves the output recognizable as\n // generated output — never mistaken for the openspec source.\n try {\n writeFile(path.join(options.absoluteOutDir, '.gitignore'), GITIGNORE_CONTENT)\n for (const file of files) {\n writeFile(path.join(options.absoluteOutDir, file.rel), file.content)\n }\n writeManifest([...files.map((f) => f.rel), ...retained], options.absoluteOutDir)\n } catch (err) {\n logError(`Failed to write openspec pages: ${String(err)}`)\n return false\n }\n\n logInfo(`Generated docs from ${options.specDir}: ${files.length} file(s)`)\n return true\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { NavItem, SidebarItem } from '../types.js'\nimport { logWarn } from './logger.js'\nimport { humanizeLabel, readOpenSpecFolder } from './reader.js'\nimport { specTitle } from './markdown.js'\n\nfunction changeItems(change: { name: string; archiveFolderName?: string; artifacts: string[] }, 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 logWarn(\n `openspec directory not found: ${path.relative(process.cwd(), path.resolve(specDir))} — skipping sidebar generation`,\n )\n return []\n }\n const folder = readOpenSpecFolder(specDir)\n const groups: SidebarItem[] = []\n\n groups.push({\n text: 'Specifications',\n collapsed: false,\n items: [\n { text: 'Overview', link: `/${outDir}/specs/` },\n ...folder.specs.map((s) => ({ text: specTitle(s), link: `/${outDir}/specs/${s.name}/` })),\n ],\n })\n\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 if (folder.archivedChanges.length > 0) {\n groups.push({\n text: 'Archive',\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 logWarn(\n `openspec directory not found: ${path.relative(process.cwd(), path.resolve(specDir))} — skipping nav generation`,\n )\n return null\n }\n return {\n text: options.text ?? 'Docs',\n link: `/${outDir}/`,\n }\n}\n","import path from 'node:path'\nimport type { ViteDevServer } from 'vite'\nimport type { ResolvedOptions } from './options.js'\nimport { generatePages } from './generator.js'\nimport { readOpenSpecFolder } from './reader.js'\nimport { generateOpenSpecSidebar } from './navigation.js'\nimport { invalidateGeneratedDestinations } from './watch.js'\n\n/**\n * Compact fingerprint of everything that feeds the sidebar and nav:\n * spec and change names, titles, dates, and artifact lists. Comparing\n * signatures before and after an edit tells us whether the navigation\n * config changed and the dev server needs a full restart.\n */\nexport function readNavigationSignature(options: ResolvedOptions): string {\n try {\n const folder = readOpenSpecFolder(options.specDir)\n return JSON.stringify({\n specs: folder.specs.map((s) => [s.name, s.title ?? null]),\n changes: folder.changes.map((c) => [c.name, c.title ?? null, c.createdDate ?? null, c.artifacts]),\n archived: folder.archivedChanges.map((c) => [c.name, c.title ?? null, c.archivedDate ?? null, c.artifacts]),\n })\n } catch {\n return 'unreadable'\n }\n}\n\n/**\n * Updates the sidebar and nav entries inside the in-memory VitePress\n * theme config that `withOpenSpec()` created. `server.restart(true)` only\n * re-creates Vite from the already-resolved inline configuration, so it\n * never re-runs `withOpenSpec()`; mutating the live themeConfig object\n * before the restart is what actually refreshes the navigation.\n *\n * The live theme config lives on the VitePress `SiteConfig` object exposed\n * as `server.config.vitepress.site.themeConfig` (VitePress resolves its\n * site config before creating Vite). The flat `server.config.vitepress`\n * object only exists in unit tests that build a Vite config manually, so\n * both locations are supported.\n */\nexport function updateNavigationInMemory(\n options: ResolvedOptions,\n server: ViteDevServer,\n ownsSidebarEntry: boolean,\n): void {\n if (!ownsSidebarEntry) return\n const vp = (server.config as unknown as {\n vitepress?: {\n site?: { themeConfig?: Record<string, unknown> }\n themeConfig?: Record<string, unknown>\n }\n }).vitepress\n const themeConfig = vp?.site?.themeConfig ?? vp?.themeConfig\n if (!themeConfig) return\n const sidebarKey = `/${options.outDir}/`\n const items = generateOpenSpecSidebar(options.specDir, { outDir: options.outDir })\n const sidebar = (themeConfig.sidebar ?? {}) as Record<string, unknown>\n if (items.length > 0) {\n sidebar[sidebarKey] = items\n themeConfig.sidebar = sidebar\n } else {\n delete sidebar[sidebarKey]\n themeConfig.sidebar = sidebar\n }\n}\n\nexport function createScheduler() {\n let timer: ReturnType<typeof setTimeout> | undefined\n return {\n schedule(options: ResolvedOptions, server: ViteDevServer): void {\n // Debounce: editors and archive operations often emit event bursts\n if (timer) clearTimeout(timer)\n timer = setTimeout(() => {\n timer = undefined\n generatePages(options)\n invalidateGeneratedDestinations(options.absoluteOutDir)\n server.ws.send({ type: 'full-reload' })\n }, 100)\n },\n cancel(): void {\n if (timer) {\n clearTimeout(timer)\n timer = undefined\n }\n },\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { Plugin } from 'vite'\nimport type { ResolvedOptions } from './lib/options.js'\nimport type { OpenSpecPluginOptions, WithOpenSpecOptions } from './types.js'\nimport { PLUGIN_NAME, logWarn } from './lib/logger.js'\nimport { resolveOptions } from './lib/options.js'\nimport { generatePages } from './lib/generator.js'\nimport { openspecNav, generateOpenSpecSidebar } from './lib/navigation.js'\nimport { isSourceArtifactEvent } from './lib/watch.js'\nimport { createScheduler, readNavigationSignature, updateNavigationInMemory } from './lib/dev-server.js'\nimport { detectSrcDir, detectVitePressRoot } from './lib/detect.js'\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. In most cases `withOpenSpec()` (which calls this\n * internally) is the simpler integration point.\n *\n * @returns true when pages were written; false when generation was skipped\n * (missing or unreadable source, ambiguous source-directory detection) or\n * failed.\n * @throws if `outDir` is not a relative path inside `srcDir` (absolute,\n * traversal, or empty).\n */\nexport function generateOpenSpecPages(userOptions: OpenSpecPluginOptions = {}): boolean {\n // When source-directory detection is ambiguous (multiple .vitepress\n // folders at the same level), detectSrcDir has already warned; skip\n // generation instead of writing into the common parent.\n const detectedSrcDir = userOptions.srcDir ?? detectSrcDir(process.cwd())\n if (!detectedSrcDir) return false\n const options = resolveOptions(userOptions, detectedSrcDir)\n return generatePages(options)\n}\n\n/**\n * Vite plugin that regenerates the openspec documentation pages whenever a\n * file inside the openspec/ directory changes. This makes `vitepress dev`\n * pick up spec edits without a manual restart.\n *\n * For the pages to be available on the first build (including CI), the pages\n * are generated once in `configResolved`. When using `withOpenSpec()` this\n * plugin is wired up automatically.\n */\nexport function openspec(userOptions: OpenSpecPluginOptions = {}): Plugin {\n let resolvedOptions: ResolvedOptions | undefined\n let ownsSidebarEntry = false\n let detachListeners: (() => void) | undefined\n\n return {\n name: PLUGIN_NAME,\n enforce: 'pre',\n\n configResolved(resolvedConfig) {\n detachListeners?.()\n const vpConfig = (resolvedConfig as unknown as { vitepress?: { srcDir?: string } }).vitepress\n const srcDir =\n userOptions.srcDir ?? vpConfig?.srcDir ?? resolvedConfig.root ?? process.cwd()\n try {\n resolvedOptions = resolveOptions(userOptions, srcDir)\n } catch (err) {\n logWarn(String(err))\n return\n }\n if (!fs.existsSync(resolvedOptions.specDir)) {\n logWarn(\n `openspec directory not found: ${resolvedOptions.specDir} — skipping page generation`,\n )\n // Still run generatePages so previously generated pages recorded in\n // the manifest are cleaned up when the source directory disappears.\n generatePages(resolvedOptions)\n resolvedOptions = undefined\n return\n }\n generatePages(resolvedOptions)\n },\n\n configureServer(server) {\n if (!resolvedOptions || !fs.existsSync(resolvedOptions.specDir)) return\n const options = resolvedOptions\n // Use Vite's own watcher: it is supported on all Node versions and\n // platforms declared by this package (unlike recursive fs.watch).\n // Ensure the openspec directory is watched even when it lives outside\n // the Vite root (the documented docs/ + openspec/ layout).\n server.watcher.add(options.specDir)\n const scheduler = createScheduler()\n let navigationSignature = readNavigationSignature(options)\n const onWatchEvent = (event: 'change' | 'add' | 'unlink', file: string) => {\n const absFile = path.resolve(file)\n if (!isSourceArtifactEvent(options, absFile)) return\n // Structural changes (files added or removed) and metadata edits\n // (.openspec.yaml, spec/change titles) also alter the sidebar and\n // nav, which are derived from the config; a full server restart\n // regenerates both pages and navigation. Plain content edits take\n // the fast regenerate+reload path unless a title changed.\n const signature = readNavigationSignature(options)\n const affectsNavigation = event !== 'change' || signature !== navigationSignature\n if (affectsNavigation) {\n scheduler.cancel()\n updateNavigationInMemory(options, server, ownsSidebarEntry)\n navigationSignature = signature\n server.restart(true)\n } else {\n scheduler.schedule(options, server)\n }\n }\n const onChange = (f: string) => onWatchEvent('change', f)\n const onAdd = (f: string) => onWatchEvent('add', f)\n const onUnlink = (f: string) => onWatchEvent('unlink', f)\n server.watcher.on('change', onChange)\n server.watcher.on('add', onAdd)\n server.watcher.on('unlink', onUnlink)\n // Unregister listeners when the dev server shuts down. Closing the\n // shared chokidar instance would break Vite itself, so we only detach.\n // The same detach runs from closeBundle so consecutive builds\n // (e.g. `vitepress build --watch` or quick relaunches) cannot\n // accumulate duplicate listeners.\n detachListeners = () => {\n scheduler.cancel()\n server.watcher.off('change', onChange)\n server.watcher.off('add', onAdd)\n server.watcher.off('unlink', onUnlink)\n server.httpServer?.removeListener('close', detachListeners!)\n detachListeners = undefined\n }\n server.httpServer?.once('close', detachListeners)\n },\n\n closeBundle() {\n detachListeners?.()\n detachListeners = undefined\n },\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 * When the VitePress source directory cannot be detected unambiguously\n * (multiple `.vitepress` folders at the same level), a warning is emitted and\n * the config is returned with only the sidebar shape normalized — nothing is\n * generated or injected.\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 * @throws if `outDir` is not a relative path inside `srcDir` (absolute, traversal, or empty).\n */\nexport function withOpenSpec<T extends Record<string, unknown>>(\n config: T,\n options: WithOpenSpecOptions = {},\n): T {\n const cwd = process.cwd()\n // Resolve a relative srcDir from the wrapped config the same way\n // VitePress resolves it: against the detected project root.\n const configSrcDir =\n typeof config.srcDir === 'string' && config.srcDir\n ? path.resolve(detectVitePressRoot(cwd), config.srcDir)\n : undefined\n const detectedSrcDir = options.srcDir ?? configSrcDir ?? detectSrcDir(cwd)\n const result = { ...config } as Record<string, unknown>\n const themeConfig = (result.themeConfig ?? {}) as Record<string, unknown>\n // Normalize an array-based (single-sidebar) config to the object form so\n // the injected section always lands under its route key — also when\n // generation is skipped below.\n if (Array.isArray(themeConfig.sidebar)) {\n themeConfig.sidebar = { '/': themeConfig.sidebar }\n }\n result.themeConfig = themeConfig\n // When source-directory detection is ambiguous, detectSrcDir has already\n // warned; skip generation and integration instead of writing into the\n // common parent of multiple VitePress sites.\n if (detectedSrcDir === undefined) return result as T\n\n let resolved: ResolvedOptions\n try {\n resolved = resolveOptions(options, detectedSrcDir)\n } catch (err) {\n logWarn(String(err))\n return result as T\n }\n\n const generated = generatePages(resolved)\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({ ...options })] }\n\n // --- Nav ---\n if (generated && options.nav !== false) {\n const navEntry = openspecNav(resolved.specDir, {\n outDir: resolved.outDir,\n text: options.navText,\n })\n const existingNav = (themeConfig.nav as unknown[]) ?? []\n themeConfig.nav = navEntry ? [navEntry, ...existingNav] : existingNav\n }\n\n // --- Sidebar ---\n const sidebarKey = `/${resolved.outDir}/`\n const existingSidebar = (themeConfig.sidebar ?? {}) as Record<string, unknown>\n // The plugin only owns (and the watcher only updates) an entry it created\n // itself; a pre-existing custom entry for this route is preserved as-is.\n const pluginOwnsSidebarEntry = generated && options.sidebar !== false && !existingSidebar[sidebarKey]\n if (pluginOwnsSidebarEntry) {\n const items = generateOpenSpecSidebar(resolved.specDir, { outDir: resolved.outDir })\n if (items.length > 0) {\n themeConfig.sidebar = { ...existingSidebar, [sidebarKey]: items }\n }\n }\n\n result.themeConfig = themeConfig\n return result as T\n}\n\nexport default openspec\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/logger.ts","../src/lib/detect.ts","../src/lib/options.ts","../src/lib/watch.ts","../src/lib/reader.ts","../src/lib/links.ts","../src/lib/markdown.ts","../src/lib/pages.ts","../src/lib/generator.ts","../src/lib/navigation.ts","../src/types.ts","../src/lib/dev-server.ts","../src/plugin.ts"],"names":["parent","path","fs","yamlLoad","prefix","retained"],"mappings":"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","file":"index.js","sourcesContent":["import pc from 'picocolors'\n\nexport const PLUGIN_NAME = 'vitepress-plugin-openspec'\n\nfunction prefix(color: (s: string) => string): string {\n return pc.bold(color(`[${PLUGIN_NAME}]`))\n}\n\nexport function logWarn(message: string): void {\n console.warn(`${prefix(pc.yellow)} ${message}`)\n}\n\nexport function logInfo(message: string): void {\n console.log(`${prefix(pc.cyan)} ${message}`)\n}\n\nexport function logError(message: string): void {\n console.error(`${prefix(pc.red)} ${message}`)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { PLUGIN_NAME, logWarn } from './logger.js'\n\nconst GENERATED_MARKER = '# Generated by vitepress-plugin-openspec'\n\n/**\n * Returns how strongly a directory looks like a real openspec/ source folder.\n * - 'strong': unambiguous markers (project.md, config file, spec.md, change yaml)\n * - 'weak': only an archive layout — valid for real sources that contain only\n * archived changes, but also matches unmarked generated output, so it is\n * only used when no strong candidate exists anywhere up the tree\n * - false: generated output (identified via its generated .gitignore marker)\n * or no openspec structure at all\n */\nexport function looksLikeOpenSpecDir(dir: string): 'strong' | 'weak' | false {\n const gitignore = path.join(dir, '.gitignore')\n if (fs.existsSync(gitignore)) {\n try {\n if (fs.readFileSync(gitignore, 'utf-8').startsWith(GENERATED_MARKER)) return false\n } catch {\n // ignore unreadable files\n }\n }\n if (fs.existsSync(path.join(dir, 'project.md'))) return 'strong'\n if (fs.existsSync(path.join(dir, 'config.yaml')) || fs.existsSync(path.join(dir, 'config.yml'))) return 'strong'\n const changesDir = path.join(dir, 'changes')\n if (fs.existsSync(changesDir)) {\n try {\n for (const entry of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!entry.isDirectory() && !entry.name.endsWith('.yaml')) continue\n const marker = path.join(changesDir, entry.name, '.openspec.yaml')\n const yaml = path.join(changesDir, `${entry.name}.yaml`)\n if (fs.existsSync(marker) || fs.existsSync(yaml)) return 'strong'\n }\n } catch {\n // ignore unreadable directories\n }\n }\n const specsDir = path.join(dir, 'specs')\n if (fs.existsSync(specsDir)) {\n try {\n for (const entry of fs.readdirSync(specsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n if (fs.existsSync(path.join(specsDir, entry.name, 'spec.md'))) return 'strong'\n }\n } catch {\n // ignore unreadable directories\n }\n }\n const archiveDir = path.join(changesDir, 'archive')\n if (fs.existsSync(archiveDir)) {\n try {\n if (fs.readdirSync(archiveDir, { withFileTypes: true }).some((e) => e.isDirectory())) return 'weak'\n } catch {\n // ignore unreadable directories\n }\n }\n return false\n}\n\n/**\n * Walks up from `start` looking for a real `openspec/` folder. The nearest\n * valid source wins: an archive-only (weak) source found on the way up is\n * preferred over any strong source further up the tree, while unmarked\n * generated output at the output location is skipped as interrupted output.\n * This keeps the plugin zero-config: users do not need to pass `specDir` when\n * `openspec/` lives at the project root, even when VitePress is invoked from\n * a subfolder.\n */\nexport function findOpenSpecDir(start: string, generatedOutputDir?: string): string | undefined {\n let current = path.resolve(start)\n for (;;) {\n const candidate = path.join(current, 'openspec')\n if (fs.existsSync(candidate)) {\n const match = looksLikeOpenSpecDir(candidate)\n // A weak match at the generated output location is unmarked output\n // from an interrupted run — keep searching for the real source.\n if (match === 'weak' && generatedOutputDir && realPath(candidate) === realPath(generatedOutputDir)) {\n const parent = path.dirname(current)\n if (parent === current) return undefined\n current = parent\n continue\n }\n if (match === 'strong' || match === 'weak') return candidate\n }\n const parent = path.dirname(current)\n if (parent === current) return undefined\n current = parent\n }\n}\n\n/**\n * Resolves a path to its canonical form, following symlinks of the deepest\n * existing ancestor so containment checks are not defeated by symlinked\n * output directories.\n */\nexport function realPath(target: string): string {\n let current = path.resolve(target)\n const suffix: string[] = []\n for (;;) {\n if (fs.existsSync(current)) break\n const parent = path.dirname(current)\n if (parent === current) return path.resolve(target)\n suffix.unshift(path.basename(current))\n current = parent\n }\n try {\n current = fs.realpathSync(current)\n } catch {\n return path.resolve(target)\n }\n return suffix.length ? path.join(current, ...suffix) : current\n}\n\nconst srcDirCache = new Map<string, string | undefined>()\n\n/**\n * Detects the VitePress source directory (the folder containing `.vitepress`)\n * by checking the current working directory and its first-level subdirectories\n * (e.g. `docs/.vitepress`). Falls back to the working directory itself.\n *\n * Cached per working directory so repeated calls (e.g. from both\n * `withOpenSpec` and `generateOpenSpecPages` during one config load) do not\n * re-run detection or repeat ambiguity warnings.\n */\nexport function detectSrcDir(cwd: string): string | undefined {\n const key = path.resolve(cwd)\n if (srcDirCache.has(key)) return srcDirCache.get(key)\n const result = resolveSrcDir(key)\n srcDirCache.set(key, result)\n return result\n}\n\nfunction resolveSrcDir(cwd: string): string | undefined {\n if (path.basename(cwd) === '.vitepress') return path.dirname(cwd)\n if (fs.existsSync(path.join(cwd, '.vitepress'))) return cwd\n const matches: string[] = []\n try {\n for (const entry of fs.readdirSync(cwd, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const subDir = path.join(cwd, entry.name)\n if (fs.existsSync(path.join(subDir, '.vitepress'))) matches.push(subDir)\n }\n } catch {\n // ignore unreadable directories\n }\n if (matches.length === 1) return matches[0]\n if (matches.length > 1) {\n const docsMatch = matches.find((m) => path.basename(m) === 'docs')\n if (docsMatch) return docsMatch\n logWarn(\n `Multiple VitePress source directories found (${matches\n .map((m) => path.relative(cwd, m))\n .join(', ')}) — pass an explicit \\`srcDir\\` option. Skipping page generation.`,\n )\n return undefined\n }\n return cwd\n}\n\n/**\n * Detects the VitePress project root — the directory containing the\n * `.vitepress` folder — so a relative `srcDir` from the wrapped config can be\n * resolved the same way VitePress resolves it.\n */\nexport function detectVitePressRoot(cwd: string): string {\n const srcDir = detectSrcDir(cwd)\n return srcDir && fs.existsSync(path.join(srcDir, '.vitepress')) ? srcDir : cwd\n}\n","import path from 'node:path'\nimport type { OpenSpecPluginOptions } from '../types.js'\nimport { detectSrcDir, findOpenSpecDir } from './detect.js'\n\n/**\n * Fully resolved and validated plugin options.\n */\nexport interface ResolvedOptions {\n /** Absolute path to the openspec/ directory */\n specDir: string\n /** Output directory name relative to srcDir (e.g. \"openspec\") */\n outDir: string\n /** Absolute VitePress source directory */\n srcDir: string\n /** Absolute output directory inside srcDir */\n absoluteOutDir: string\n}\n\n/**\n * Centralizes default resolution for all plugin entry points so\n * `generateOpenSpecPages()`, `openspec()` and `withOpenSpec()` behave\n * identically.\n *\n * Defaults are zero-config: `srcDir` falls back to the auto-detected\n * VitePress source directory (the folder containing `.vitepress`), and\n * `specDir` falls back to the nearest ancestor `openspec/` folder,\n * skipping generated output recognized by its marker.\n *\n * @throws if `outDir` is not a relative path inside `srcDir`.\n */\nexport function resolveOptions(\n userOptions: OpenSpecPluginOptions = {},\n fallbackSrcDir?: string,\n): ResolvedOptions {\n // Normalize Windows-style separators so traversal variants like\n // \"nested\\\\..\\\\..\\\\outside\" cannot bypass the containment check.\n const outDir = (userOptions.outDir ?? 'openspec').replace(/\\\\/g, '/')\n if (path.isAbsolute(outDir) || outDir === '' || outDir === '.' || outDir === '..') {\n throw new Error(\n `[vitepress-plugin-openspec] Invalid outDir \"${outDir}\": it must be a relative path inside the VitePress srcDir.`,\n )\n }\n const srcDir = userOptions.srcDir ?? fallbackSrcDir ?? detectSrcDir(process.cwd()) ?? process.cwd()\n const absoluteSrcDir = path.resolve(srcDir)\n const absoluteOutDir = path.resolve(absoluteSrcDir, outDir)\n const rel = path.relative(absoluteSrcDir, absoluteOutDir)\n if (rel.startsWith('..') || path.isAbsolute(rel) || rel === '') {\n throw new Error(\n `[vitepress-plugin-openspec] Invalid outDir \"${outDir}\": it resolves outside the VitePress srcDir.`,\n )\n }\n const specDir = userOptions.specDir ?? findOpenSpecDir(process.cwd(), absoluteOutDir) ?? './openspec'\n return {\n specDir: path.resolve(specDir),\n outDir,\n srcDir: absoluteSrcDir,\n absoluteOutDir,\n }\n}\n","import path from 'node:path'\nimport type { ResolvedOptions } from './options.js'\nimport { readManifest } from './generator.js'\n\n// Basenames of files the plugin always writes into the output tree.\nconst ALWAYS_GENERATED_BASENAMES = new Set(['index.md', '.gitignore', '.openspec-manifest.json'])\n// Artifact copies the plugin writes when the output tree is distinct\n// from the openspec source tree.\nconst ARTIFACT_BASENAMES = new Set(['proposal.md', 'design.md', 'tasks.md'])\n\nconst generatedDestCache = new Map<string, Set<string>>()\n\n/**\n * Resolved absolute destinations of all files recorded in the previous\n * run's manifest — i.e. paths the plugin itself wrote. Only these exact\n * destinations count as generated, never a basename heuristic, so real\n * source artifacts that live inside the output tree remain watchable.\n */\nfunction generatedDestinations(absoluteOutDir: string): Set<string> {\n const cached = generatedDestCache.get(absoluteOutDir)\n if (cached) return cached\n const set = new Set<string>()\n for (const entry of readManifest(absoluteOutDir)) {\n set.add(path.resolve(absoluteOutDir, entry))\n }\n generatedDestCache.set(absoluteOutDir, set)\n return set\n}\n\n/**\n * Invalidates the cached manifest destinations after a regeneration wrote\n * a new manifest.\n */\nexport function invalidateGeneratedDestinations(absoluteOutDir: string): void {\n generatedDestCache.delete(absoluteOutDir)\n}\n\nfunction isInside(parent: string, child: string): boolean {\n const rel = path.relative(parent, child)\n return !(rel.startsWith('..') || path.isAbsolute(rel))\n}\n\n/**\n * Layout classification for the overlapping specDir/outDir cases:\n * - 'equal': specDir and outDir are the same directory\n * - 'out-inside-spec': outDir is a proper child of specDir\n * - 'spec-inside-out': specDir is a proper child of outDir\n * - 'disjoint': no overlap\n */\nexport type LayoutRelation = 'equal' | 'out-inside-spec' | 'spec-inside-out' | 'disjoint'\n\nexport function classifyLayout(options: ResolvedOptions): LayoutRelation {\n if (options.specDir === options.absoluteOutDir) return 'equal'\n if (isInside(options.specDir, options.absoluteOutDir)) return 'out-inside-spec'\n if (isInside(options.absoluteOutDir, options.specDir)) return 'spec-inside-out'\n return 'disjoint'\n}\n\n/**\n * Whether a file inside the output tree was written by this plugin (as\n * opposed to an openspec source artifact that happens to live in the same\n * tree when specDir and outDir overlap).\n *\n * Layout rules (generated destinations never coincide with source files):\n * - 'equal': the shared tree only receives index.md/.gitignore/manifest\n * from the plugin; artifact-named files are sources.\n * - 'out-inside-spec' / 'disjoint': the plugin writes artifact copies into\n * the output tree; every known basename inside it is generated.\n * - 'spec-inside-out': source files live inside the output tree; files\n * inside specDir are sources, only files outside it are generated.\n */\nexport function isPluginGeneratedFile(options: ResolvedOptions, absFile: string): boolean {\n if (!isInside(options.absoluteOutDir, absFile)) return false\n // Only exact destinations recorded in the generation manifest are\n // generated output — never a basename heuristic. This keeps real source\n // artifacts inside an overlapping output tree watchable.\n if (generatedDestinations(options.absoluteOutDir).has(path.resolve(absFile))) return true\n const base = path.basename(absFile)\n switch (classifyLayout(options)) {\n case 'equal':\n return ALWAYS_GENERATED_BASENAMES.has(base)\n case 'out-inside-spec':\n // The output tree is nested inside specDir, so a basename match can\n // hit real source files too. Only the exact destinations recorded\n // in the manifest (checked above) plus the always-generated\n // top-level markers count as plugin output.\n return ALWAYS_GENERATED_BASENAMES.has(base) && !isInside(options.specDir, absFile)\n case 'disjoint':\n return ALWAYS_GENERATED_BASENAMES.has(base) || ARTIFACT_BASENAMES.has(base)\n case 'spec-inside-out':\n return !isInside(options.specDir, absFile) &&\n (ALWAYS_GENERATED_BASENAMES.has(base) || ARTIFACT_BASENAMES.has(base))\n }\n}\n\n/**\n * Whether a watch event for this file should trigger regeneration of the\n * openspec pages. True for openspec source files (including\n * `.openspec.yaml`), false for files the plugin itself generated.\n */\nexport function isSourceArtifactEvent(options: ResolvedOptions, absFile: string): boolean {\n if (!isInside(options.specDir, absFile)) return false\n return !isPluginGeneratedFile(options, absFile)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { load as yamlLoad } from 'js-yaml'\nimport type { CapabilitySpec, Change, ChangeArtifact, OpenSpecFolder } from '../types.js'\n\nconst ARTIFACT_NAMES: ChangeArtifact[] = ['proposal', 'design', 'tasks']\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\nexport function 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 return ARTIFACT_NAMES.filter((name) => fs.existsSync(path.join(dir, `${name}.md`)))\n}\n\nfunction isDirectory(dir: string, name: string): boolean {\n return fs.existsSync(path.join(dir, name, '.openspec.yaml'))\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 (!isDirectory(changeDir, '.')) 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 const meta = readOpenSpecYaml(changeDir)\n const match = entry.name.match(/^(\\d{4}-\\d{2}-\\d{2})-(.+)$/)\n archivedChanges.push({\n name: match?.[2] ?? entry.name,\n title: meta.title ? String(meta.title) : undefined,\n dir: changeDir,\n artifacts: readArtifacts(changeDir),\n createdDate: formatDate(meta.created),\n archivedDate: match?.[1],\n archiveFolderName: entry.name,\n })\n }\n }\n\n return { dir: resolved, specs, changes, archivedChanges }\n}\n","import path from 'node:path'\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 * Links that point outside the openspec root, absolute paths, HTTP URLs, and\n * anchor-only links are left unchanged.\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 return content.replace(\n /(\\[[^\\]]*\\])\\(([^)]+)\\)/g,\n (_match, linkText: string, urlPart: string) => {\n const titleMatch = urlPart.match(/^(.+?)(\\s+[\"'][^\"']*[\"'])?\\s*$/)\n if (!titleMatch) return _match\n const rawUrl = titleMatch[1].trim()\n const title = titleMatch[2] ?? ''\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 const hashIdx = rawUrl.indexOf('#')\n const urlWithoutFragment = hashIdx >= 0 ? rawUrl.slice(0, hashIdx) : rawUrl\n const fragment = hashIdx >= 0 ? rawUrl.slice(hashIdx) : ''\n if (!urlWithoutFragment) {\n return _match\n }\n const resolvedPath = path.resolve(srcDir, urlWithoutFragment)\n const relToOpenspec = path.relative(openspecRootDir, resolvedPath)\n if (relToOpenspec.startsWith('..') || path.isAbsolute(relToOpenspec)) {\n return _match\n }\n const vitePath = relToOpenspec.replace(/\\.md$/, '').replace(/\\\\/g, '/')\n const absoluteLink = `/${outDir}/${vitePath}${fragment}`\n return `${linkText}(${absoluteLink}${title})`\n },\n )\n}\n","import type { CapabilitySpec } from '../types.js'\nimport { humanizeLabel } from './reader.js'\n\nexport function 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, '\\\\$1')\n}\n\nexport function 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 return stripped.replace(/\\n{3,}/g, '\\n\\n')\n}\n\nexport function transformScenarios(content: string): string {\n const lines = content.split('\\n')\n const result: string[] = []\n let inScenario = false\n for (const line of lines) {\n const scenarioMatch = line.match(/^#### Scenario: (.+)$/)\n const isHeading = /^#{1,6} /.test(line)\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 if (inScenario) result.push(':::')\n return result.join('\\n')\n}\n\nexport function specTitle(spec: CapabilitySpec): string {\n return spec.title ?? humanizeLabel(spec.name)\n}\n","import type { CapabilitySpec, Change, OpenSpecFolder } from '../types.js'\nimport { humanizeLabel } from './reader.js'\nimport { extractSpecDescription, specTitle, stripDeltaMarkers, transformScenarios } from './markdown.js'\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(`# ${specTitle(spec)}`)\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(`- [${specTitle(spec)}](/${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 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 if (folder.archivedChanges.length > 0) {\n lines.push('')\n lines.push('## Archive')\n lines.push('')\n for (const change of folder.archivedChanges) {\n const date = change.archivedDate ? ` *(archived: ${change.archivedDate})*` : ''\n lines.push(\n `- [${change.title ?? humanizeLabel(change.name)}](/${outDir}/changes/archive/${change.archiveFolderName}/)${date}`,\n )\n }\n }\n lines.push('')\n return lines.join('\\n')\n}\n\n/**\n * Generates the root index page of the openspec documentation section.\n */\nexport function generateRootIndexPage(outDir: string): string {\n return [\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}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { invalidateGeneratedDestinations } from './watch.js'\nimport type { Change } from '../types.js'\nimport type { ResolvedOptions } from './options.js'\nimport { logError, logInfo, logWarn } from './logger.js'\nimport { readOpenSpecFolder } from './reader.js'\nimport { rewriteRelativeLinks } from './links.js'\nimport {\n generateChangeIndexPage,\n generateChangesIndexPage,\n generateRootIndexPage,\n generateSpecPage,\n generateSpecsIndexPage,\n} from './pages.js'\n\nexport const MANIFEST_FILE = '.openspec-manifest.json'\nconst GITIGNORE_CONTENT = '# Generated by vitepress-plugin-openspec — do not commit generated files.\\n*\\n!.gitignore\\n'\n\ninterface OutputFile {\n /** Path relative to absoluteOutDir, using forward slashes */\n rel: string\n content: string\n}\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 toRel(absoluteOutDir: string, filePath: string): string {\n return path.relative(absoluteOutDir, filePath).split(path.sep).join('/')\n}\n\nfunction pruneEmptyDirs(rootDir: string, startDir: string): void {\n let dir = startDir\n while (dir.startsWith(rootDir) && dir !== rootDir) {\n try {\n if (fs.readdirSync(dir).length > 0) break\n fs.rmdirSync(dir)\n } catch {\n break\n }\n dir = path.dirname(dir)\n }\n}\n\n/**\n * Reads the previous run's manifest and deletes all recorded files.\n * Runs only after the replacement generation has been fully read and\n * rendered in memory, so a failing source read never destroys the last\n * successful output. Because cleanup precedes writing the new files, a\n * stale entry can never resolve to a freshly written page, even for\n * case-only renames on case-insensitive filesystems.\n *\n * @returns entries whose deletion failed; they are retained in the next\n * manifest so cleanup retries instead of forgetting them.\n */\nfunction cleanupPreviousManifest(rootDir: string): string[] {\n const manifestPath = path.join(rootDir, MANIFEST_FILE)\n if (!fs.existsSync(manifestPath)) return []\n let previous: string[] = []\n try {\n const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as unknown\n if (Array.isArray(parsed)) previous = parsed.filter((f): f is string => typeof f === 'string')\n } catch {\n // Unreadable manifest: treat as empty\n return []\n }\n const retained: string[] = []\n for (const entry of previous) {\n const entryPath = path.resolve(rootDir, entry)\n const rel = path.relative(rootDir, entryPath)\n if (rel.startsWith('..') || path.isAbsolute(rel)) continue\n try {\n if (fs.existsSync(entryPath)) {\n fs.rmSync(entryPath)\n pruneEmptyDirs(rootDir, path.dirname(entryPath))\n }\n } catch {\n // Deletion failed (e.g. locked file): retry on the next run\n retained.push(entry)\n }\n }\n return retained\n}\n\nexport function readManifest(rootDir: string): string[] {\n try {\n const parsed = JSON.parse(fs.readFileSync(path.join(rootDir, MANIFEST_FILE), 'utf-8')) as unknown\n if (Array.isArray(parsed)) return parsed.filter((f): f is string => typeof f === 'string')\n } catch {\n // Unreadable or missing manifest: treat as empty\n }\n return []\n}\n\nfunction writeManifest(files: string[], rootDir: string): void {\n const manifestPath = path.join(rootDir, MANIFEST_FILE)\n try {\n writeFile(manifestPath, JSON.stringify(files, null, 2))\n invalidateGeneratedDestinations(rootDir)\n } catch {\n // Best-effort: never fail generation because of the manifest\n }\n}\n\nfunction renderChangePages(\n change: Change,\n options: ResolvedOptions,\n isArchived: boolean,\n): OutputFile[] {\n const subPath = isArchived\n ? path.join('changes', 'archive', change.archiveFolderName ?? change.name)\n : path.join('changes', change.name)\n const changeOutDir = path.join(options.absoluteOutDir, subPath)\n const files: OutputFile[] = []\n\n files.push({\n rel: toRel(options.absoluteOutDir, path.join(changeOutDir, 'index.md')),\n content: generateChangeIndexPage(change, options.outDir),\n })\n\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 // When specDir and outDir overlap, never copy a file onto itself\n if (path.resolve(srcFile) === path.resolve(destFile)) continue\n const content = fs.readFileSync(srcFile, 'utf-8')\n files.push({\n rel: toRel(options.absoluteOutDir, destFile),\n content: rewriteRelativeLinks(content, srcFile, options.specDir, options.outDir),\n })\n }\n return files\n}\n\n/**\n * Reads the openspec directory and renders every output page into memory.\n * All source file access happens here, before any destructive step, so\n * an inconsistent source tree cannot destroy the previous output.\n */\nfunction renderAllPages(options: ResolvedOptions): OutputFile[] {\n const folder = readOpenSpecFolder(options.specDir)\n const files: OutputFile[] = []\n\n for (const spec of folder.specs) {\n const dest = path.join(options.absoluteOutDir, 'specs', spec.name, 'index.md')\n files.push({ rel: toRel(options.absoluteOutDir, dest), content: generateSpecPage(spec) })\n }\n files.push({\n rel: 'specs/index.md',\n content: generateSpecsIndexPage(folder.specs, options.outDir),\n })\n\n for (const change of folder.changes) {\n files.push(...renderChangePages(change, options, false))\n }\n for (const change of folder.archivedChanges) {\n files.push(...renderChangePages(change, options, true))\n }\n\n files.push({\n rel: 'changes/index.md',\n content: generateChangesIndexPage(folder, options.outDir),\n })\n files.push({\n rel: 'index.md',\n content: generateRootIndexPage(options.outDir),\n })\n\n return files\n}\n\n/**\n * Synchronously generates all VitePress Markdown pages from the openspec/\n * directory and writes them to disk, removing stale output from previous runs.\n *\n * @returns true when pages were written; false when generation was skipped\n * (missing or unreadable source) or failed.\n */\nexport function generatePages(options: ResolvedOptions): boolean {\n // Remove stale output from the previous run even when the source\n // directory has disappeared, so published pages do not linger forever.\n if (!fs.existsSync(options.specDir)) {\n logWarn(\n `openspec directory not found: ${path.relative(options.srcDir, options.specDir)} — skipping page generation`,\n )\n const retained = cleanupPreviousManifest(options.absoluteOutDir)\n if (retained.length > 0 || fs.existsSync(options.absoluteOutDir)) {\n writeManifest(retained, options.absoluteOutDir)\n }\n return false\n }\n\n // Phase 1: read sources and render everything in memory. A failure here\n // leaves the last successful output untouched.\n let files: OutputFile[]\n try {\n files = renderAllPages(options)\n } catch (err) {\n logError(`Failed to process openspec directory \"${options.specDir}\": ${String(err)}`)\n return false\n }\n\n // Phase 2: destructive cleanup of the previous output, now that the\n // replacement generation is complete and safe to write.\n const retained = cleanupPreviousManifest(options.absoluteOutDir)\n\n // Phase 3: write the new pages. The self-managed .gitignore marker goes\n // first so even an interrupted run leaves the output recognizable as\n // generated output — never mistaken for the openspec source.\n try {\n writeFile(path.join(options.absoluteOutDir, '.gitignore'), GITIGNORE_CONTENT)\n for (const file of files) {\n writeFile(path.join(options.absoluteOutDir, file.rel), file.content)\n }\n writeManifest([...files.map((f) => f.rel), ...retained], options.absoluteOutDir)\n } catch (err) {\n logError(`Failed to write openspec pages: ${String(err)}`)\n return false\n }\n\n logInfo(`Generated docs from ${options.specDir}: ${files.length} file(s)`)\n return true\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { NavItem, SidebarItem } from '../types.js'\nimport { logWarn } from './logger.js'\nimport { humanizeLabel, readOpenSpecFolder } from './reader.js'\nimport { specTitle } from './markdown.js'\n\nfunction changeItems(change: { name: string; archiveFolderName?: string; artifacts: string[] }, 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 logWarn(\n `openspec directory not found: ${path.relative(process.cwd(), path.resolve(specDir))} — skipping sidebar generation`,\n )\n return []\n }\n const folder = readOpenSpecFolder(specDir)\n const groups: SidebarItem[] = []\n\n groups.push({\n text: 'Specifications',\n collapsed: false,\n items: [\n { text: 'Overview', link: `/${outDir}/specs/` },\n ...folder.specs.map((s) => ({ text: specTitle(s), link: `/${outDir}/specs/${s.name}/` })),\n ],\n })\n\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 if (folder.archivedChanges.length > 0) {\n groups.push({\n text: 'Archive',\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 logWarn(\n `openspec directory not found: ${path.relative(process.cwd(), path.resolve(specDir))} — skipping nav generation`,\n )\n return null\n }\n return {\n text: options.text ?? 'Docs',\n link: `/${outDir}/`,\n }\n}\n","/**\n * Options for the `withOpenSpec()` config helper.\n * Extends `OpenSpecPluginOptions` with optional nav/sidebar merge controls.\n */\nexport interface WithOpenSpecOptions extends OpenSpecPluginOptions {\n /**\n * Whether to prepend an openspec nav entry to `themeConfig.nav`.\n * @default true\n */\n nav?: boolean\n\n /**\n * Whether to inject the openspec sidebar section into `themeConfig.sidebar`.\n * @default true\n */\n sidebar?: boolean\n /**\n * Label for the nav entry injected into `themeConfig.nav`.\n * @default 'Docs'\n */\n navText?: string\n}\n\n/**\n * Configuration options for the vitepress-plugin-openspec plugin.\n */\nexport interface OpenSpecPluginOptions {\n /**\n * Path to the openspec/ directory of the project.\n *\n * By default the plugin walks up from the current working directory looking\n * for an `openspec/` folder (skipping generated output recognized by its\n * marker), so no configuration is needed when it lives at the project root.\n * Set an explicit path only for custom locations.\n *\n * If the directory does not exist a warning is printed and the build continues\n * without generating any pages or nav/sidebar entries — no error is thrown.\n * An invalid `outDir` (absolute, empty, or escaping `srcDir`) throws instead.\n *\n * @default auto-detected (`<nearest ancestor>/openspec`, falling back to `'./openspec'`)\n * @example\n * // Resolving from docs/.vitepress/config.ts\n * import path from 'node:path'\n * import { fileURLToPath } from 'node:url'\n * const __dirname = path.dirname(fileURLToPath(import.meta.url))\n * const specDir = path.resolve(__dirname, '../../openspec')\n */\n specDir?: string\n\n /**\n * Output directory (relative to VitePress `srcDir`) where the generated\n * Markdown pages will be written.\n * @default 'openspec'\n */\n outDir?: string\n\n /**\n * VitePress source directory — the directory containing your `.md` files\n * (i.e. the `docs/` folder). By default the plugin detects the directory that\n * contains `.vitepress` (the working directory, a first-level subdirectory\n * such as `docs/`, or the parent when the config is evaluated from inside\n * `docs/.vitepress/`), so no configuration is needed for standard layouts.\n *\n * @default auto-detected (directory containing `.vitepress`, falling back to the working directory)\n * @example path.resolve(__dirname, '..') // from docs/.vitepress/config.ts\n */\n srcDir?: string\n}\n\n/**\n * A canonical capability specification from openspec/specs/<name>/spec.md\n */\nexport interface CapabilitySpec {\n /** Folder name (kebab-case capability identifier) */\n name: string\n /** Optional display title from spec.md frontmatter. Overrides humanized name. */\n title?: string\n /** Absolute path to the spec.md file */\n specPath: string\n /** Raw Markdown content of the spec */\n content: string\n}\n\n/**\n * A single artifact (file) belonging to a Change.\n */\nexport type ChangeArtifact = 'proposal' | 'design' | 'tasks'\n\n/**\n * An OpenSpec change (active or archived).\n */\nexport interface Change {\n /** Change directory name (e.g. \"my-feature\" or for archived: \"my-feature\" extracted from \"2026-03-10-my-feature\") */\n name: string\n /** Optional display title from .openspec.yaml. Overrides humanized name. */\n title?: string\n /** Absolute path to the change directory */\n dir: string\n /** Which artifact files are present */\n artifacts: ChangeArtifact[]\n /** Creation date from .openspec.yaml, if available */\n createdDate?: string\n /** For archived changes: the archive date (YYYY-MM-DD) parsed from directory name */\n archivedDate?: string\n /**\n * For archived changes: the original archive folder name (e.g. \"2026-01-15-my-feature\" or\n * \"legacy-feature\" for non-standard names). Used to build correct archive URLs.\n */\n archiveFolderName?: string\n}\n\n/**\n * The full parsed structure of an openspec/ directory.\n */\nexport interface OpenSpecFolder {\n /** Absolute path to the openspec/ root */\n dir: string\n /** Canonical capability specs from openspec/specs/ */\n specs: CapabilitySpec[]\n /** Active changes from openspec/changes/ (excluding archive/) */\n changes: Change[]\n /** Archived changes from openspec/changes/archive/ */\n archivedChanges: Change[]\n}\n\n/**\n * A nav item compatible with VitePress `DefaultTheme.NavItem`.\n */\nexport interface NavItem {\n text: string\n link: string\n}\n\n/**\n * A sidebar item compatible with VitePress `DefaultTheme.SidebarItem`.\n */\nexport interface SidebarItem {\n text: string\n link?: string\n collapsed?: boolean\n items?: SidebarItem[]\n}\n\n/**\n * Shape of the VitePress extension that Vite attaches to the resolved\n * config object (`server.config.vitepress`). VitePress itself attaches its\n * resolved `SiteConfig` under `vitepress.site`; the flat `themeConfig`\n * variant only exists in manually built Vite configs (unit tests), so both\n * locations are supported.\n */\nexport interface VitepressExtension {\n /** VitePress srcDir, when resolved from a real VitePress context */\n srcDir?: string\n /** Resolved VitePress site config (production and dev server) */\n site?: { themeConfig?: Record<string, unknown> }\n /** Flat theme config as built by unit tests constructing a Vite config manually */\n themeConfig?: Record<string, unknown>\n}\n\n/** Extracts the VitePress extension from a Vite `ResolvedConfig`-like object. */\nexport function getVitepressExtension(\n resolvedConfig: unknown,\n): VitepressExtension | undefined {\n return (resolvedConfig as { vitepress?: VitepressExtension }).vitepress\n}\n","import path from 'node:path'\nimport type { ViteDevServer } from 'vite'\nimport type { ResolvedOptions } from './options.js'\nimport { generatePages } from './generator.js'\nimport { readOpenSpecFolder } from './reader.js'\nimport { generateOpenSpecSidebar } from './navigation.js'\nimport { invalidateGeneratedDestinations } from './watch.js'\nimport { getVitepressExtension } from '../types.js'\n\n/**\n * Compact fingerprint of everything that feeds the sidebar and nav:\n * spec and change names, titles, dates, and artifact lists. Comparing\n * signatures before and after an edit tells us whether the navigation\n * config changed and the dev server needs a full restart.\n */\nexport function readNavigationSignature(options: ResolvedOptions): string {\n try {\n const folder = readOpenSpecFolder(options.specDir)\n return JSON.stringify({\n specs: folder.specs.map((s) => [s.name, s.title ?? null]),\n changes: folder.changes.map((c) => [c.name, c.title ?? null, c.createdDate ?? null, c.artifacts]),\n archived: folder.archivedChanges.map((c) => [c.name, c.title ?? null, c.archivedDate ?? null, c.artifacts]),\n })\n } catch {\n return 'unreadable'\n }\n}\n\n/**\n * Updates the sidebar and nav entries inside the in-memory VitePress\n * theme config that `withOpenSpec()` created. `server.restart(true)` only\n * re-creates Vite from the already-resolved inline configuration, so it\n * never re-runs `withOpenSpec()`; mutating the live themeConfig object\n * before the restart is what actually refreshes the navigation.\n *\n * The live theme config lives on the VitePress `SiteConfig` object exposed\n * as `server.config.vitepress.site.themeConfig` (VitePress resolves its\n * site config before creating Vite). The flat `server.config.vitepress`\n * object only exists in unit tests that build a Vite config manually, so\n * both locations are supported.\n */\nexport function updateNavigationInMemory(\n options: ResolvedOptions,\n server: ViteDevServer,\n ownsSidebarEntry: boolean,\n): void {\n if (!ownsSidebarEntry) return\n const vp = getVitepressExtension(server.config)\n const themeConfig = vp?.site?.themeConfig ?? vp?.themeConfig\n if (!themeConfig) return\n const sidebarKey = `/${options.outDir}/`\n const items = generateOpenSpecSidebar(options.specDir, { outDir: options.outDir })\n const sidebar = (themeConfig.sidebar ?? {}) as Record<string, unknown>\n if (items.length > 0) {\n sidebar[sidebarKey] = items\n themeConfig.sidebar = sidebar\n } else {\n delete sidebar[sidebarKey]\n themeConfig.sidebar = sidebar\n }\n}\n\nexport function createScheduler() {\n let timer: ReturnType<typeof setTimeout> | undefined\n return {\n schedule(options: ResolvedOptions, server: ViteDevServer): void {\n // Debounce: editors and archive operations often emit event bursts\n if (timer) clearTimeout(timer)\n timer = setTimeout(() => {\n timer = undefined\n generatePages(options)\n invalidateGeneratedDestinations(options.absoluteOutDir)\n server.ws.send({ type: 'full-reload' })\n }, 100)\n },\n cancel(): void {\n if (timer) {\n clearTimeout(timer)\n timer = undefined\n }\n },\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { Plugin } from 'vite'\nimport type { ResolvedOptions } from './lib/options.js'\nimport type { OpenSpecPluginOptions, WithOpenSpecOptions } from './types.js'\nimport { PLUGIN_NAME, logWarn } from './lib/logger.js'\nimport { resolveOptions } from './lib/options.js'\nimport { generatePages } from './lib/generator.js'\nimport { openspecNav, generateOpenSpecSidebar } from './lib/navigation.js'\nimport { isSourceArtifactEvent } from './lib/watch.js'\nimport { createScheduler, readNavigationSignature, updateNavigationInMemory } from './lib/dev-server.js'\nimport { detectSrcDir, detectVitePressRoot } from './lib/detect.js'\nimport { getVitepressExtension } from './types.js'\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. In most cases `withOpenSpec()` (which calls this\n * internally) is the simpler integration point.\n *\n * @returns true when pages were written; false when generation was skipped\n * (missing or unreadable source, ambiguous source-directory detection) or\n * failed.\n * @throws if `outDir` is not a relative path inside `srcDir` (absolute,\n * traversal, or empty).\n */\nexport function generateOpenSpecPages(userOptions: OpenSpecPluginOptions = {}): boolean {\n // When source-directory detection is ambiguous (multiple .vitepress\n // folders at the same level), detectSrcDir has already warned; skip\n // generation instead of writing into the common parent.\n const detectedSrcDir = userOptions.srcDir ?? detectSrcDir(process.cwd())\n if (!detectedSrcDir) return false\n const options = resolveOptions(userOptions, detectedSrcDir)\n return generatePages(options)\n}\n\n/**\n * Vite plugin that regenerates the openspec documentation pages whenever a\n * file inside the openspec/ directory changes. This makes `vitepress dev`\n * pick up spec edits without a manual restart.\n *\n * For the pages to be available on the first build (including CI), the pages\n * are generated once in `configResolved`. When using `withOpenSpec()` this\n * plugin is wired up automatically.\n */\nexport function openspec(userOptions: OpenSpecPluginOptions = {}): Plugin {\n let resolvedOptions: ResolvedOptions | undefined\n let ownsSidebarEntry = false\n let detachListeners: (() => void) | undefined\n\n return {\n name: PLUGIN_NAME,\n enforce: 'pre',\n\n configResolved(resolvedConfig) {\n detachListeners?.()\n const vpConfig = getVitepressExtension(resolvedConfig)\n const srcDir =\n userOptions.srcDir ?? vpConfig?.srcDir ?? resolvedConfig.root ?? process.cwd()\n try {\n resolvedOptions = resolveOptions(userOptions, srcDir)\n } catch (err) {\n logWarn(String(err))\n return\n }\n if (!fs.existsSync(resolvedOptions.specDir)) {\n logWarn(\n `openspec directory not found: ${resolvedOptions.specDir} — skipping page generation`,\n )\n // Still run generatePages so previously generated pages recorded in\n // the manifest are cleaned up when the source directory disappears.\n generatePages(resolvedOptions)\n resolvedOptions = undefined\n return\n }\n generatePages(resolvedOptions)\n },\n\n configureServer(server) {\n if (!resolvedOptions || !fs.existsSync(resolvedOptions.specDir)) return\n const options = resolvedOptions\n // Use Vite's own watcher: it is supported on all Node versions and\n // platforms declared by this package (unlike recursive fs.watch).\n // Ensure the openspec directory is watched even when it lives outside\n // the Vite root (the documented docs/ + openspec/ layout).\n server.watcher.add(options.specDir)\n const scheduler = createScheduler()\n let navigationSignature = readNavigationSignature(options)\n const onWatchEvent = (event: 'change' | 'add' | 'unlink', file: string) => {\n const absFile = path.resolve(file)\n if (!isSourceArtifactEvent(options, absFile)) return\n // Structural changes (files added or removed) and metadata edits\n // (.openspec.yaml, spec/change titles) also alter the sidebar and\n // nav, which are derived from the config; a full server restart\n // regenerates both pages and navigation. Plain content edits take\n // the fast regenerate+reload path unless a title changed.\n const signature = readNavigationSignature(options)\n const affectsNavigation = event !== 'change' || signature !== navigationSignature\n if (affectsNavigation) {\n scheduler.cancel()\n updateNavigationInMemory(options, server, ownsSidebarEntry)\n navigationSignature = signature\n server.restart(true)\n } else {\n scheduler.schedule(options, server)\n }\n }\n const onChange = (f: string) => onWatchEvent('change', f)\n const onAdd = (f: string) => onWatchEvent('add', f)\n const onUnlink = (f: string) => onWatchEvent('unlink', f)\n server.watcher.on('change', onChange)\n server.watcher.on('add', onAdd)\n server.watcher.on('unlink', onUnlink)\n // Unregister listeners when the dev server shuts down. Closing the\n // shared chokidar instance would break Vite itself, so we only detach.\n // The same detach runs from closeBundle so consecutive builds\n // (e.g. `vitepress build --watch` or quick relaunches) cannot\n // accumulate duplicate listeners.\n detachListeners = () => {\n scheduler.cancel()\n server.watcher.off('change', onChange)\n server.watcher.off('add', onAdd)\n server.watcher.off('unlink', onUnlink)\n server.httpServer?.removeListener('close', detachListeners!)\n detachListeners = undefined\n }\n server.httpServer?.once('close', detachListeners)\n },\n\n closeBundle() {\n detachListeners?.()\n detachListeners = undefined\n },\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 * When the VitePress source directory cannot be detected unambiguously\n * (multiple `.vitepress` folders at the same level), a warning is emitted and\n * the config is returned with only the sidebar shape normalized — nothing is\n * generated or injected.\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 * @throws if `outDir` is not a relative path inside `srcDir` (absolute, traversal, or empty).\n */\nexport function withOpenSpec<T extends Record<string, unknown>>(\n config: T,\n options: WithOpenSpecOptions = {},\n): T {\n const cwd = process.cwd()\n // Resolve a relative srcDir from the wrapped config the same way\n // VitePress resolves it: against the detected project root.\n const configSrcDir =\n typeof config.srcDir === 'string' && config.srcDir\n ? path.resolve(detectVitePressRoot(cwd), config.srcDir)\n : undefined\n const detectedSrcDir = options.srcDir ?? configSrcDir ?? detectSrcDir(cwd)\n const result = { ...config } as Record<string, unknown>\n const themeConfig = (result.themeConfig ?? {}) as Record<string, unknown>\n // Normalize an array-based (single-sidebar) config to the object form so\n // the injected section always lands under its route key — also when\n // generation is skipped below.\n if (Array.isArray(themeConfig.sidebar)) {\n themeConfig.sidebar = { '/': themeConfig.sidebar }\n }\n result.themeConfig = themeConfig\n // When source-directory detection is ambiguous, detectSrcDir has already\n // warned; skip generation and integration instead of writing into the\n // common parent of multiple VitePress sites.\n if (detectedSrcDir === undefined) return result as T\n\n let resolved: ResolvedOptions\n try {\n resolved = resolveOptions(options, detectedSrcDir)\n } catch (err) {\n logWarn(String(err))\n return result as T\n }\n\n const generated = generatePages(resolved)\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({ ...options })] }\n\n // --- Nav ---\n if (generated && options.nav !== false) {\n const navEntry = openspecNav(resolved.specDir, {\n outDir: resolved.outDir,\n text: options.navText,\n })\n const existingNav = (themeConfig.nav as unknown[]) ?? []\n themeConfig.nav = navEntry ? [navEntry, ...existingNav] : existingNav\n }\n\n // --- Sidebar ---\n const sidebarKey = `/${resolved.outDir}/`\n const existingSidebar = (themeConfig.sidebar ?? {}) as Record<string, unknown>\n // The plugin only owns (and the watcher only updates) an entry it created\n // itself; a pre-existing custom entry for this route is preserved as-is.\n const pluginOwnsSidebarEntry = generated && options.sidebar !== false && !existingSidebar[sidebarKey]\n if (pluginOwnsSidebarEntry) {\n const items = generateOpenSpecSidebar(resolved.specDir, { outDir: resolved.outDir })\n if (items.length > 0) {\n themeConfig.sidebar = { ...existingSidebar, [sidebarKey]: items }\n }\n }\n\n result.themeConfig = themeConfig\n return result as T\n}\n\nexport default openspec\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../src/lib/dev-server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../src/lib/dev-server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAOnD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAWxE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,aAAa,EACrB,gBAAgB,EAAE,OAAO,GACxB,IAAI,CAeN;AAED,wBAAgB,eAAe;IAG3B,QAAQ,UAAU,eAAe,UAAU,aAAa,GAAG,IAAI;IAU/D,MAAM,IAAI,IAAI;EAOjB"}
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAElC,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAElC,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAU5E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,GAAE,qBAA0B,GAAG,OAAO,CAQtF;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,WAAW,GAAE,qBAA0B,GAAG,MAAM,CAyFxE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5D,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,mBAAwB,GAChC,CAAC,CA+DH;eAEc,QAAQ"}
|
package/dist/types.d.ts
CHANGED
|
@@ -130,4 +130,23 @@ export interface SidebarItem {
|
|
|
130
130
|
collapsed?: boolean;
|
|
131
131
|
items?: SidebarItem[];
|
|
132
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Shape of the VitePress extension that Vite attaches to the resolved
|
|
135
|
+
* config object (`server.config.vitepress`). VitePress itself attaches its
|
|
136
|
+
* resolved `SiteConfig` under `vitepress.site`; the flat `themeConfig`
|
|
137
|
+
* variant only exists in manually built Vite configs (unit tests), so both
|
|
138
|
+
* locations are supported.
|
|
139
|
+
*/
|
|
140
|
+
export interface VitepressExtension {
|
|
141
|
+
/** VitePress srcDir, when resolved from a real VitePress context */
|
|
142
|
+
srcDir?: string;
|
|
143
|
+
/** Resolved VitePress site config (production and dev server) */
|
|
144
|
+
site?: {
|
|
145
|
+
themeConfig?: Record<string, unknown>;
|
|
146
|
+
};
|
|
147
|
+
/** Flat theme config as built by unit tests constructing a Vite config manually */
|
|
148
|
+
themeConfig?: Record<string, unknown>;
|
|
149
|
+
}
|
|
150
|
+
/** Extracts the VitePress extension from a Vite `ResolvedConfig`-like object. */
|
|
151
|
+
export declare function getVitepressExtension(resolvedConfig: unknown): VitepressExtension | undefined;
|
|
133
152
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,mBAAoB,SAAQ,qBAAqB;IAChE;;;OAGG;IACH,GAAG,CAAC,EAAE,OAAO,CAAA;IAEb;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAA;IACZ,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAA;IAChB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE5D;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,qHAAqH;IACrH,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAA;IACX,uCAAuC;IACvC,SAAS,EAAE,cAAc,EAAE,CAAA;IAC3B,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAA;IACX,sDAAsD;IACtD,KAAK,EAAE,cAAc,EAAE,CAAA;IACvB,iEAAiE;IACjE,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,sDAAsD;IACtD,eAAe,EAAE,MAAM,EAAE,CAAA;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,KAAK,CAAC,EAAE,WAAW,EAAE,CAAA;CACtB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,mBAAoB,SAAQ,qBAAqB;IAChE;;;OAGG;IACH,GAAG,CAAC,EAAE,OAAO,CAAA;IAEb;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAA;IACZ,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAA;IAChB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE5D;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,qHAAqH;IACrH,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAA;IACX,uCAAuC;IACvC,SAAS,EAAE,cAAc,EAAE,CAAA;IAC3B,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAA;IACX,sDAAsD;IACtD,KAAK,EAAE,cAAc,EAAE,CAAA;IACvB,iEAAiE;IACjE,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,sDAAsD;IACtD,eAAe,EAAE,MAAM,EAAE,CAAA;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,KAAK,CAAC,EAAE,WAAW,EAAE,CAAA;CACtB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,iEAAiE;IACjE,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAA;IAChD,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACtC;AAED,iFAAiF;AACjF,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,OAAO,GACtB,kBAAkB,GAAG,SAAS,CAEhC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stritti/vitepress-plugin-openspec",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "A VitePress plugin that integrates OpenSpec documentation into your VitePress site",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openspec",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"lint": "tsc --noEmit",
|
|
38
38
|
"prepublishOnly": "npm run build",
|
|
39
39
|
"test": "vitest run",
|
|
40
|
+
"test:coverage": "vitest run --coverage",
|
|
40
41
|
"test:watch": "vitest",
|
|
41
42
|
"docs:dev": "cd docs && bun run dev",
|
|
42
43
|
"docs:build": "cd docs && bun run build"
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
53
54
|
"@types/js-yaml": "^4.0.9",
|
|
54
55
|
"@types/node": "^26.6.4",
|
|
56
|
+
"@vitest/coverage-v8": "^5.0.3",
|
|
55
57
|
"semantic-release": "^25.0.3",
|
|
56
58
|
"tsup": "^8.5.1",
|
|
57
59
|
"typescript": "^7.0.2",
|