vitepress-allyouneed 0.5.4 → 0.5.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.
package/CHANGELOG.md CHANGED
@@ -2,9 +2,19 @@
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
+
6
+ ## [Unreleased]
7
+
8
+ ## [0.5.5] - 2026-06-20
9
+
5
10
  ## [Unreleased]
6
11
 
12
+ ### Added
13
+ - **目录可由 dirIndex 排序**:`index.md`、`README.md` 或同名目录页现在是该文件夹 group 的排序锚点。默认 `sortBy: 'order-then-title'` 下,给目录页写 `order: 1` 即可控制目录位置;嵌套目录、`per-folder` 根侧栏和 `autoNav` 均一致生效,无需给文件夹名添加数字前缀。顶级 `groupOrder` 仍具有最高优先级。
14
+
7
15
  ### Fixed
16
+ - **嵌套 `index.md` 生成错误的无尾斜杠 URL**:`cleanUrls: true` 下目录页现在输出 `/guide/` 而不是 `/guide`;与 VitePress 的 `guide/index.html` 路由及 dead-link validator 保持一致。
17
+ - **`scanWikilinks` 把合法 `[[folder/]]` 误报为死链**:启动预扫不再维护遗漏 `folderLinkOrder` 的简化解析器,改为与渲染阶段共用 `resolveWikilink`;目录 index、相对路径、自引用锚点和冲突策略现在只有一套解析语义。
8
18
  - **同名页面跨 locale / 区域解析错误**:`[[Gravitationsphysik]]` 这类 basename-only Wikilink 不再直接使用全局 `onConflict`。解析器现在先按源页面的同目录和最长共同路径前缀收窄候选(例如 `zh/themen/*` 优先于 `zh/selfcheck/*`,二者都优先于其它 locale),仍有歧义时才执行 `shortest` / `first` / `error`。
9
19
  - 强化当前源页面定位:relativePath 精确匹配先于后缀兜底,且后缀存在多个 locale 命中时不再取扫描顺序中的第一个。
10
20
 
package/dist/index.cjs CHANGED
@@ -594,7 +594,8 @@ function computeUrl(rel, options) {
594
594
  } else if (!options.cleanUrls) {
595
595
  segments.push("index.html");
596
596
  }
597
- return buildUrl("/", segments);
597
+ const url = buildUrl("/", segments);
598
+ return isIndex && options.cleanUrls ? url + "/" : url;
598
599
  }
599
600
  function pushToArrayMap(m, k, v) {
600
601
  const arr = m.get(k);
@@ -2401,7 +2402,7 @@ function renderTemplate(v) {
2401
2402
  // src/core/views/generate-data.ts
2402
2403
  var import_node_fs6 = __toESM(require("fs"), 1);
2403
2404
  var import_node_path6 = __toESM(require("path"), 1);
2404
- var PLUGIN_VERSION = true ? "0.5.4" : "0.0.0-dev";
2405
+ var PLUGIN_VERSION = true ? "0.5.5" : "0.0.0-dev";
2405
2406
  var WIKILINK_RE = /(!?)\[\[([^\]\n]+)\]\]/g;
2406
2407
  var DEFAULT_BODY_TAG_RE = /(?:^|[\s([{,;。,;])#([\p{L}_][\p{L}\p{N}_/-]*)/gu;
2407
2408
  function buildBodyTagRe(userPattern) {
@@ -3453,8 +3454,27 @@ function shouldLinkGroup(opts, isTopLevel) {
3453
3454
  }
3454
3455
  function sortChildKeys(node, opts, isTopLevel) {
3455
3456
  const keys = [...node.children.keys()];
3457
+ const collateOpts = { numeric: true, sensitivity: "base" };
3458
+ const compareFolderKeys = (a, b) => {
3459
+ const aNode = node.children.get(a);
3460
+ const bNode = node.children.get(b);
3461
+ const aAnchor = pickTitleSourceCandidate(aNode);
3462
+ const bAnchor = pickTitleSourceCandidate(bNode);
3463
+ if (opts.sortBy === "mtime-desc") {
3464
+ const am = aAnchor?.mtime ?? Number.NEGATIVE_INFINITY;
3465
+ const bm = bAnchor?.mtime ?? Number.NEGATIVE_INFINITY;
3466
+ if (am !== bm) return bm - am;
3467
+ } else if (opts.sortBy === "order-then-title") {
3468
+ const ao = aAnchor ? readOrder(aAnchor, opts.orderKey) : Number.POSITIVE_INFINITY;
3469
+ const bo = bAnchor ? readOrder(bAnchor, opts.orderKey) : Number.POSITIVE_INFINITY;
3470
+ if (ao !== bo) return ao - bo;
3471
+ }
3472
+ const at = computeGroupText(aNode.path, aAnchor, opts);
3473
+ const bt = computeGroupText(bNode.path, bAnchor, opts);
3474
+ return at.localeCompare(bt, void 0, collateOpts);
3475
+ };
3456
3476
  if (!isTopLevel || opts.groupOrder.length === 0) {
3457
- return keys.sort();
3477
+ return keys.sort(compareFolderKeys);
3458
3478
  }
3459
3479
  const orderMap = /* @__PURE__ */ new Map();
3460
3480
  opts.groupOrder.forEach((name, i) => {
@@ -3490,7 +3510,7 @@ function sortChildKeys(node, opts, isTopLevel) {
3490
3510
  const ob = orderMap.has(b) ? orderMap.get(b) : orderMap.get(tb);
3491
3511
  return oa - ob;
3492
3512
  });
3493
- rest.sort();
3513
+ rest.sort(compareFolderKeys);
3494
3514
  return [...indexed, ...rest];
3495
3515
  }
3496
3516
  function toFlatSidebar(root, opts) {
@@ -3540,7 +3560,12 @@ function toPerFolderSidebar(root, opts, options, index) {
3540
3560
  for (const f of sortedRootFiles) {
3541
3561
  rootItems.push({ text: opts.formatItemTitle(f), link: f.url });
3542
3562
  }
3543
- const topKeys = [...root.children.keys()].sort();
3563
+ const topKeys = sortChildKeys(
3564
+ root,
3565
+ opts,
3566
+ /* isTopLevel */
3567
+ true
3568
+ );
3544
3569
  for (const key of topKeys) {
3545
3570
  const child = root.children.get(key);
3546
3571
  const childWinner = resolveFolderLink(
@@ -3617,7 +3642,12 @@ function generateNav(index, options, autoOptions = {}) {
3617
3642
  const root = buildTree2(visible);
3618
3643
  const base = options.base.endsWith("/") ? options.base : options.base + "/";
3619
3644
  const out = [{ text: opts.homeNavText, link: "/" }];
3620
- const topKeys = [...root.children.keys()].sort();
3645
+ const topKeys = sortChildKeys(
3646
+ root,
3647
+ opts,
3648
+ /* isTopLevel */
3649
+ true
3650
+ );
3621
3651
  for (const key of topKeys) {
3622
3652
  const child = root.children.get(key);
3623
3653
  const winner = resolveFolderLink(
@@ -3909,9 +3939,14 @@ function scanWikilinks(index, options) {
3909
3939
  if (isAsset) continue;
3910
3940
  }
3911
3941
  }
3912
- const isSelfAnchor = !rawTarget && !!headingPart;
3913
- const found = isSelfAnchor || resolveSimple(rawTarget, index, options, f.relativePath);
3914
- if (!found) {
3942
+ const resolved = resolveWikilink(
3943
+ rawTargetFull,
3944
+ index,
3945
+ options,
3946
+ isEmbed ? "transclusion" : "page",
3947
+ f.absolutePath
3948
+ );
3949
+ if (resolved.isDead) {
3915
3950
  dead.push({
3916
3951
  source: f.relativePath,
3917
3952
  target: rawTarget,
@@ -3920,7 +3955,7 @@ function scanWikilinks(index, options) {
3920
3955
  continue;
3921
3956
  }
3922
3957
  if (scanAmbig && headingPart) {
3923
- const targetEntry = isSelfAnchor ? f : resolveSimpleEntry(rawTarget, index, options, f.relativePath);
3958
+ const targetEntry = resolved.target;
3924
3959
  if (!targetEntry) continue;
3925
3960
  const matches2 = findAmbiguousLeadingNumberMatches(targetEntry, headingPart);
3926
3961
  if (matches2.length > 1) {
@@ -3942,27 +3977,6 @@ function scanWikilinks(index, options) {
3942
3977
  }
3943
3978
  return { total, dead, ambiguous };
3944
3979
  }
3945
- function resolveSimpleEntry(raw, index, options, currentSourceRel) {
3946
- const target = stripMarkdownExt(toPosix(raw));
3947
- if (!target) return void 0;
3948
- if (target.includes("/")) {
3949
- const e = index.byRelativePath.get(target) ?? index.byRelativePath.get(target + ".md") ?? index.byRelativePath.get(target + ".markdown");
3950
- if (e) return e;
3951
- if (currentSourceRel) {
3952
- const curDir = currentSourceRel.split("/").slice(0, -1).join("/");
3953
- if (curDir) {
3954
- return index.byRelativePath.get(`${curDir}/${target}`) ?? index.byRelativePath.get(`${curDir}/${target}.md`) ?? index.byRelativePath.get(`${curDir}/${target}.markdown`);
3955
- }
3956
- }
3957
- return void 0;
3958
- }
3959
- const aliasKey = options.caseSensitive ? target : target.toLowerCase();
3960
- const aliased = index.byAlias.get(aliasKey);
3961
- if (aliased) return aliased;
3962
- const map = options.caseSensitive ? index.byBasename : index.byBasenameLower;
3963
- const key = options.caseSensitive ? target : target.toLowerCase();
3964
- return map.get(key)?.[0];
3965
- }
3966
3980
  function logDeadLinks(report, deadLink) {
3967
3981
  if (deadLink === "silent") return;
3968
3982
  if (report.dead.length > 0) {
@@ -4011,27 +4025,6 @@ function extractExt3(target) {
4011
4025
  if (dot <= 0) return "";
4012
4026
  return cleaned.slice(dot + 1).toLowerCase();
4013
4027
  }
4014
- function resolveSimple(raw, index, options, currentSourceRel) {
4015
- const target = stripMarkdownExt(toPosix(raw));
4016
- if (!target) return false;
4017
- if (target.includes("/")) {
4018
- if (index.byRelativePath.has(target) || index.byRelativePath.has(target + ".md") || index.byRelativePath.has(target + ".markdown")) {
4019
- return true;
4020
- }
4021
- if (currentSourceRel) {
4022
- const curDir = currentSourceRel.split("/").slice(0, -1).join("/");
4023
- if (curDir) {
4024
- return index.byRelativePath.has(`${curDir}/${target}`) || index.byRelativePath.has(`${curDir}/${target}.md`) || index.byRelativePath.has(`${curDir}/${target}.markdown`);
4025
- }
4026
- }
4027
- return false;
4028
- }
4029
- const aliasKey = options.caseSensitive ? target : target.toLowerCase();
4030
- if (index.byAlias.has(aliasKey)) return true;
4031
- const map = options.caseSensitive ? index.byBasename : index.byBasenameLower;
4032
- const key = options.caseSensitive ? target : target.toLowerCase();
4033
- return (map.get(key)?.length ?? 0) > 0;
4034
- }
4035
4028
 
4036
4029
  // src/vitepress.ts
4037
4030
  var autoFolderIndexWarned = false;