vitepress-allyouneed 0.3.2 → 0.3.4
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 +36 -0
- package/dist/index.cjs +183 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +183 -62
- package/dist/index.js.map +1 -1
- package/dist/markdown-it.cjs +79 -20
- package/dist/markdown-it.cjs.map +1 -1
- package/dist/markdown-it.d.cts +1 -1
- package/dist/markdown-it.d.ts +1 -1
- package/dist/markdown-it.js +79 -20
- package/dist/markdown-it.js.map +1 -1
- package/dist/{types-Nx7d15xb.d.cts → types-BLbN9Pg6.d.cts} +9 -0
- package/dist/{types-Nx7d15xb.d.ts → types-BLbN9Pg6.d.ts} +9 -0
- package/dist/vite.cjs +39 -6
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +39 -6
- package/dist/vite.js.map +1 -1
- package/dist/vitepress.cjs +185 -62
- package/dist/vitepress.cjs.map +1 -1
- package/dist/vitepress.d.cts +1 -1
- package/dist/vitepress.d.ts +1 -1
- package/dist/vitepress.js +185 -62
- package/dist/vitepress.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,42 @@
|
|
|
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.3.4] - 2026-05-20
|
|
6
|
+
|
|
7
|
+
真实 Obsidian 物理笔记 vault 测试暴露的 9 个 bug + 3 个隐性问题的集中修复。
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- **图片找不到**:`resolveAsset` 之前只查 vault 绝对相对路径(`assetsByRelativePath`),Obsidian "相对当前文件" 路径模式下写 `![[media/image4.png]]` 在 `Themen/X.md` 里时找不到 → 退化为 basename + base → `/image4.png` → Vite 当 public 根 → 404。现接 `currentSourcePath`,**先**查 vault 绝对路径、**再**查相对源文件 dir、**最后**走 basename fallback;`image.ts` / `media.ts` / `transclusion.ts` 三个调用方都已传 `env.currentPath`。
|
|
11
|
+
- **`![[ ]]` transclusion 同样问题**:`renderTransclusionHtml` 和降级版 `handleTransclusion` 调 `resolveWikilink` 时漏传 `currentSourcePath`,现已补。
|
|
12
|
+
- **`autoFolderIndex` 根目录生成 `[[/foo/]]` 死链**:`defaultTemplate` 拼路径时 `dirRelPath===''` 没特判,产出带前导 `/` 的 wikilink,resolver 不识别"绝对 wikilink"全死。改成根用空 prefix(`[[foo/]]`)。
|
|
13
|
+
- **Obsidian 表格内 `\|` 转义被当成路径字符**:`[[Foo\|Bar]]` 是 Obsidian 在表格 cell 里转义 pipe 的标准写法。原 5 处 `inner.split('|')` 把 target 解析成 `Foo\`(带尾巴反斜杠)→ 找不到。统一抽 `utils/wikilink.ts:splitWikilinkInner`,5 处(`wikilinks/rule.ts`、`embeds/block-rule.ts`、`sidebar-auto/parse-sidebar-md.ts`、`views/generate-data.ts`、`core/scan-wikilinks.ts`)替换。
|
|
14
|
+
- **`stripNumericPrefix` 把版本号吃掉**:`/^\d+[-_.\s]+/` 把 `1.2.3-formula.md` 误剥成 `2.3-formula`。`.` 不再算分隔符,只剩 `-` / `_` / 空白。
|
|
15
|
+
- **行内 `#tag` 在 `cleanUrls: false` 下 404**:`<a class="ayn-tag" href>` 直接拼 `/_perspectives_/tags#xxx`,没考虑 `cleanUrls`。现走 `applyCleanUrls`,需要 `.html` 时自动加。
|
|
16
|
+
- **`%% block comment %%` 包了 ``` fence 时提前结束**:扫描闭合 `%%` 没跟踪 fence 状态,fence 内的 `%%` 字面行会把注释关掉,导致 fence 残留。改成同时跟踪 ``` / ~~~ 配对状态,只在 fence 外才允许关闭。
|
|
17
|
+
- **`views.urlPrefix` 自定义后 sidebar fallback 失效**:`buildPerspectivesFallbackSidebar` 硬编码 `_perspectives_/`,用户改 `views.urlPrefix: 'extras'` 后过滤失效,会在视图页 sidebar 看到一个指向自己的"前往 Extras"项。现接 `viewsPrefix` 参数。
|
|
18
|
+
- **i18n locale Perspectives 注入不对称**:(a) per-locale sidebar 生成后没过 `injectViewsSidebar`,EN locale 等丢 Perspectives 组;(b) nav 注入老逻辑要求 `lc.themeConfig.nav !== undefined`,没自定义 nav 的 locale 拿不到下拉。两边都修。
|
|
19
|
+
- **graph 视图丢相对路径 wikilink 边**:`resolveTargetSimple` 不接 `currentSourceRel`,与 `resolver.ts:117` 行为不一致,从而 sibling 笔记的相对链接在 Graph 上看不见。补齐相对路径 fallback。
|
|
20
|
+
- **`_sidebar.md` fence 检测同 `%%` 同症**:`/^```|^~~~/` 任一 marker 都切状态,`~~~` 在 ``` 块里会提前结束。改成 marker 配对跟踪。
|
|
21
|
+
- **`callout` 标题不解析 inline markdown**:`[!info] **Newton**` 之前显示字面 `**Newton**`。Obsidian 实际会渲染。现走 `md.renderInline`(用户传了自定义标题时)。
|
|
22
|
+
- **`webm` 同时在 audio/video 列表**:`classifyMediaExt` video-first,所有 `.webm` 一律渲染为 `<video>`。从 `AUDIO_EXTS` 删掉。
|
|
23
|
+
- **静默 `catch{}` 加日志**:`writeVaultData` 失败、`scanWikilinks` 失败之前都吞错,debug "Graph 不更新"非常难找。改成 `console.warn`。
|
|
24
|
+
|
|
25
|
+
### Tests
|
|
26
|
+
- 新增 `tests/v034-bugfixes.test.ts`,每个 RED bug 一条回归用例。
|
|
27
|
+
|
|
28
|
+
## [0.3.3] - 2026-05-20
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- **`sidebarAuto.foldersFirst`** — 控制同一层级内"普通文件 vs 子目录 group"的相对位置。
|
|
32
|
+
- `false`(默认)`files → virtualGroups → folders`(老行为,兼容)
|
|
33
|
+
- `true` `folders → virtualGroups → files`(Finder / Obsidian 风格)
|
|
34
|
+
- 仅影响相对位置;段内排序仍由 `sortBy` / `orderKey` / `groupOrder` 决定。
|
|
35
|
+
|
|
36
|
+
## [0.3.2] - 2026-05-20
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
- **根目录无 `index.md` 时 404**:`autoFolderIndex: 'top-level' / 'all'` 模式之前只为 srcDir **下**的目录生成 index,根本身被漏。现在 `dirsToProcess` 把 srcDir 根也加进去,根索引页用 `srcDir` basename 当 H1(fallback `Home`)。
|
|
40
|
+
|
|
5
41
|
## [0.3.1] - 2026-05-20
|
|
6
42
|
|
|
7
43
|
### Fixed
|
package/dist/index.cjs
CHANGED
|
@@ -772,13 +772,47 @@ function defaultLabel(target, headingPart, entry, options) {
|
|
|
772
772
|
}
|
|
773
773
|
return base;
|
|
774
774
|
}
|
|
775
|
-
function resolveAsset(rawTarget, index, options) {
|
|
775
|
+
function resolveAsset(rawTarget, index, options, currentSourcePath) {
|
|
776
776
|
const target = toPosix(rawTarget).trim();
|
|
777
777
|
if (target.includes("/")) {
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
rawBasename: basename(target)
|
|
781
|
-
}
|
|
778
|
+
const direct = index.assetsByRelativePath.get(target);
|
|
779
|
+
if (direct) {
|
|
780
|
+
return { asset: direct, rawBasename: basename(target) };
|
|
781
|
+
}
|
|
782
|
+
if (currentSourcePath) {
|
|
783
|
+
const srcDirAbs = index.srcDir;
|
|
784
|
+
const cur = toPosix(currentSourcePath);
|
|
785
|
+
const rel = cur.startsWith(srcDirAbs + "/") ? cur.slice(srcDirAbs.length + 1) : "";
|
|
786
|
+
if (rel) {
|
|
787
|
+
const curDir = rel.split("/").slice(0, -1).join("/");
|
|
788
|
+
if (curDir) {
|
|
789
|
+
const relAsset = index.assetsByRelativePath.get(`${curDir}/${target}`);
|
|
790
|
+
if (relAsset) {
|
|
791
|
+
return { asset: relAsset, rawBasename: basename(target) };
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
const bn0 = options.caseSensitive ? basename(target) : basename(target).toLowerCase();
|
|
797
|
+
const map0 = options.caseSensitive ? index.assetsByBasename : index.assetsByBasenameLower;
|
|
798
|
+
const fallback = map0.get(bn0);
|
|
799
|
+
if (fallback && fallback.length === 1) {
|
|
800
|
+
return { asset: fallback[0], rawBasename: basename(target) };
|
|
801
|
+
}
|
|
802
|
+
if (fallback && fallback.length > 1) {
|
|
803
|
+
switch (options.onConflict) {
|
|
804
|
+
case "shortest":
|
|
805
|
+
return {
|
|
806
|
+
asset: sortByShortestPath(fallback)[0],
|
|
807
|
+
rawBasename: basename(target)
|
|
808
|
+
};
|
|
809
|
+
case "first":
|
|
810
|
+
return { asset: fallback[0], rawBasename: basename(target) };
|
|
811
|
+
case "error":
|
|
812
|
+
return { asset: void 0, rawBasename: basename(target) };
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
return { asset: void 0, rawBasename: basename(target) };
|
|
782
816
|
}
|
|
783
817
|
const bn = options.caseSensitive ? target : target.toLowerCase();
|
|
784
818
|
const map = options.caseSensitive ? index.assetsByBasename : index.assetsByBasenameLower;
|
|
@@ -903,7 +937,7 @@ function renderImageHtml(rawTarget, aliasParts, env) {
|
|
|
903
937
|
const { index, options } = env;
|
|
904
938
|
const { altText, dim } = parseAltAndDim(aliasParts);
|
|
905
939
|
const processedTarget = options.embeds.postProcessImageTarget(rawTarget);
|
|
906
|
-
const { asset } = resolveAsset(processedTarget, index, options);
|
|
940
|
+
const { asset } = resolveAsset(processedTarget, index, options, env.currentPath);
|
|
907
941
|
let src;
|
|
908
942
|
if (asset) {
|
|
909
943
|
asset.referencedBy.add(env.currentPath ?? "<unknown>");
|
|
@@ -997,7 +1031,13 @@ function escapeAttrName(k) {
|
|
|
997
1031
|
// src/modules/embeds/transclusion.ts
|
|
998
1032
|
function renderTransclusionHtml(md, rawTarget, aliasParts, env) {
|
|
999
1033
|
const { index, options } = env;
|
|
1000
|
-
const result = resolveWikilink(
|
|
1034
|
+
const result = resolveWikilink(
|
|
1035
|
+
rawTarget,
|
|
1036
|
+
index,
|
|
1037
|
+
options,
|
|
1038
|
+
"transclusion",
|
|
1039
|
+
env.currentPath
|
|
1040
|
+
);
|
|
1001
1041
|
if (result.isDead || !result.target) {
|
|
1002
1042
|
return `<div class="transclusion transclusion--dead" data-target="${escapeHtml(
|
|
1003
1043
|
rawTarget
|
|
@@ -1070,7 +1110,7 @@ function handleTransclusion(state, rawTarget, aliasParts, env) {
|
|
|
1070
1110
|
);
|
|
1071
1111
|
}
|
|
1072
1112
|
const { index, options } = env;
|
|
1073
|
-
const result = resolveWikilink(rawTarget, index, options, "page");
|
|
1113
|
+
const result = resolveWikilink(rawTarget, index, options, "page", env.currentPath);
|
|
1074
1114
|
const url = result.url;
|
|
1075
1115
|
const label = aliasParts.length ? aliasParts.join("|").trim() : result.defaultLabel;
|
|
1076
1116
|
const html = `<a class="wikilink wikilink--inline-transclusion-degraded" href="${escapeHtml(url)}" data-wikilink-target="${escapeHtml(rawTarget)}" title="\u884C\u5185 transclusion \u5DF2\u964D\u7EA7,\u89C1\u63A7\u5236\u53F0">${escapeHtml(label)}</a>`;
|
|
@@ -1108,7 +1148,7 @@ function getCache(env) {
|
|
|
1108
1148
|
}
|
|
1109
1149
|
|
|
1110
1150
|
// src/modules/embeds/media.ts
|
|
1111
|
-
var AUDIO_EXTS = ["mp3", "wav", "ogg", "m4a", "flac", "aac"
|
|
1151
|
+
var AUDIO_EXTS = ["mp3", "wav", "ogg", "m4a", "flac", "aac"];
|
|
1112
1152
|
var VIDEO_EXTS = ["mp4", "webm", "mov", "m4v", "avi", "mkv"];
|
|
1113
1153
|
var PDF_EXTS = ["pdf"];
|
|
1114
1154
|
function isAudioExt(ext) {
|
|
@@ -1146,7 +1186,7 @@ function parseAliasDim(parts) {
|
|
|
1146
1186
|
function resolveSrc(rawTarget, env) {
|
|
1147
1187
|
const { index, options } = env;
|
|
1148
1188
|
const processedTarget = options.embeds.postProcessImageTarget(rawTarget);
|
|
1149
|
-
const { asset } = resolveAsset(processedTarget, index, options);
|
|
1189
|
+
const { asset } = resolveAsset(processedTarget, index, options, env.currentPath);
|
|
1150
1190
|
if (asset) {
|
|
1151
1191
|
asset.referencedBy.add(env.currentPath ?? "<unknown>");
|
|
1152
1192
|
env.referencedAssets?.add(asset);
|
|
@@ -1188,6 +1228,11 @@ function handleMediaEmbed(state, kind, rawTarget, aliasParts, env) {
|
|
|
1188
1228
|
return true;
|
|
1189
1229
|
}
|
|
1190
1230
|
|
|
1231
|
+
// src/utils/wikilink.ts
|
|
1232
|
+
function splitWikilinkInner(inner) {
|
|
1233
|
+
return inner.split(/\\?\|/).map((p) => p.trim());
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1191
1236
|
// src/modules/wikilinks/rule.ts
|
|
1192
1237
|
function makeWikilinkRule(scope) {
|
|
1193
1238
|
return function wikilinkRule(state, silent) {
|
|
@@ -1216,7 +1261,7 @@ function makeWikilinkRule(scope) {
|
|
|
1216
1261
|
return false;
|
|
1217
1262
|
}
|
|
1218
1263
|
state.pos = closeIdx + 2;
|
|
1219
|
-
const parts = inner
|
|
1264
|
+
const parts = splitWikilinkInner(inner);
|
|
1220
1265
|
const rawTarget = parts[0];
|
|
1221
1266
|
const aliasParts = parts.slice(1);
|
|
1222
1267
|
if (isEmbed) {
|
|
@@ -1310,7 +1355,7 @@ function makeRule(md) {
|
|
|
1310
1355
|
const env = state.env;
|
|
1311
1356
|
if (!env || !env.index || !env.options) return false;
|
|
1312
1357
|
const inner = m[1];
|
|
1313
|
-
const parts = inner
|
|
1358
|
+
const parts = splitWikilinkInner(inner);
|
|
1314
1359
|
const rawTarget = parts[0];
|
|
1315
1360
|
const aliasParts = parts.slice(1);
|
|
1316
1361
|
const ext = extractExt2(rawTarget);
|
|
@@ -1445,7 +1490,7 @@ function registerCalloutsCore(md) {
|
|
|
1445
1490
|
const header = extractHeader(inner);
|
|
1446
1491
|
if (!header) continue;
|
|
1447
1492
|
const bodyHtml = renderBody(inner, header.firstLineRest, md, state.env);
|
|
1448
|
-
const html = renderCallout(header.parsed, bodyHtml);
|
|
1493
|
+
const html = renderCallout(header.parsed, bodyHtml, md, state.env);
|
|
1449
1494
|
const newToken = new state.Token("html_block", "", 0);
|
|
1450
1495
|
newToken.content = html + "\n";
|
|
1451
1496
|
newToken.map = t.map;
|
|
@@ -1502,16 +1547,17 @@ function renderBody(inner, firstLineRest, md, env) {
|
|
|
1502
1547
|
}
|
|
1503
1548
|
return md.renderer.render(cloned, md.options, env);
|
|
1504
1549
|
}
|
|
1505
|
-
function renderCallout(header, bodyHtml) {
|
|
1550
|
+
function renderCallout(header, bodyHtml, md, env) {
|
|
1506
1551
|
const { type, foldable, title } = header;
|
|
1507
|
-
const
|
|
1552
|
+
const rawTitle = title || DEFAULT_TITLES[type];
|
|
1553
|
+
const titleHtml = title ? md.renderInline(rawTitle, env) : escapeHtml(rawTitle);
|
|
1508
1554
|
const iconSvg = `<svg class="callout-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">` + CALLOUT_ICONS[type] + `</svg>`;
|
|
1509
1555
|
const cls = `callout callout--${type}` + (foldable ? " callout--foldable" : "");
|
|
1510
1556
|
if (foldable) {
|
|
1511
1557
|
const isOpen = foldable === "open";
|
|
1512
|
-
return `<details class="${cls}" data-callout="${type}"${isOpen ? " open" : ""}><summary class="callout-title">${iconSvg}<span class="callout-title-text">${
|
|
1558
|
+
return `<details class="${cls}" data-callout="${type}"${isOpen ? " open" : ""}><summary class="callout-title">${iconSvg}<span class="callout-title-text">${titleHtml}</span></summary><div class="callout-content">${bodyHtml}</div></details>`;
|
|
1513
1559
|
}
|
|
1514
|
-
return `<div class="${cls}" data-callout="${type}"><div class="callout-title">${iconSvg}<span class="callout-title-text">${
|
|
1560
|
+
return `<div class="${cls}" data-callout="${type}"><div class="callout-title">${iconSvg}<span class="callout-title-text">${titleHtml}</span></div><div class="callout-content">${bodyHtml}</div></div>`;
|
|
1515
1561
|
}
|
|
1516
1562
|
|
|
1517
1563
|
// src/modules/callouts/index.ts
|
|
@@ -1666,12 +1712,25 @@ function makeCommentBlockRule() {
|
|
|
1666
1712
|
if (silent) return true;
|
|
1667
1713
|
let next = startLine + 1;
|
|
1668
1714
|
let closed = false;
|
|
1715
|
+
let fenceMarker = null;
|
|
1669
1716
|
while (next < endLine) {
|
|
1670
1717
|
const lpos = state.bMarks[next] + state.tShift[next];
|
|
1671
1718
|
const lmax = state.eMarks[next];
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1719
|
+
const lineText = state.src.slice(lpos, lmax);
|
|
1720
|
+
const trimmed = lineText.trim();
|
|
1721
|
+
const fm = /^(`{3,}|~{3,})/.exec(trimmed);
|
|
1722
|
+
if (fm) {
|
|
1723
|
+
const ch = fm[1][0];
|
|
1724
|
+
if (fenceMarker === null) fenceMarker = ch;
|
|
1725
|
+
else if (fenceMarker === ch) fenceMarker = null;
|
|
1726
|
+
next += 1;
|
|
1727
|
+
continue;
|
|
1728
|
+
}
|
|
1729
|
+
if (fenceMarker === null) {
|
|
1730
|
+
if (lpos + 2 <= lmax && state.src.charCodeAt(lpos) === PCT && state.src.charCodeAt(lpos + 1) === PCT && state.src.slice(lpos + 2, lmax).trim() === "") {
|
|
1731
|
+
closed = true;
|
|
1732
|
+
break;
|
|
1733
|
+
}
|
|
1675
1734
|
}
|
|
1676
1735
|
next += 1;
|
|
1677
1736
|
}
|
|
@@ -2085,7 +2144,7 @@ function renderTemplate(v) {
|
|
|
2085
2144
|
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
2086
2145
|
var import_node_path7 = __toESM(require("path"), 1);
|
|
2087
2146
|
var PLUGIN_VERSION = "0.2.0-beta.0";
|
|
2088
|
-
var WIKILINK_RE = /(!?)\[\[([^\]\n
|
|
2147
|
+
var WIKILINK_RE = /(!?)\[\[([^\]\n]+)\]\]/g;
|
|
2089
2148
|
var BODY_TAG_RE = /(?:^|[\s([{,;。,;])#([\p{L}_][\p{L}\p{N}_/-]*)/gu;
|
|
2090
2149
|
function buildVaultData(index, options) {
|
|
2091
2150
|
const viewsPrefix = options.views.urlPrefix ? options.views.urlPrefix.replace(/^\/+|\/+$/g, "") + "/" : "";
|
|
@@ -2112,8 +2171,13 @@ function buildVaultData(index, options) {
|
|
|
2112
2171
|
const matches = f.content.matchAll(WIKILINK_RE);
|
|
2113
2172
|
for (const m of matches) {
|
|
2114
2173
|
const isEmbed = m[1] === "!";
|
|
2115
|
-
const
|
|
2116
|
-
|
|
2174
|
+
const inner = m[2];
|
|
2175
|
+
let rawTarget = splitWikilinkInner(inner)[0] ?? "";
|
|
2176
|
+
const hashIdx = rawTarget.indexOf("#");
|
|
2177
|
+
if (hashIdx >= 0) rawTarget = rawTarget.slice(0, hashIdx);
|
|
2178
|
+
rawTarget = rawTarget.trim();
|
|
2179
|
+
if (!rawTarget) continue;
|
|
2180
|
+
const target = resolveTargetSimple(rawTarget, index, options, f.relativePath);
|
|
2117
2181
|
if (!target) continue;
|
|
2118
2182
|
if (isPerspective(target)) continue;
|
|
2119
2183
|
if (target.relativePath === f.relativePath) continue;
|
|
@@ -2204,11 +2268,28 @@ function pickTitle(f) {
|
|
|
2204
2268
|
}
|
|
2205
2269
|
return f.basename;
|
|
2206
2270
|
}
|
|
2207
|
-
function resolveTargetSimple(rawTarget, index, options) {
|
|
2271
|
+
function resolveTargetSimple(rawTarget, index, options, currentSourceRel) {
|
|
2208
2272
|
const target = stripMarkdownExt(toPosix(rawTarget));
|
|
2209
2273
|
if (!target) return void 0;
|
|
2210
2274
|
if (target.includes("/")) {
|
|
2211
|
-
|
|
2275
|
+
const direct = index.byRelativePath.get(target) ?? index.byRelativePath.get(target + ".md") ?? index.byRelativePath.get(target + ".markdown") ?? index.byRelativePath.get(target + "/index.md") ?? index.byRelativePath.get(target + "/index.markdown");
|
|
2276
|
+
if (direct) return direct;
|
|
2277
|
+
if (currentSourceRel) {
|
|
2278
|
+
const curDir = currentSourceRel.split("/").slice(0, -1).join("/");
|
|
2279
|
+
if (curDir) {
|
|
2280
|
+
for (const v of [
|
|
2281
|
+
`${curDir}/${target}`,
|
|
2282
|
+
`${curDir}/${target}.md`,
|
|
2283
|
+
`${curDir}/${target}.markdown`,
|
|
2284
|
+
`${curDir}/${target}/index.md`,
|
|
2285
|
+
`${curDir}/${target}/index.markdown`
|
|
2286
|
+
]) {
|
|
2287
|
+
const e = index.byRelativePath.get(v);
|
|
2288
|
+
if (e) return e;
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
return void 0;
|
|
2212
2293
|
}
|
|
2213
2294
|
const aliasKey = options.caseSensitive ? target : target.toLowerCase();
|
|
2214
2295
|
const aliased = index.byAlias.get(aliasKey);
|
|
@@ -2323,7 +2404,11 @@ function viteAllYouNeed(userOptions = {}) {
|
|
|
2323
2404
|
if (resolved.modules.views) {
|
|
2324
2405
|
try {
|
|
2325
2406
|
writeVaultData(index, resolved);
|
|
2326
|
-
} catch {
|
|
2407
|
+
} catch (e) {
|
|
2408
|
+
console.warn(
|
|
2409
|
+
"vitepress-allyouneed: \u91CD\u65B0\u5199 vault-data.json \u5931\u8D25,Graph/Stats/Tags \u53EF\u80FD\u4E0D\u66F4\u65B0\u3002",
|
|
2410
|
+
e instanceof Error ? e.message : String(e)
|
|
2411
|
+
);
|
|
2327
2412
|
}
|
|
2328
2413
|
}
|
|
2329
2414
|
},
|
|
@@ -2392,8 +2477,10 @@ function makeTagRule() {
|
|
|
2392
2477
|
const tagsViewName = env.options?.views?.names?.tags ?? "tags";
|
|
2393
2478
|
const urlPrefix = env.options?.views?.urlPrefix ?? "_perspectives_";
|
|
2394
2479
|
const base = env.options?.base ?? "/";
|
|
2480
|
+
const cleanUrls = env.options?.cleanUrls ?? true;
|
|
2395
2481
|
const prefixSeg = urlPrefix ? `${urlPrefix}/` : "";
|
|
2396
|
-
const
|
|
2482
|
+
const pagePath = applyCleanUrls(`${prefixSeg}${tagsViewName}`, cleanUrls);
|
|
2483
|
+
const href = `${base}${pagePath}#${encodeURIComponent(tag)}`;
|
|
2397
2484
|
const html = `<a class="ayn-tag" data-tag="${escapeHtml(tag)}" href="${escapeHtml(href)}">#${escapeHtml(tag)}</a>`;
|
|
2398
2485
|
const token = state.push("html_inline", "", 0);
|
|
2399
2486
|
token.content = html;
|
|
@@ -2434,7 +2521,8 @@ function injectViewsSidebar(sidebar, options) {
|
|
|
2434
2521
|
sidebar[persPath] = buildPerspectivesFallbackSidebar(
|
|
2435
2522
|
sidebar,
|
|
2436
2523
|
group,
|
|
2437
|
-
options.base.endsWith("/") ? options.base : options.base + "/"
|
|
2524
|
+
options.base.endsWith("/") ? options.base : options.base + "/",
|
|
2525
|
+
prefix
|
|
2438
2526
|
);
|
|
2439
2527
|
}
|
|
2440
2528
|
}
|
|
@@ -2442,10 +2530,11 @@ function injectViewsSidebar(sidebar, options) {
|
|
|
2442
2530
|
}
|
|
2443
2531
|
return [group];
|
|
2444
2532
|
}
|
|
2445
|
-
function buildPerspectivesFallbackSidebar(allSidebars, group, base) {
|
|
2533
|
+
function buildPerspectivesFallbackSidebar(allSidebars, group, base, viewsPrefix) {
|
|
2446
2534
|
const out = [{ text: "Home", link: "/" }];
|
|
2535
|
+
const persSuffix = `/${viewsPrefix}/`;
|
|
2447
2536
|
const topPaths = Object.keys(allSidebars).filter(
|
|
2448
|
-
(p) => p !== base && !p.endsWith(
|
|
2537
|
+
(p) => p !== base && !p.endsWith(persSuffix)
|
|
2449
2538
|
);
|
|
2450
2539
|
for (const p of topPaths) {
|
|
2451
2540
|
const seg = p.replace(/^\/|\/$/g, "").split("/").filter(Boolean).pop() ?? p;
|
|
@@ -2522,18 +2611,22 @@ function normalizeItems(items) {
|
|
|
2522
2611
|
});
|
|
2523
2612
|
}
|
|
2524
2613
|
var LINE_RE2 = /^(\s*)-\s+(.*)$/;
|
|
2525
|
-
var WIKILINK_RE2 = /^\[\[([^\]\n
|
|
2614
|
+
var WIKILINK_RE2 = /^\[\[([^\]\n]+)\]\]/;
|
|
2526
2615
|
var MD_LINK_RE = /^\[([^\]]+)\]\(([^)]+)\)/;
|
|
2527
2616
|
function parseList(src, entry, index, options) {
|
|
2528
2617
|
const lines = src.split(/\r?\n/);
|
|
2529
2618
|
const parsed = [];
|
|
2530
|
-
let
|
|
2619
|
+
let fenceMarker = null;
|
|
2531
2620
|
for (const raw of lines) {
|
|
2532
|
-
|
|
2533
|
-
|
|
2621
|
+
const trimmed = raw.trim();
|
|
2622
|
+
const fenceMatch = /^(`{3,}|~{3,})/.exec(trimmed);
|
|
2623
|
+
if (fenceMatch) {
|
|
2624
|
+
const ch = fenceMatch[1][0];
|
|
2625
|
+
if (fenceMarker === null) fenceMarker = ch;
|
|
2626
|
+
else if (fenceMarker === ch) fenceMarker = null;
|
|
2534
2627
|
continue;
|
|
2535
2628
|
}
|
|
2536
|
-
if (
|
|
2629
|
+
if (fenceMarker !== null) continue;
|
|
2537
2630
|
const m = LINE_RE2.exec(raw);
|
|
2538
2631
|
if (!m) continue;
|
|
2539
2632
|
const indent = m[1].replace(/\t/g, " ").length;
|
|
@@ -2545,12 +2638,16 @@ function parseList(src, entry, index, options) {
|
|
|
2545
2638
|
function parseLineBody(indent, body, entry, index, options) {
|
|
2546
2639
|
const wl = WIKILINK_RE2.exec(body);
|
|
2547
2640
|
if (wl) {
|
|
2548
|
-
const
|
|
2549
|
-
const
|
|
2550
|
-
|
|
2641
|
+
const inner = wl[1];
|
|
2642
|
+
const parts = splitWikilinkInner(inner);
|
|
2643
|
+
let rawTarget = parts[0];
|
|
2644
|
+
const customText = parts[1] ?? void 0;
|
|
2645
|
+
const hashIdx = rawTarget.indexOf("#");
|
|
2646
|
+
if (hashIdx >= 0) rawTarget = rawTarget.slice(0, hashIdx);
|
|
2647
|
+
const resolved = resolveTarget(rawTarget, index, options, entry);
|
|
2551
2648
|
return {
|
|
2552
2649
|
indent,
|
|
2553
|
-
text: customText ?? defaultTextForTarget(
|
|
2650
|
+
text: customText ?? defaultTextForTarget(rawTarget, resolved),
|
|
2554
2651
|
link: resolved?.url ?? null
|
|
2555
2652
|
};
|
|
2556
2653
|
}
|
|
@@ -2663,7 +2760,8 @@ function resolveSidebarAutoOptions(user = {}) {
|
|
|
2663
2760
|
maxDepth: user.maxDepth,
|
|
2664
2761
|
groupLink: user.groupLink ?? "all",
|
|
2665
2762
|
includePrefix: user.includePrefix,
|
|
2666
|
-
excludePrefixes: user.excludePrefixes ?? []
|
|
2763
|
+
excludePrefixes: user.excludePrefixes ?? [],
|
|
2764
|
+
foldersFirst: user.foldersFirst ?? false
|
|
2667
2765
|
};
|
|
2668
2766
|
}
|
|
2669
2767
|
function defaultItemTitle(entry, strip) {
|
|
@@ -2678,7 +2776,7 @@ function defaultItemTitle(entry, strip) {
|
|
|
2678
2776
|
}
|
|
2679
2777
|
function humanize(name, strip) {
|
|
2680
2778
|
let s = name;
|
|
2681
|
-
if (strip) s = s.replace(/^\d+[-_
|
|
2779
|
+
if (strip) s = s.replace(/^\d+[-_\s]+/, "");
|
|
2682
2780
|
return s.replace(/[-_]+/g, " ").replace(/\s+/g, " ").trim().replace(/\b\w/g, (m) => m.toUpperCase());
|
|
2683
2781
|
}
|
|
2684
2782
|
function newNode(path) {
|
|
@@ -2787,7 +2885,6 @@ function renderNode(node, opts, depth, isRoot, index, options) {
|
|
|
2787
2885
|
const override = parseSidebarOverride(node.sidebarOverride, index, options);
|
|
2788
2886
|
if (override) return override;
|
|
2789
2887
|
}
|
|
2790
|
-
const out = [];
|
|
2791
2888
|
const virtualGroups = /* @__PURE__ */ new Map();
|
|
2792
2889
|
const normalFiles = [];
|
|
2793
2890
|
for (const f of node.files) {
|
|
@@ -2801,18 +2898,21 @@ function renderNode(node, opts, depth, isRoot, index, options) {
|
|
|
2801
2898
|
}
|
|
2802
2899
|
}
|
|
2803
2900
|
normalFiles.sort((a, b) => compareEntries(a, b, opts));
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2901
|
+
const fileItems = normalFiles.map((f) => ({
|
|
2902
|
+
text: opts.formatItemTitle(f),
|
|
2903
|
+
link: f.url
|
|
2904
|
+
}));
|
|
2807
2905
|
const virtualKeys = [...virtualGroups.keys()].sort();
|
|
2906
|
+
const virtualItems = [];
|
|
2808
2907
|
for (const name of virtualKeys) {
|
|
2809
2908
|
const items = virtualGroups.get(name).sort((a, b) => compareEntries(a, b, opts));
|
|
2810
|
-
|
|
2909
|
+
virtualItems.push({
|
|
2811
2910
|
text: name,
|
|
2812
2911
|
collapsed: opts.collapsed,
|
|
2813
2912
|
items: items.map((f) => ({ text: opts.formatItemTitle(f), link: f.url }))
|
|
2814
2913
|
});
|
|
2815
2914
|
}
|
|
2915
|
+
const folderItems = [];
|
|
2816
2916
|
const childKeys = sortChildKeys(node, opts, isRoot);
|
|
2817
2917
|
for (const key of childKeys) {
|
|
2818
2918
|
const child = node.children.get(key);
|
|
@@ -2826,9 +2926,12 @@ function renderNode(node, opts, depth, isRoot, index, options) {
|
|
|
2826
2926
|
if (child.dirIndex && !child.dirIndexEmpty && shouldLinkGroup(opts, isRoot)) {
|
|
2827
2927
|
group.link = child.dirIndex.url;
|
|
2828
2928
|
}
|
|
2829
|
-
|
|
2929
|
+
folderItems.push(group);
|
|
2830
2930
|
}
|
|
2831
|
-
|
|
2931
|
+
if (opts.foldersFirst) {
|
|
2932
|
+
return [...folderItems, ...virtualItems, ...fileItems];
|
|
2933
|
+
}
|
|
2934
|
+
return [...fileItems, ...virtualItems, ...folderItems];
|
|
2832
2935
|
}
|
|
2833
2936
|
function findFirstPageUrl(node, opts) {
|
|
2834
2937
|
if (node.dirIndex && !node.dirIndexEmpty) return node.dirIndex.url;
|
|
@@ -3249,11 +3352,12 @@ function matchGlob(path, pat) {
|
|
|
3249
3352
|
function humanize2(name, stripNumeric) {
|
|
3250
3353
|
let s = name;
|
|
3251
3354
|
if (stripNumeric) {
|
|
3252
|
-
s = s.replace(/^\d+[-_
|
|
3355
|
+
s = s.replace(/^\d+[-_\s]+/, "");
|
|
3253
3356
|
}
|
|
3254
3357
|
return s.replace(/[-_]+/g, " ").replace(/\s+/g, " ").trim().replace(/\b\w/g, (m) => m.toUpperCase());
|
|
3255
3358
|
}
|
|
3256
3359
|
function defaultTemplate(ctx) {
|
|
3360
|
+
const prefix = ctx.dirRelPath === "" ? "" : `${ctx.dirRelPath}/`;
|
|
3257
3361
|
const lines = [];
|
|
3258
3362
|
lines.push("---");
|
|
3259
3363
|
lines.push(`title: ${ctx.title}`);
|
|
@@ -3267,7 +3371,7 @@ function defaultTemplate(ctx) {
|
|
|
3267
3371
|
lines.push("## Sections");
|
|
3268
3372
|
lines.push("");
|
|
3269
3373
|
for (const d of ctx.subDirs) {
|
|
3270
|
-
lines.push(`- [[${
|
|
3374
|
+
lines.push(`- [[${prefix}${d.name}/|${d.title}]]`);
|
|
3271
3375
|
}
|
|
3272
3376
|
lines.push("");
|
|
3273
3377
|
}
|
|
@@ -3275,7 +3379,7 @@ function defaultTemplate(ctx) {
|
|
|
3275
3379
|
lines.push("## Pages");
|
|
3276
3380
|
lines.push("");
|
|
3277
3381
|
for (const f of ctx.files) {
|
|
3278
|
-
lines.push(`- [[${
|
|
3382
|
+
lines.push(`- [[${prefix}${f.relPath}|${f.title}]]`);
|
|
3279
3383
|
}
|
|
3280
3384
|
lines.push("");
|
|
3281
3385
|
}
|
|
@@ -3283,7 +3387,7 @@ function defaultTemplate(ctx) {
|
|
|
3283
3387
|
}
|
|
3284
3388
|
|
|
3285
3389
|
// src/core/scan-wikilinks.ts
|
|
3286
|
-
var WIKILINK_RE3 = /(!?)\[\[([^\]\n
|
|
3390
|
+
var WIKILINK_RE3 = /(!?)\[\[([^\]\n]+)\]\]/g;
|
|
3287
3391
|
function stripCodeForScan(src) {
|
|
3288
3392
|
let r = src.replace(/```[\s\S]*?```/g, (m) => " ".repeat(m.length));
|
|
3289
3393
|
r = r.replace(/~~~[\s\S]*?~~~/g, (m) => " ".repeat(m.length));
|
|
@@ -3299,7 +3403,12 @@ function scanWikilinks(index, options) {
|
|
|
3299
3403
|
for (const m of matches) {
|
|
3300
3404
|
total += 1;
|
|
3301
3405
|
const isEmbed = m[1] === "!";
|
|
3302
|
-
const
|
|
3406
|
+
const inner = m[2];
|
|
3407
|
+
let rawTarget = splitWikilinkInner(inner)[0] ?? "";
|
|
3408
|
+
const hashIdx = rawTarget.indexOf("#");
|
|
3409
|
+
if (hashIdx >= 0) rawTarget = rawTarget.slice(0, hashIdx);
|
|
3410
|
+
rawTarget = rawTarget.trim();
|
|
3411
|
+
if (!rawTarget) continue;
|
|
3303
3412
|
if (isEmbed) {
|
|
3304
3413
|
const ext = extractExt3(rawTarget);
|
|
3305
3414
|
if (ext) {
|
|
@@ -3439,7 +3548,11 @@ function defineConfigWithAllYouNeed(config, pluginOptions = {}) {
|
|
|
3439
3548
|
try {
|
|
3440
3549
|
const report = scanWikilinks(index, resolvedForWrapper);
|
|
3441
3550
|
logDeadLinks(report, resolvedForWrapper.deadLink);
|
|
3442
|
-
} catch {
|
|
3551
|
+
} catch (e) {
|
|
3552
|
+
console.warn(
|
|
3553
|
+
"vitepress-allyouneed: scanWikilinks \u5931\u8D25,\u8DF3\u8FC7\u6B7B\u94FE\u6C47\u603B\u3002",
|
|
3554
|
+
e instanceof Error ? e.message : String(e)
|
|
3555
|
+
);
|
|
3443
3556
|
}
|
|
3444
3557
|
const localesObj = config.locales;
|
|
3445
3558
|
const localeKeys = localesObj ? Object.keys(localesObj).filter((k) => k !== "root") : [];
|
|
@@ -3488,17 +3601,25 @@ function defineConfigWithAllYouNeed(config, pluginOptions = {}) {
|
|
|
3488
3601
|
themeConfig.nav,
|
|
3489
3602
|
resolvedForWrapper
|
|
3490
3603
|
);
|
|
3491
|
-
const
|
|
3492
|
-
if (
|
|
3493
|
-
for (const lang of Object.keys(
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
if (lc.themeConfig.
|
|
3497
|
-
|
|
3498
|
-
|
|
3604
|
+
const localesForViews = config.locales;
|
|
3605
|
+
if (localesForViews) {
|
|
3606
|
+
for (const lang of Object.keys(localesForViews)) {
|
|
3607
|
+
if (lang === "root") continue;
|
|
3608
|
+
const lc = localesForViews[lang];
|
|
3609
|
+
if (!lc.themeConfig) lc.themeConfig = {};
|
|
3610
|
+
if (lc.themeConfig.sidebar !== void 0) {
|
|
3611
|
+
lc.themeConfig.sidebar = injectViewsSidebar(
|
|
3612
|
+
lc.themeConfig.sidebar,
|
|
3499
3613
|
resolvedForWrapper
|
|
3500
3614
|
);
|
|
3501
3615
|
}
|
|
3616
|
+
const navInjected = injectViewsNav(
|
|
3617
|
+
lc.themeConfig.nav,
|
|
3618
|
+
resolvedForWrapper
|
|
3619
|
+
);
|
|
3620
|
+
if (navInjected !== void 0) {
|
|
3621
|
+
lc.themeConfig.nav = navInjected;
|
|
3622
|
+
}
|
|
3502
3623
|
}
|
|
3503
3624
|
}
|
|
3504
3625
|
}
|