vitepress-allyouneed 0.4.3 → 0.5.0-beta.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/README.md +54 -8
  3. package/dist/index.cjs +91 -43
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.js +91 -43
  6. package/dist/index.js.map +1 -1
  7. package/dist/theme/components/DocHeader.vue +55 -15
  8. package/dist/theme/components/Tags.vue +24 -5
  9. package/dist/theme/components/VaultGraph.vue +223 -65
  10. package/dist/theme/components/VaultStats.vue +34 -10
  11. package/dist/theme/composables/useVaultData.cjs +21 -6
  12. package/dist/theme/composables/useVaultData.cjs.map +1 -1
  13. package/dist/theme/composables/useVaultData.d.cts +12 -1
  14. package/dist/theme/composables/useVaultData.d.ts +12 -1
  15. package/dist/theme/composables/useVaultData.js +19 -5
  16. package/dist/theme/composables/useVaultData.js.map +1 -1
  17. package/dist/theme/index.cjs +37 -14
  18. package/dist/theme/index.cjs.map +1 -1
  19. package/dist/theme/index.d.cts +8 -0
  20. package/dist/theme/index.d.ts +8 -0
  21. package/dist/theme/index.js +36 -14
  22. package/dist/theme/index.js.map +1 -1
  23. package/dist/theme/styles/callouts.css +9 -3
  24. package/dist/theme/styles/doc-header.css +10 -1
  25. package/dist/theme/styles/graph.css +84 -11
  26. package/dist/theme/styles/index.css +24 -1
  27. package/dist/theme/styles/shared.css +12 -2
  28. package/dist/theme/styles/stats.css +11 -0
  29. package/dist/theme/styles/tags.css +17 -3
  30. package/dist/vite.cjs +46 -36
  31. package/dist/vite.cjs.map +1 -1
  32. package/dist/vite.js +46 -36
  33. package/dist/vite.js.map +1 -1
  34. package/dist/vitepress.cjs +91 -43
  35. package/dist/vitepress.cjs.map +1 -1
  36. package/dist/vitepress.js +91 -43
  37. package/dist/vitepress.js.map +1 -1
  38. package/package.json +7 -2
  39. package/style.css +5 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,88 @@
2
2
 
3
3
  本项目遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/);版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。
4
4
 
5
+ ## [0.5.0-beta.3] - 2026-05-22
6
+
7
+ ### Fixed
8
+ - **Tags 视图(可能也包括其它视图)整片失样**:0.5.0-beta.0/.1/.2 的 `@layer` 声明用了 `@import url('./x.css') layer(vitepress-allyouneed)` 这种"在 @import 子句上挂 layer"语法。CSS 标准支持,但 **Vite + postcss-import / lightningcss 不同链路对它支持参差**:某些组合下 `layer()` 子句被吞,resolve 后的规则**没进 layer**;另一些组合下规则进了 layer 但没正确链入 layer order,被埋在最底层 specificity 一概输掉。Tags chip 失去 pill 样式就是这个症状(`.ayn-tag-chip` 的 padding/border/radius/bg 全输给 user-agent + VP)。
9
+ - **改法**:不再用 `@import ... layer()`。每个 .css 文件**自己头尾**包 `@layer vitepress-allyouneed { ... }`,这是浏览器原生 cascade layer 语法,不经过 bundler 黑盒,100% 可靠。`styles/index.css` 退回最朴素的 `@import './x.css'`。
10
+ - 行为不变:7 个 .css 全 layered,主题作者 unlayered CSS 自动赢。
11
+
12
+ ### Files touched
13
+ - `src/theme/styles/index.css`(去 layer() 子句)
14
+ - `src/theme/styles/shared.css`、`stats.css`、`tags.css`、`graph.css`、`callouts.css`、`doc-header.css`(各自头尾包 @layer block)
15
+ - `style.css`(同上)
16
+
17
+ ## [0.5.0-beta.2] - 2026-05-22
18
+
19
+ 更彻底的修法:把 DocHeader 的 banner title 改成 `<div role="heading" aria-level="1">`,把 doc-header.css 放回 @layer,所有 7 个 .css 终于统一 layered。
20
+
21
+ ### Changed
22
+ - **DocHeader banner 元素 `<h1>` → `<div role="heading" aria-level="1">`**:`.vp-doc h1` 选择器不再匹配我们,@layer 内 layered CSS 不再被 VitePress 默认 unlayered 32px 字号覆盖。
23
+ - 视觉:无差(`.ayn-doc-banner-title` 字号/字重等都生效)
24
+ - 辅助技术:WAI-ARIA 标准,屏幕阅读器按 h1 念出,跟原生 `<h1>` 等同
25
+ - SEO:Google 早期声明 `role="heading" aria-level="1"` 跟 `<h1>` 等价对待
26
+ - 文档大纲算法:99% 工具支持;少数 reader-mode 工具可能少识别一个标题
27
+ - **doc-header.css 放回 `@layer vitepress-allyouneed`**:0.5.0-beta.1 的"豁免"特例不再需要。**所有 7 个 .css 都 layered**,主题作者覆盖故事彻底干净
28
+ - `styles/index.css` 不再 split "layered / unlayered",注释简化
29
+
30
+ ### Why
31
+ 0.5.0-beta.0 引入 @layer 后,banner title 是 `<h1>` 在 `.vp-doc` 内,VP 默认 `.vp-doc h1 { font-size: 32px }` 是 unlayered,我们 layered CSS 永远输 → banner title 字号塌缩。0.5.0-beta.1 临时方案:doc-header.css 不 layer。0.5.0-beta.2 釜底抽薪:banner 不用 `<h1>` 元素了,VP 选择器抓不到我们。
32
+
33
+ ## [0.5.0-beta.1] - 2026-05-22
34
+
35
+ ### Fixed
36
+ - **DocHeader banner title 字号丢失**(0.5.0-beta.0 回归):banner title 是 `<h1>` 在 `.vp-doc` 内,VitePress 默认 `.vp-doc h1 { font-size: 32px }` 是 unlayered;0.5.0-beta.0 把 `doc-header.css` 包进 `@layer vitepress-allyouneed` 后,**layered 永远输 unlayered**,我们的 `clamp(2rem, 4.5vw, 3.25rem)` 大字号被 VP 32px 覆盖 → "大标题"看起来变小。
37
+ - **修法**:`doc-header.css` 不再 layer。原则上"必须压过 VP unlayered defaults 的 CSS"不能 layer;"用户可覆盖的装饰"才 layer。文档 `styles/index.css` 顶部添加注释说明这条边界
38
+ - 其它 6 个 CSS 文件继续 layer(它们的 selector 不跟 VP 默认强冲突)
39
+
40
+ ### Note for theme authors
41
+ 想覆盖 banner title:写 `.ayn-doc-banner-title { ... }` —— 跟 0.4.x 行为一致(unlayered 源顺序赢)。注意我们文件在 `defineTheme` import 时加载,你 CSS 必须在它之后 import 才赢。
42
+
43
+ ## [0.5.0-beta.0] - 2026-05-21
44
+
45
+ 主题集成大改 —— **目标:让 3rd-party VitePress 主题作者完全不需要知道本插件**。
46
+
47
+ ### Theme: CSS 用 `@layer` 包裹(底层化)
48
+ - 全部 7 个 .css 文件通过 `styles/index.css` 用 `@import ... layer(vitepress-allyouneed)` 加载,所有规则进 `vitepress-allyouneed` cascade layer
49
+ - **后果**:用户(或第三方主题)写的任何 unlayered CSS **自动赢**我们,无论 specificity 或 import 顺序。`.wikilink { color: red }` 真就 red,不用知道我们有个 `.wikilink`
50
+ - 删除全部 3 处 `!important`(`callouts.css` callout-title 色、`shared.css` mark 内 mathjax bg、`tags.css` tag link 下划线 reset)—— 它们都不需要 `!important`,specificity 已够,且 `!important` 会在 layer 内反向打败用户 unlayered。删了用户 100% 能盖
51
+ - 浏览器支持:`@layer` Chrome/Edge 99 / Firefox 97 / Safari 15.4+(2022 春)
52
+
53
+ ### Theme: 新 `defineTheme()` 工厂(替代之前的 `withAllYouNeed` 设想)
54
+ - `vitepress-allyouneed/theme` 默认导出仍是开箱即用的 Theme 对象,**额外**导出 `defineTheme(userTheme?)` 工厂
55
+ - 三种用户场景:
56
+ 1. **零配置**:`export { default } from 'vitepress-allyouneed/theme'` — 一行完事(DefaultTheme + 我们组件 + 我们 CSS)
57
+ 2. **自定义 Layout / 加自己组件**:`defineTheme({ Layout, enhanceApp })`
58
+ 3. **嵌 3rd-party 主题**:`defineTheme({ extends: SomeAwesomeTheme })`
59
+ - 内部:用户 `enhanceApp` 在我们之后跑 → 同名 `app.component()` 注册**自动赢**(Vue last-registration-wins);用户 `Layout`、`setup` 直接替换
60
+ - 主题包作者的工作流跟有没有本插件**完全无关**:他们写正常 VitePress 主题,published,最终用户负责 `defineTheme({ extends: ... })` 一行接入
61
+
62
+ ### Theme: 可被替换的 Vue 组件清单(API 契约)
63
+ | 组件名 | 干什么 | 用户怎么换 |
64
+ |---|---|---|
65
+ | `Layout` | DefaultTheme.Layout + 自动 `<DocHeader />` + `frontmatter.cssclasses` → body | `defineTheme({ Layout: MyLayout })` |
66
+ | `DocHeader` | 文档头:banner / 标题 / 时间 / tags | `app.component('DocHeader', MyDocHeader)` |
67
+ | `VaultGraph` | d3 力导向关系图 | 同上 |
68
+ | `VaultStats` | 统计卡片 | 同上 |
69
+ | `Tags` | 标签云 + 搜索 + 列表 | 同上 |
70
+
71
+ ### Composables(显式契约)
72
+ `useVaultData()` 早已暴露;0.5.0 起明确这是"给写自己 UI 的人"的公共 API。
73
+
74
+ ### Docs
75
+ - `src/theme/index.ts` 文件头三段示例覆盖三种场景
76
+ - README "当前版本" 章节同步
77
+ - DOCS.md 新增 "Theming" 章节(下个 beta 补全)
78
+
79
+ ### Why beta
80
+ - @layer 在 Vite CSS pipeline 的实际行为没在我这边 prod build 跑过,需要真实项目验证
81
+ - `defineTheme()` 是新 API,等用户回声再 stabilize
82
+ - 老 0.4.x 用户 `import AllYouNeedTheme from 'vitepress-allyouneed/theme'` 仍兼容(default export 没变),只是多了 `defineTheme` 命名导出
83
+
84
+ ### Migration from 0.4.x
85
+ **完全无 breaking** —— 老代码继续跑。新代码推荐用 `defineTheme()`,见 README。
86
+
5
87
  ## [0.4.1] - 2026-05-21
6
88
 
7
89
  修 0.4.0 几个回归 + 小幅 UX 优化。
package/README.md CHANGED
@@ -4,16 +4,62 @@
4
4
 
5
5
  Forked from [`actuallysomecat/markdown-it-wikilinks-plus`](https://github.com/actuallysomecat/markdown-it-wikilinks-plus) (MIT) 并针对 VitePress 大幅重写。
6
6
 
7
- ## 当前版本:0.4.1(2026-05-21)
7
+ ## 当前版本:0.5.0-beta.0(2026-05-21)
8
8
 
9
- **0.4.x 重要变更(从 0.3.x 升级看这里)**
9
+ **主题集成大改 —— 目标:让第三方 VitePress 主题作者不需要知道本插件存在**
10
10
 
11
- - **`sidebarAuto.autoFolderIndex` 已删除**。文件夹链接由 `sidebarAuto.folderLinkOrder`(默认 `['same-name', 'index', 'readme', 'first-file']`)在 sidebar/nav/wikilink 解析时直接处理,不再生成 `index.md` 文件。配置里还留着这个字段会在控制台 warn 一次,删掉就行。
12
- - **`folderLinkOrder`** 新增 — 自定义文件夹链接来源顺序;`[]` 表示文件夹不可点。
13
- - **数字排序修正(0.4.1)**:`1, 2, 10, 11` 真按数字大小排,不再字典序成 `1, 10, 11, 2`。
14
- - **`markdown.math: true`** 自动检测 — 没装 `markdown-it-mathjax3` 时给清晰提示,一行 `npm i -D markdown-it-mathjax3` 即可。
15
- - **dev HMR**:`.md` add/remove 或 `_sidebar.md` 改动自动 server restart,sidebar 立即刷新。
16
- - **leading-number 锚点**:`#13` 现在能匹 `## 13) Optik`、`13: ...`、`13, ...`、`13 — ...`。不匹 `13.5 Sub`(避免吃版本号)。
11
+ ### CSS 自动让用户赢(`@layer`)
12
+
13
+ 我们所有 CSS 包在 `@layer vitepress-allyouneed` 里。CSS 标准规则:**任何 unlayered CSS 永远赢 layered CSS**,无关顺序、specificity。所以:
14
+
15
+ ```css
16
+ /* 第三方主题随便写,自动赢 */
17
+ .wikilink { color: red; }
18
+ .callout { border-radius: 12px; }
19
+ ```
20
+
21
+ 零知识负担。
22
+
23
+ ### Vue 组件:`defineTheme()` 工厂
24
+
25
+ 三种场景,递进式:
26
+
27
+ ```ts
28
+ // 1. 零配置(默认主题 + 我们)
29
+ export { default } from 'vitepress-allyouneed/theme'
30
+
31
+ // 2. 自定义 Layout / 覆盖某个视图
32
+ import { defineTheme } from 'vitepress-allyouneed/theme'
33
+ import MyLayout from './MyLayout.vue'
34
+ import MyVaultGraph from './MyVaultGraph.vue'
35
+ export default defineTheme({
36
+ Layout: MyLayout,
37
+ enhanceApp({ app }) {
38
+ app.component('VaultGraph', MyVaultGraph) // 同名注册自动覆盖
39
+ },
40
+ })
41
+
42
+ // 3. 嵌别人写的 VitePress 主题(主题包作者无需感知本插件)
43
+ import { defineTheme } from 'vitepress-allyouneed/theme'
44
+ import SomeTheme from 'some-vitepress-theme'
45
+ export default defineTheme({ extends: SomeTheme })
46
+ ```
47
+
48
+ 可被替换的全局组件:`Layout` / `DocHeader` / `VaultGraph` / `VaultStats` / `Tags`。
49
+
50
+ ### 4.x 兼容
51
+
52
+ 老代码 `import theme from 'vitepress-allyouneed/theme'; export default theme` 继续跑,没有 breaking。
53
+
54
+ ---
55
+
56
+ ### 0.4.x 重要变更(从 0.3.x 升级看这里)
57
+
58
+ - **`sidebarAuto.autoFolderIndex` 已删除**。文件夹链接由 `sidebarAuto.folderLinkOrder`(默认 `['same-name', 'index', 'readme', 'first-file']`)在 sidebar/nav/wikilink 解析时直接处理。
59
+ - **数字排序修正(0.4.1)**:`1, 2, 10, 11` 真按数字大小排。
60
+ - **`markdown.math: true`** 自动检测 — 没装 `markdown-it-mathjax3` 时给清晰提示。
61
+ - **dev HMR**:`.md` add/remove 或 `_sidebar.md` 改动自动 server restart。
62
+ - **leading-number 锚点**:`#13` 能匹 `## 13) Optik`、`13: ...` 等。
17
63
 
18
64
  完整 changelog 见 [`CHANGELOG.md`](./CHANGELOG.md);配置参考见 [`DOCS.md`](./DOCS.md)。
19
65
 
package/dist/index.cjs CHANGED
@@ -2102,11 +2102,10 @@ var markdown_it_default = allYouNeedMarkdownIt;
2102
2102
 
2103
2103
  // src/vite.ts
2104
2104
  var import_node_fs7 = __toESM(require("fs"), 1);
2105
- var import_node_path8 = __toESM(require("path"), 1);
2105
+ var import_node_path7 = __toESM(require("path"), 1);
2106
2106
 
2107
2107
  // src/core/asset-pipeline/dev-middleware.ts
2108
2108
  var import_node_fs4 = __toESM(require("fs"), 1);
2109
- var import_node_path5 = __toESM(require("path"), 1);
2110
2109
  function createDevMiddleware(index, options) {
2111
2110
  return (req, res, next) => {
2112
2111
  if (!req.url) return next();
@@ -2124,25 +2123,38 @@ function createDevMiddleware(index, options) {
2124
2123
  if (!/\.[a-zA-Z0-9]+$/.test(decoded)) return next();
2125
2124
  const relCandidate = decoded.replace(/^\/+/, "");
2126
2125
  let asset = index.assetsByRelativePath.get(relCandidate);
2127
- if (!asset) {
2126
+ if (!asset && !relCandidate.includes("/")) {
2128
2127
  const bn = basename(decoded);
2129
2128
  const map = options.caseSensitive ? index.assetsByBasename : index.assetsByBasenameLower;
2130
2129
  const key = options.caseSensitive ? bn : bn.toLowerCase();
2131
2130
  const candidates = map.get(key);
2132
- if (candidates && candidates.length > 0) asset = candidates[0];
2131
+ if (candidates && candidates.length > 0) {
2132
+ asset = [...candidates].sort(
2133
+ (a, b) => a.relativePath.length - b.relativePath.length
2134
+ )[0];
2135
+ }
2133
2136
  }
2134
2137
  if (!asset) return next();
2135
- let stat;
2136
- try {
2137
- stat = import_node_fs4.default.statSync(asset.absolutePath);
2138
- } catch {
2139
- return next();
2138
+ const etag = `W/"${asset.size.toString(16)}-${Math.floor(asset.mtime).toString(16)}"`;
2139
+ const lastModified = new Date(asset.mtime).toUTCString();
2140
+ const ifNoneMatch = req.headers["if-none-match"];
2141
+ const ifModifiedSince = req.headers["if-modified-since"];
2142
+ if (ifNoneMatch === etag || ifModifiedSince && Date.parse(ifModifiedSince) >= Math.floor(asset.mtime)) {
2143
+ res.statusCode = 304;
2144
+ res.setHeader("ETag", etag);
2145
+ res.setHeader("Last-Modified", lastModified);
2146
+ return res.end();
2140
2147
  }
2141
2148
  res.statusCode = 200;
2142
2149
  res.setHeader("Content-Type", guessMime(asset.extension));
2143
- res.setHeader("Content-Length", String(stat.size));
2150
+ res.setHeader("Content-Length", String(asset.size));
2144
2151
  res.setHeader("Cache-Control", "no-cache");
2145
- import_node_fs4.default.createReadStream(asset.absolutePath).on("error", () => next()).pipe(res);
2152
+ res.setHeader("ETag", etag);
2153
+ res.setHeader("Last-Modified", lastModified);
2154
+ import_node_fs4.default.createReadStream(asset.absolutePath).on("error", () => {
2155
+ if (!res.headersSent) next();
2156
+ else res.destroy();
2157
+ }).pipe(res);
2146
2158
  };
2147
2159
  }
2148
2160
  var MIME = {
@@ -2174,14 +2186,14 @@ function guessMime(ext) {
2174
2186
 
2175
2187
  // src/core/views/generate-md.ts
2176
2188
  var import_node_fs5 = __toESM(require("fs"), 1);
2177
- var import_node_path6 = __toESM(require("path"), 1);
2189
+ var import_node_path5 = __toESM(require("path"), 1);
2178
2190
  var VIEW_SENTINEL = "<!-- generated by vitepress-allyouneed (do not edit; will be regenerated) -->";
2179
2191
  function generateViewMarkdown(options, index) {
2180
2192
  const report = { written: [], skipped: [] };
2181
2193
  if (!options.modules.views) return report;
2182
- const srcDir = import_node_path6.default.resolve(options.srcDir);
2194
+ const srcDir = import_node_path5.default.resolve(options.srcDir);
2183
2195
  const prefix = options.views.urlPrefix;
2184
- const viewDir = prefix ? import_node_path6.default.join(srcDir, prefix) : srcDir;
2196
+ const viewDir = prefix ? import_node_path5.default.join(srcDir, prefix) : srcDir;
2185
2197
  if (prefix) {
2186
2198
  try {
2187
2199
  import_node_fs5.default.mkdirSync(viewDir, { recursive: true });
@@ -2190,7 +2202,7 @@ function generateViewMarkdown(options, index) {
2190
2202
  }
2191
2203
  const views = buildViewList(options);
2192
2204
  for (const v of views) {
2193
- const target = import_node_path6.default.join(viewDir, v.fileName);
2205
+ const target = import_node_path5.default.join(viewDir, v.fileName);
2194
2206
  if (import_node_fs5.default.existsSync(target)) {
2195
2207
  let existing;
2196
2208
  try {
@@ -2271,8 +2283,8 @@ function renderTemplate(v) {
2271
2283
 
2272
2284
  // src/core/views/generate-data.ts
2273
2285
  var import_node_fs6 = __toESM(require("fs"), 1);
2274
- var import_node_path7 = __toESM(require("path"), 1);
2275
- var PLUGIN_VERSION = "0.2.0-beta.0";
2286
+ var import_node_path6 = __toESM(require("path"), 1);
2287
+ var PLUGIN_VERSION = true ? "0.5.0-beta.3" : "0.0.0-dev";
2276
2288
  var WIKILINK_RE = /(!?)\[\[([^\]\n]+)\]\]/g;
2277
2289
  var DEFAULT_BODY_TAG_RE = /(?:^|[\s([{,;。,;])#([\p{L}_][\p{L}\p{N}_/-]*)/gu;
2278
2290
  function buildBodyTagRe(userPattern) {
@@ -2329,19 +2341,6 @@ function buildVaultData(index, options) {
2329
2341
  const edges = [...edgeMap.values()];
2330
2342
  const bodyTagRe = buildBodyTagRe(options.views.inlineTagPattern);
2331
2343
  const tagsMap = /* @__PURE__ */ new Map();
2332
- for (const f of userFiles) {
2333
- const allTags = new Set(f.tags);
2334
- if (options.views.parseInlineTags) {
2335
- for (const tm of f.content.matchAll(bodyTagRe)) {
2336
- allTags.add(tm[1]);
2337
- }
2338
- }
2339
- for (const tag of allTags) {
2340
- const arr = tagsMap.get(tag) ?? [];
2341
- arr.push(f);
2342
- tagsMap.set(tag, arr);
2343
- }
2344
- }
2345
2344
  const allTagsByFile = /* @__PURE__ */ new Map();
2346
2345
  for (const f of userFiles) {
2347
2346
  const set = new Set(f.tags);
@@ -2349,6 +2348,11 @@ function buildVaultData(index, options) {
2349
2348
  for (const tm of f.content.matchAll(bodyTagRe)) set.add(tm[1]);
2350
2349
  }
2351
2350
  allTagsByFile.set(f.relativePath, [...set]);
2351
+ for (const tag of set) {
2352
+ const arr = tagsMap.get(tag) ?? [];
2353
+ arr.push(f);
2354
+ tagsMap.set(tag, arr);
2355
+ }
2352
2356
  }
2353
2357
  const tags = {};
2354
2358
  for (const [tag, files] of tagsMap) {
@@ -2391,9 +2395,9 @@ function buildVaultData(index, options) {
2391
2395
  function writeVaultData(index, options) {
2392
2396
  const data = buildVaultData(index, options);
2393
2397
  const json = JSON.stringify(data);
2394
- const publicDir = import_node_path7.default.join(import_node_path7.default.resolve(options.srcDir), "public");
2398
+ const publicDir = import_node_path6.default.join(import_node_path6.default.resolve(options.srcDir), "public");
2395
2399
  import_node_fs6.default.mkdirSync(publicDir, { recursive: true });
2396
- const out = import_node_path7.default.join(publicDir, options.views.dataFileName);
2400
+ const out = import_node_path6.default.join(publicDir, options.views.dataFileName);
2397
2401
  import_node_fs6.default.writeFileSync(out, json, "utf8");
2398
2402
  return { path: out, bytes: json.length };
2399
2403
  }
@@ -2458,7 +2462,7 @@ function viteAllYouNeed(userOptions = {}) {
2458
2462
  config(_userViteConfig, _envCtx) {
2459
2463
  const srcDirOpt = userOptions.srcDir;
2460
2464
  if (!srcDirOpt) return void 0;
2461
- const abs = toPosix(import_node_path8.default.resolve(srcDirOpt));
2465
+ const abs = toPosix(import_node_path7.default.resolve(srcDirOpt));
2462
2466
  return {
2463
2467
  server: {
2464
2468
  fs: {
@@ -2540,9 +2544,15 @@ function viteAllYouNeed(userOptions = {}) {
2540
2544
  removeFile(index, ctx.file, resolved);
2541
2545
  if (wasIndexed) structuralChange = "remove";
2542
2546
  }
2543
- } catch {
2544
- removeFile(index, ctx.file, resolved);
2545
- if (wasIndexed) structuralChange = "remove";
2547
+ } catch (err) {
2548
+ if (err.code === "ENOENT") {
2549
+ removeFile(index, ctx.file, resolved);
2550
+ if (wasIndexed) structuralChange = "remove";
2551
+ } else {
2552
+ console.warn(
2553
+ `vitepress-allyouneed: stat failed for ${ctx.file} (${err.code ?? "unknown"}); keeping existing index entry.`
2554
+ );
2555
+ }
2546
2556
  }
2547
2557
  const baseName = ctx.file.split(/[\\/]/).pop() ?? "";
2548
2558
  const isSidebarFile = /^_sidebar\.(md|markdown)$/i.test(baseName);
@@ -3594,7 +3604,7 @@ function computeGroupText(dir, dirIndex, opts) {
3594
3604
 
3595
3605
  // src/core/sidebar-auto/generate-sidebar-materialize.ts
3596
3606
  var import_node_fs8 = __toESM(require("fs"), 1);
3597
- var import_node_path9 = __toESM(require("path"), 1);
3607
+ var import_node_path8 = __toESM(require("path"), 1);
3598
3608
  var SIDEBAR_MATERIALIZE_SENTINEL = "<!-- generated by vitepress-allyouneed/sidebar-materialize (do not edit if you want auto-refresh; remove this comment to take ownership) -->";
3599
3609
  var MD_RE = /\.(md|markdown)$/i;
3600
3610
  var SIDEBAR_RE = /^_sidebar\.(md|markdown)$/i;
@@ -3602,12 +3612,12 @@ function generateSidebarMaterializations(options, matOpts = {}) {
3602
3612
  const report = { written: [], skipped: [] };
3603
3613
  const mode = matOpts.mode ?? "off";
3604
3614
  if (mode === "off") return report;
3605
- const srcDir = import_node_path9.default.resolve(options.srcDir);
3615
+ const srcDir = import_node_path8.default.resolve(options.srcDir);
3606
3616
  const viewsPrefix = options.views.urlPrefix ? options.views.urlPrefix.replace(/^\/+|\/+$/g, "") : "";
3607
3617
  const exclude = matOpts.exclude ?? [];
3608
3618
  const dirs = [srcDir, ...collectDirs(srcDir, srcDir, viewsPrefix, exclude, mode)];
3609
3619
  for (const dirAbs of dirs) {
3610
- const target = import_node_path9.default.join(dirAbs, "_sidebar.md");
3620
+ const target = import_node_path8.default.join(dirAbs, "_sidebar.md");
3611
3621
  if (import_node_fs8.default.existsSync(target)) {
3612
3622
  let content;
3613
3623
  try {
@@ -3680,8 +3690,8 @@ function collectDirs(root, cur, viewsPrefix, exclude, mode) {
3680
3690
  if (!e.isDirectory()) continue;
3681
3691
  if (e.name.startsWith(".") || e.name.startsWith("_")) continue;
3682
3692
  if (e.name === "node_modules" || e.name === "public") continue;
3683
- const full = import_node_path9.default.join(dir, e.name);
3684
- const rel = import_node_path9.default.relative(root, full).split(import_node_path9.default.sep).join("/");
3693
+ const full = import_node_path8.default.join(dir, e.name);
3694
+ const rel = import_node_path8.default.relative(root, full).split(import_node_path8.default.sep).join("/");
3685
3695
  if (viewsPrefix && (rel === viewsPrefix || rel.startsWith(viewsPrefix + "/"))) continue;
3686
3696
  if (exclude.some((pat) => matchGlob(rel, pat))) continue;
3687
3697
  out.push(full);
@@ -3695,7 +3705,7 @@ function hasAnyMd(dir) {
3695
3705
  for (const e of entries) {
3696
3706
  if (e.isFile() && MD_RE.test(e.name) && !SIDEBAR_RE.test(e.name)) return true;
3697
3707
  if (e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")) {
3698
- if (hasAnyMd(import_node_path9.default.join(dir, e.name))) return true;
3708
+ if (hasAnyMd(import_node_path8.default.join(dir, e.name))) return true;
3699
3709
  }
3700
3710
  }
3701
3711
  } catch {
@@ -3713,9 +3723,47 @@ var WIKILINK_RE3 = /(!?)\[\[([^\]\n]+)\]\]/g;
3713
3723
  function stripCodeForScan(src) {
3714
3724
  let r = src.replace(/```[\s\S]*?```/g, (m) => " ".repeat(m.length));
3715
3725
  r = r.replace(/~~~[\s\S]*?~~~/g, (m) => " ".repeat(m.length));
3716
- r = r.replace(/(`+)(?:(?!\1)[\s\S])*?\1/g, (m) => " ".repeat(m.length));
3726
+ r = stripInlineCodeLinear(r);
3717
3727
  return r;
3718
3728
  }
3729
+ function stripInlineCodeLinear(src) {
3730
+ const out = src.split("");
3731
+ let i = 0;
3732
+ const n = src.length;
3733
+ while (i < n) {
3734
+ if (src.charCodeAt(i) !== 96) {
3735
+ i += 1;
3736
+ continue;
3737
+ }
3738
+ let openLen = 0;
3739
+ while (i + openLen < n && src.charCodeAt(i + openLen) === 96) openLen += 1;
3740
+ const contentStart = i + openLen;
3741
+ let j = contentStart;
3742
+ let closeAt = -1;
3743
+ while (j < n) {
3744
+ if (src.charCodeAt(j) === 96) {
3745
+ let runLen = 0;
3746
+ while (j + runLen < n && src.charCodeAt(j + runLen) === 96) runLen += 1;
3747
+ if (runLen === openLen) {
3748
+ closeAt = j;
3749
+ break;
3750
+ }
3751
+ j += runLen;
3752
+ } else {
3753
+ j += 1;
3754
+ }
3755
+ }
3756
+ if (closeAt === -1) {
3757
+ i = contentStart;
3758
+ continue;
3759
+ }
3760
+ for (let k = i; k < closeAt + openLen; k++) {
3761
+ if (out[k] !== "\n") out[k] = " ";
3762
+ }
3763
+ i = closeAt + openLen;
3764
+ }
3765
+ return out.join("");
3766
+ }
3719
3767
  function scanWikilinks(index, options) {
3720
3768
  const dead = [];
3721
3769
  const ambiguous = [];