@stritti/vitepress-plugin-openspec 0.8.4 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +65 -76
  2. package/package.json +8 -6
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @stritti/vitepress-plugin-openspec
2
2
 
3
- A [VitePress](https://vitepress.dev/) plugin that renders your project's [OpenSpec](https://openspec.dev/) folder as structured documentation pages — specs, changes, and artifacts — with sidebar and nav integration.
3
+ A [VitePress](https://vitepress.dev/) plugin that renders your [OpenSpec](https://openspec.dev/) folder as structured documentation pages with automatic sidebar and navigation integration.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@stritti/vitepress-plugin-openspec?style=flat-square&color=cb3837&logo=npm)](https://www.npmjs.com/package/@stritti/vitepress-plugin-openspec)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/@stritti/vitepress-plugin-openspec?style=flat-square&color=cb3837&logo=npm)](https://www.npmjs.com/package/@stritti/vitepress-plugin-openspec)
@@ -9,7 +9,20 @@ A [VitePress](https://vitepress.dev/) plugin that renders your project's [OpenSp
9
9
 
10
10
  ---
11
11
 
12
- ## Installation
12
+ ## What is OpenSpec?
13
+
14
+ [OpenSpec](https://openspec.dev/) is a specification format that organizes your project documentation into capabilities and changes. It structures your docs into:
15
+ - **Specs** – Capability specifications in `openspec/specs/<capability>/spec.md`
16
+ - **Changes** – Proposed changes with artifacts in `openspec/changes/<name>/`
17
+ - **Archive** – Completed changes in `openspec/changes/archive/`
18
+
19
+ This plugin renders your OpenSpec folder as navigable VitePress documentation pages.
20
+
21
+ ---
22
+
23
+ ## Quick Start
24
+
25
+ ### Install
13
26
 
14
27
  ```bash
15
28
  npm install @stritti/vitepress-plugin-openspec
@@ -17,76 +30,82 @@ npm install @stritti/vitepress-plugin-openspec
17
30
  bun add @stritti/vitepress-plugin-openspec
18
31
  ```
19
32
 
20
- ---
21
-
22
- ## Usage
33
+ ### Configure
23
34
 
24
- Add the following to your `.vitepress/config.ts`:
35
+ Wrap your VitePress config with `withOpenSpec()`:
25
36
 
26
37
  ```typescript
38
+ // docs/.vitepress/config.ts
27
39
  import { defineConfig } from 'vitepress'
28
40
  import { withOpenSpec } from '@stritti/vitepress-plugin-openspec'
29
41
 
30
42
  export default defineConfig(
31
43
  withOpenSpec({
32
- // your regular VitePress config
33
- themeConfig: {
34
- nav: [{ text: 'Home', link: '/' }],
35
- sidebar: {},
36
- },
44
+ title: 'My Project',
37
45
  })
38
46
  )
39
47
  ```
40
48
 
41
- `withOpenSpec` handles everything in one call: page generation, the Vite plugin for live reload, the nav entry, and the sidebar section. All fields are optional — it works with an empty config object and sensible defaults.
49
+ That's it! Run `vitepress dev` and your OpenSpec docs appear at `/openspec/`.
50
+
51
+ ---
52
+
53
+ ## Features
42
54
 
43
- **Zero-config by default:** `specDir` and `srcDir` are auto-detected.
55
+ - **Zero-config** – Automatically detects your `openspec/` folder and VitePress source directory
56
+ - **Live reload** – Pages update automatically during `vitepress dev` when you edit OpenSpec files
57
+ - **Sidebar & nav** – Automatic integration into VitePress theme with configurable labels
58
+ - **Index pages** – Generated overviews for specs, changes, and archive with proper hierarchy
59
+ - **Smart defaults** – Works with standard project layouts out of the box
44
60
 
45
- - `specDir`: the plugin walks up from the working directory until it finds an `openspec/` folder, so the standard project layout (`openspec/` at the repo root, docs in `docs/.vitepress/config.ts`) needs no path configuration at all.
46
- - `srcDir`: the plugin detects the directory containing `.vitepress` — either the working directory itself, a first-level subdirectory such as `docs/`, or the parent when the config is evaluated from inside `docs/.vitepress/`.
61
+ ---
47
62
 
48
- An array-based `sidebar` (single sidebar) is automatically converted to the object form `{ '/': [...] }` so the openspec section can be injected without discarding your existing entries.
63
+ ## Configuration
49
64
 
50
- **Other Vite plugins** go into `vite.plugins` as usual — `withOpenSpec` appends to the array without replacing it:
65
+ ### `withOpenSpec(config, options?)`
66
+
67
+ Wrap your VitePress config. `withOpenSpec` handles page generation, the Vite plugin for live reload, nav entry, and sidebar section in one call.
51
68
 
52
69
  ```typescript
53
70
  import { defineConfig } from 'vitepress'
54
71
  import { withOpenSpec } from '@stritti/vitepress-plugin-openspec'
55
- import myOtherPlugin from 'vitepress-plugin-something'
56
72
 
57
73
  export default defineConfig(
58
74
  withOpenSpec(
59
75
  {
60
- vite: { plugins: [myOtherPlugin()] }, // preserved alongside openspec
61
- themeConfig: { nav: [], sidebar: {} },
76
+ // Your regular VitePress config
77
+ themeConfig: {
78
+ nav: [{ text: 'Home', link: '/' }],
79
+ sidebar: {},
80
+ },
62
81
  },
63
- { specDir: '../openspec', outDir: 'openspec' } // options (all optional)
82
+ { specDir: '../openspec', outDir: 'openspec' } // Options (all optional)
64
83
  )
65
84
  )
66
85
  ```
67
86
 
68
- ---
87
+ **Note:** Array-based sidebars are automatically converted to object form (`{ '/': [...] }`) to inject the OpenSpec section while preserving your existing entries.
69
88
 
70
- ## Options
89
+ ### Options
71
90
 
72
91
  | Option | Type | Default | Description |
73
92
  | --- | --- | --- | --- |
74
- | `specDir` | `string` | auto-detected (`<nearest ancestor>/openspec`, fallback `'./openspec'`) | Path to your project's `openspec/` directory. Can be an absolute path or relative to the working directory — use `path.resolve(__dirname, '../../openspec')` when `config.ts` lives in `docs/.vitepress/`. |
93
+ | `specDir` | `string` | auto-detected | Path to your `openspec/` directory. Auto-detects nearest ancestor folder or falls back to `./openspec` |
75
94
  | `outDir` | `string` | `'openspec'` | Output directory relative to VitePress `srcDir` |
76
- | `srcDir` | `string` | auto-detected (directory containing `.vitepress`, fallback working directory) | VitePress source directory (the `docs/` folder) |
77
- | `nav` | `boolean` | `true` | Whether to prepend an openspec entry to `themeConfig.nav` |
78
- | `sidebar` | `boolean` | `true` | Whether to inject the openspec sidebar section into `themeConfig.sidebar` |
79
- | `navText` | `string` | `'Docs'` | Label for the nav entry injected into `themeConfig.nav` |
95
+ | `srcDir` | `string` | auto-detected | VitePress source directory (folder containing `.vitepress/`) |
96
+ | `nav` | `boolean` | `true` | Prepend OpenSpec entry to `themeConfig.nav` |
97
+ | `sidebar` | `boolean` | `true` | Inject OpenSpec sidebar section into `themeConfig.sidebar` |
98
+ | `navText` | `string` | `'Docs'` | Label for the nav entry |
80
99
 
81
- > **Missing directory** — if `specDir` does not exist the plugin emits a `console.warn` and skips page generation, nav, and sidebar. No error is thrown and your VitePress build continues normally. This is intentional for projects that haven't set up an `openspec/` folder yet.
100
+ > **Missing `specDir`:** If the folder doesn't exist, the plugin emits a warning and skips generation. Your build continues normally.
82
101
 
83
- > **Invalid `outDir`** — an `outDir` that is absolute, empty, or resolves outside the VitePress `srcDir` throws an error at config evaluation time. Unlike a missing `specDir`, a misconfigured output path is never silently ignored.
102
+ > **Invalid `outDir`:** An absolute path, empty string, or path resolving outside `srcDir` throws an error at config time.
84
103
 
85
104
  ---
86
105
 
87
- ## Advanced / manual setup
106
+ ## Advanced Setup
88
107
 
89
- If you need full control over each integration point, you can wire up the lower-level APIs individually:
108
+ For full control over each integration point, use the lower-level APIs:
90
109
 
91
110
  ```typescript
92
111
  import { defineConfig } from 'vitepress'
@@ -99,23 +118,22 @@ import openspec, {
99
118
  } from '@stritti/vitepress-plugin-openspec'
100
119
 
101
120
  const __dirname = path.dirname(fileURLToPath(import.meta.url))
102
- const specDir = path.resolve(__dirname, '../openspec')
103
121
 
104
- // Must be called before defineConfig so pages exist when VitePress scans for routes.
122
+ // Must be called before defineConfig so pages exist when VitePress scans for routes
105
123
  generateOpenSpecPages({
106
- specDir,
124
+ specDir: path.resolve(__dirname, '../openspec'),
107
125
  outDir: 'openspec',
108
126
  srcDir: path.resolve(__dirname, '..'),
109
127
  })
110
128
 
111
129
  export default defineConfig({
112
130
  vite: {
113
- plugins: [openspec({ specDir, outDir: 'openspec' })],
131
+ plugins: [openspec({ specDir: path.resolve(__dirname, '../openspec'), outDir: 'openspec' })],
114
132
  },
115
133
  themeConfig: {
116
- nav: [openspecNav(specDir, { outDir: 'openspec', text: 'Docs' })],
134
+ nav: [openspecNav(path.resolve(__dirname, '../openspec'), { outDir: 'openspec', text: 'Docs' })],
117
135
  sidebar: {
118
- '/openspec/': generateOpenSpecSidebar(specDir, { outDir: 'openspec' }),
136
+ '/openspec/': generateOpenSpecSidebar(path.resolve(__dirname, '../openspec'), { outDir: 'openspec' }),
119
137
  },
120
138
  },
121
139
  })
@@ -123,51 +141,22 @@ export default defineConfig({
123
141
 
124
142
  ---
125
143
 
126
- ## Output Structure
144
+ ## How It Works
127
145
 
128
- The plugin reads your `openspec/` folder and generates:
146
+ VitePress scans `srcDir` for `.md` files **before** any Vite plugin hooks run. This plugin solves this with two mechanisms:
129
147
 
130
- ```
131
- openspec/ ← your source (not committed if used as output)
132
- ├── specs/
133
- │ └── <capability>/
134
- │ └── spec.md
135
- └── changes/
136
- ├── <change-name>/
137
- │ ├── .openspec.yaml
138
- │ ├── proposal.md
139
- │ ├── design.md
140
- │ └── tasks.md
141
- └── archive/
142
- └── YYYY-MM-DD-<change-name>/
143
-
144
- docs/openspec/ ← generated by the plugin (automatically gitignored)
145
- ├── index.md
146
- ├── specs/
147
- │ ├── index.md
148
- │ └── <capability>/
149
- │ └── index.md
150
- └── changes/
151
- ├── index.md
152
- ├── <change-name>/
153
- │ ├── index.md
154
- │ ├── proposal.md
155
- │ └── tasks.md
156
- └── archive/
157
- └── YYYY-MM-DD-<change-name>/
158
- └── ...
159
- ```
148
+ 1. **`generateOpenSpecPages()`** – Called synchronously before `defineConfig()` to ensure pages exist when VitePress scans for routes (critical for first builds and CI)
149
+ 2. **`openspec()` Vite plugin** – Re-generates pages on every config reload during `vitepress dev` for live reload support
160
150
 
161
- The plugin automatically writes a `.gitignore` into the output directory that excludes all generated files from version control. No manual `.gitignore` entry is needed.
151
+ The plugin automatically writes a `.gitignore` in the output directory to exclude generated files.
162
152
 
163
153
  ---
164
154
 
165
- ## How It Works
166
-
167
- VitePress scans `srcDir` for `.md` files **before** any Vite plugin hooks run. The plugin solves this with two complementary mechanisms:
155
+ ## Documentation
168
156
 
169
- 1. **`generateOpenSpecPages()`** — called synchronously at the top of `config.ts`, before `defineConfig()`. Ensures all pages exist when VitePress scans for routes (critical for first builds and CI).
170
- 2. **`openspec()` Vite plugin** — calls `generateOpenSpecPages()` again on every config reload during `vitepress dev`, keeping pages in sync with your source files.
157
+ - [Full Integration Guide](https://stritti.github.io/vitepress-plugin-openspec/guide) – Complete setup and configuration
158
+ - [API Reference](https://stritti.github.io/vitepress-plugin-openspec/guide#api-reference) – Detailed API documentation
159
+ - [Troubleshooting](https://stritti.github.io/vitepress-plugin-openspec/guide#troubleshooting) – Common issues and solutions
171
160
 
172
161
  ---
173
162
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stritti/vitepress-plugin-openspec",
3
- "version": "0.8.4",
3
+ "version": "0.8.5",
4
4
  "description": "A VitePress plugin that integrates OpenSpec documentation into your VitePress site",
5
5
  "keywords": [
6
6
  "openspec",
@@ -47,22 +47,24 @@
47
47
  "picocolors": "^1.1.1"
48
48
  },
49
49
  "devDependencies": {
50
+ "@eslint/js": "^10.0.0",
51
+ "@semantic-release/changelog": "^7.0.0",
50
52
  "@semantic-release/commit-analyzer": "^13.0.1",
53
+ "@semantic-release/git": "^11.0.1",
51
54
  "@semantic-release/github": "^12.0.6",
52
55
  "@semantic-release/npm": "^13.1.5",
53
56
  "@semantic-release/release-notes-generator": "^14.1.0",
54
57
  "@types/js-yaml": "^4.0.9",
55
58
  "@types/node": "^26.6.4",
56
59
  "@vitest/coverage-v8": "^5.0.3",
60
+ "eslint": "^10.13.0",
57
61
  "semantic-release": "^25.0.3",
58
- "tsup": "^8.5.1",
62
+ "tsup": "^9.0.0",
59
63
  "typescript": "npm:@typescript/typescript6@^6.0.2",
64
+ "typescript-eslint": "^8.72.0",
60
65
  "vite": "^8.0.5",
61
66
  "vitepress": "^1.6.4",
62
- "vitest": "^5.0.3",
63
- "@eslint/js": "^10.0.0",
64
- "eslint": "^10.13.0",
65
- "typescript-eslint": "^8.72.0"
67
+ "vitest": "^5.0.3"
66
68
  },
67
69
  "peerDependencies": {
68
70
  "vite": ">=5.0.0",