fuma-content 1.1.2 → 1.1.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/dist/async-cache-BVuJiIDT.d.ts +9 -0
- package/dist/async-cache-BVuJiIDT.d.ts.map +1 -0
- package/dist/{async-cache-U87GzQTb.js → async-cache-DRmFaVGm.js} +1 -1
- package/dist/{async-cache-U87GzQTb.js.map → async-cache-DRmFaVGm.js.map} +1 -1
- package/dist/build-mdx-DRqbcE1d.d.ts +79 -0
- package/dist/build-mdx-DRqbcE1d.d.ts.map +1 -0
- package/dist/{build-mdx-CUp6FpfT.js → build-mdx-DgzggXIL.js} +27 -40
- package/dist/build-mdx-DgzggXIL.js.map +1 -0
- package/dist/bun/index.d.ts +1 -1
- package/dist/bun/index.d.ts.map +1 -1
- package/dist/bun/index.js +2 -2
- package/dist/{bun-CBROq3I0.js → bun-Be5pgXW_.js} +4 -3
- package/dist/bun-Be5pgXW_.js.map +1 -0
- package/dist/{code-generator-Qhhq7kHh.js → code-generator-CHcOrCeM.js} +5 -7
- package/dist/code-generator-CHcOrCeM.js.map +1 -0
- package/dist/collections/data/runtime.d.ts +3 -6
- package/dist/collections/data/runtime.d.ts.map +1 -1
- package/dist/collections/data/runtime.js.map +1 -1
- package/dist/collections/data.d.ts +4 -4
- package/dist/collections/data.d.ts.map +1 -1
- package/dist/collections/data.js +158 -4
- package/dist/collections/data.js.map +1 -0
- package/dist/collections/fs.d.ts +45 -3
- package/dist/collections/fs.d.ts.map +1 -0
- package/dist/collections/fs.js +65 -2
- package/dist/collections/fs.js.map +1 -0
- package/dist/collections/index.d.ts +37 -2
- package/dist/collections/index.d.ts.map +1 -0
- package/dist/collections/index.js +37 -2
- package/dist/collections/index.js.map +1 -0
- package/dist/collections/json/loader-webpack.d.ts +3 -3
- package/dist/collections/json/loader-webpack.d.ts.map +1 -1
- package/dist/collections/json/loader-webpack.js +3 -7
- package/dist/collections/json/loader-webpack.js.map +1 -1
- package/dist/collections/mdx/loader-webpack.d.ts +3 -3
- package/dist/collections/mdx/loader-webpack.d.ts.map +1 -1
- package/dist/collections/mdx/loader-webpack.js +3 -8
- package/dist/collections/mdx/loader-webpack.js.map +1 -1
- package/dist/collections/mdx/react.d.ts +3 -10
- package/dist/collections/mdx/react.d.ts.map +1 -1
- package/dist/collections/mdx/react.js +2 -1
- package/dist/collections/mdx/react.js.map +1 -1
- package/dist/collections/mdx/runtime-browser.d.ts +25 -11
- package/dist/collections/mdx/runtime-browser.d.ts.map +1 -0
- package/dist/collections/mdx/runtime-browser.js +2 -2
- package/dist/collections/mdx/runtime-browser.js.map +1 -1
- package/dist/collections/mdx/runtime-dynamic.d.ts +6 -10
- package/dist/collections/mdx/runtime-dynamic.d.ts.map +1 -1
- package/dist/collections/mdx/runtime-dynamic.js +15 -13
- package/dist/collections/mdx/runtime-dynamic.js.map +1 -1
- package/dist/collections/mdx/runtime.d.ts +26 -10
- package/dist/collections/mdx/runtime.d.ts.map +1 -0
- package/dist/collections/mdx/runtime.js.map +1 -1
- package/dist/collections/mdx.d.ts +66 -6
- package/dist/collections/mdx.d.ts.map +1 -0
- package/dist/collections/mdx.js +316 -6
- package/dist/collections/mdx.js.map +1 -0
- package/dist/collections/obsidian.d.ts +10 -0
- package/dist/collections/obsidian.d.ts.map +1 -0
- package/dist/collections/obsidian.js +497 -0
- package/dist/collections/obsidian.js.map +1 -0
- package/dist/collections/runtime/file-store.d.ts +21 -4
- package/dist/collections/runtime/file-store.d.ts.map +1 -0
- package/dist/collections/runtime/file-store.js +1 -1
- package/dist/collections/runtime/store.d.ts +31 -3
- package/dist/collections/runtime/store.d.ts.map +1 -0
- package/dist/collections/runtime/store.js +33 -2
- package/dist/collections/runtime/store.js.map +1 -0
- package/dist/collections/yaml/loader-webpack.d.ts +3 -3
- package/dist/collections/yaml/loader-webpack.d.ts.map +1 -1
- package/dist/collections/yaml/loader-webpack.js +3 -7
- package/dist/collections/yaml/loader-webpack.js.map +1 -1
- package/dist/config/index.d.ts +35 -2
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js.map +1 -1
- package/dist/{core-Uv3jZqL-.js → core-BuUsOElL.js} +9 -9
- package/dist/core-BuUsOElL.js.map +1 -0
- package/dist/{core-CT06v32N.d.ts → core-FjA_Xoho.d.ts} +4 -67
- package/dist/core-FjA_Xoho.d.ts.map +1 -0
- package/dist/dynamic.d.ts +25 -3
- package/dist/dynamic.d.ts.map +1 -0
- package/dist/dynamic.js +28 -2
- package/dist/dynamic.js.map +1 -0
- package/dist/{fuma-matter-BuBO2w-p.js → fuma-matter-B4gT09gM.js} +1 -1
- package/dist/fuma-matter-B4gT09gM.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/is-promise-like-DYHv0Yap.js +8 -0
- package/dist/is-promise-like-DYHv0Yap.js.map +1 -0
- package/dist/{load-from-file-z7EGuf2n.js → load-from-file-BhdBOcQT.js} +4 -2
- package/dist/{load-from-file-z7EGuf2n.js.map → load-from-file-BhdBOcQT.js.map} +1 -1
- package/dist/load-from-file-CIYdu-B5.d.ts +10 -0
- package/dist/load-from-file-CIYdu-B5.d.ts.map +1 -0
- package/dist/loader-BOYLUNfh.js +18 -0
- package/dist/{loader-BK8PnqRg.js.map → loader-BOYLUNfh.js.map} +1 -1
- package/dist/{loader-CnksfM7I.js → loader-BT4fwLTJ.js} +13 -7
- package/dist/loader-BT4fwLTJ.js.map +1 -0
- package/dist/loader-Cb9kSSxT.js +19 -0
- package/dist/{loader-Cnz-VHne.js.map → loader-Cb9kSSxT.js.map} +1 -1
- package/dist/{loader-CuntMmR4.js → loader-UhlX4xbz.js} +3 -3
- package/dist/loader-UhlX4xbz.js.map +1 -0
- package/dist/next/index.d.ts +1 -1
- package/dist/next/index.d.ts.map +1 -1
- package/dist/next/index.js +3 -3
- package/dist/next/index.js.map +1 -1
- package/dist/node/index.d.ts +1 -1
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/loader.d.ts +1 -1
- package/dist/node/loader.d.ts.map +1 -1
- package/dist/node/loader.js +8 -8
- package/dist/node/loader.js.map +1 -1
- package/dist/{node-2VZOh3P9.js → node-Cu5Pqxxo.js} +2 -2
- package/dist/node-Cu5Pqxxo.js.map +1 -0
- package/dist/{collections-CNWuMDAZ.js → pipe-CvCqOpXX.js} +2 -36
- package/dist/pipe-CvCqOpXX.js.map +1 -0
- package/dist/plugins/git.d.ts +38 -3
- package/dist/plugins/git.d.ts.map +1 -0
- package/dist/plugins/git.js +60 -2
- package/dist/plugins/git.js.map +1 -0
- package/dist/plugins/json-schema.d.ts +2 -1
- package/dist/plugins/json-schema.d.ts.map +1 -1
- package/dist/plugins/json-schema.js +2 -2
- package/dist/plugins/json-schema.js.map +1 -1
- package/dist/plugins/loader/index.d.ts +72 -4
- package/dist/plugins/loader/index.d.ts.map +1 -0
- package/dist/plugins/loader/index.js +77 -2
- package/dist/plugins/loader/index.js.map +1 -0
- package/dist/plugins/loader/webpack.d.ts +21 -4
- package/dist/plugins/loader/webpack.d.ts.map +1 -0
- package/dist/plugins/loader/webpack.js +7 -5
- package/dist/plugins/loader/webpack.js.map +1 -1
- package/dist/rolldown-runtime-CjeV3_4I.js +18 -0
- package/dist/{validation-BvVvvLII.js → validation-C3kXuveD.js} +1 -1
- package/dist/{validation-BvVvvLII.js.map → validation-C3kXuveD.js.map} +1 -1
- package/dist/vite/index.d.ts +1 -1
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +4 -15
- package/dist/vite/index.js.map +1 -1
- package/dist/{vite-C1qXY47G.js → vite-CoJIMNWk.js} +4 -4
- package/dist/vite-CoJIMNWk.js.map +1 -0
- package/package.json +27 -11
- package/dist/build-mdx-CUp6FpfT.js.map +0 -1
- package/dist/build-mdx-D6zM3Sgl.js +0 -4
- package/dist/bun-CBROq3I0.js.map +0 -1
- package/dist/code-generator-Qhhq7kHh.js.map +0 -1
- package/dist/collections-CNWuMDAZ.js.map +0 -1
- package/dist/core-CT06v32N.d.ts.map +0 -1
- package/dist/core-Uv3jZqL-.js.map +0 -1
- package/dist/data-Cxsx5KPD.js +0 -159
- package/dist/data-Cxsx5KPD.js.map +0 -1
- package/dist/dynamic-Ck1wYoaL.d.ts +0 -33
- package/dist/dynamic-Ck1wYoaL.d.ts.map +0 -1
- package/dist/dynamic-CtOB4Rkp.js +0 -29
- package/dist/dynamic-CtOB4Rkp.js.map +0 -1
- package/dist/file-store-Dm1SjuLg.d.ts +0 -20
- package/dist/file-store-Dm1SjuLg.d.ts.map +0 -1
- package/dist/fs-CXzVd2Dp.js +0 -68
- package/dist/fs-CXzVd2Dp.js.map +0 -1
- package/dist/fs-CmwaaFyx.d.ts +0 -45
- package/dist/fs-CmwaaFyx.d.ts.map +0 -1
- package/dist/fuma-matter-BuBO2w-p.js.map +0 -1
- package/dist/git-DnejL9r_.js +0 -60
- package/dist/git-DnejL9r_.js.map +0 -1
- package/dist/git-n-9ddn78.d.ts +0 -37
- package/dist/git-n-9ddn78.d.ts.map +0 -1
- package/dist/index-BheUVWBm.d.ts +0 -87
- package/dist/index-BheUVWBm.d.ts.map +0 -1
- package/dist/load-from-file-D-Xm95Fz.js +0 -3
- package/dist/loader-B4nQrRwA.js +0 -77
- package/dist/loader-B4nQrRwA.js.map +0 -1
- package/dist/loader-B6ordrWK.js +0 -9
- package/dist/loader-BK8PnqRg.js +0 -16
- package/dist/loader-CnksfM7I.js.map +0 -1
- package/dist/loader-Cnz-VHne.js +0 -17
- package/dist/loader-CuntMmR4.js.map +0 -1
- package/dist/loader-Cx1Rg_VM.js +0 -8
- package/dist/loader-Dao_nv3e.js +0 -8
- package/dist/mdx-Cw1nBJ0D.js +0 -306
- package/dist/mdx-Cw1nBJ0D.js.map +0 -1
- package/dist/mdx-PaqRNZMS.d.ts +0 -135
- package/dist/mdx-PaqRNZMS.d.ts.map +0 -1
- package/dist/node-2VZOh3P9.js.map +0 -1
- package/dist/runtime-BUUHSFlR.d.ts +0 -31
- package/dist/runtime-BUUHSFlR.d.ts.map +0 -1
- package/dist/runtime-browser-B70WGxeQ.d.ts +0 -29
- package/dist/runtime-browser-B70WGxeQ.d.ts.map +0 -1
- package/dist/store-CRyvZFKN.js +0 -34
- package/dist/store-CRyvZFKN.js.map +0 -1
- package/dist/store-D_PPrdRE.d.ts +0 -31
- package/dist/store-D_PPrdRE.d.ts.map +0 -1
- package/dist/vite-C1qXY47G.js.map +0 -1
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
import { n as slash } from "../code-generator-CHcOrCeM.js";
|
|
2
|
+
import "../validation-C3kXuveD.js";
|
|
3
|
+
import { MDXCollection, mdxCollection } from "./mdx.js";
|
|
4
|
+
import { t as fumaMatter } from "../fuma-matter-B4gT09gM.js";
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { slug } from "github-slugger";
|
|
9
|
+
import { visit } from "unist-util-visit";
|
|
10
|
+
|
|
11
|
+
//#region src/collections/obsidian/schema.ts
|
|
12
|
+
const frontmatterSchema = z.object({ aliases: z.array(z.string()).optional() }).loose().optional();
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/collections/obsidian/build-storage.ts
|
|
16
|
+
/**
|
|
17
|
+
* Build virtual storage containing all files in the vault
|
|
18
|
+
*/
|
|
19
|
+
async function buildStorage(options) {
|
|
20
|
+
const { files, dir, url = (file) => {
|
|
21
|
+
return `/${normalize(file).split("/").filter((v) => v.length > 0).join("/")}`;
|
|
22
|
+
}, outputPath: outputPathOption = "simple", enforceMdx = true } = options;
|
|
23
|
+
const getOutputPath = typeof outputPathOption === "function" ? outputPathOption : createRenameOutput(outputPathOption);
|
|
24
|
+
const storage = /* @__PURE__ */ new Map();
|
|
25
|
+
for (const file of files) {
|
|
26
|
+
const normalizedPath = normalize(path.relative(dir, file));
|
|
27
|
+
const raw = {
|
|
28
|
+
_raw: { path: file },
|
|
29
|
+
path: normalizedPath,
|
|
30
|
+
async read() {
|
|
31
|
+
return (await readFile(file)).toString();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
let outPath = getOutputPath(normalizedPath, raw);
|
|
35
|
+
let parsed;
|
|
36
|
+
switch (path.extname(normalizedPath)) {
|
|
37
|
+
case ".json":
|
|
38
|
+
case ".yaml":
|
|
39
|
+
case ".yml":
|
|
40
|
+
case ".toml":
|
|
41
|
+
parsed = {
|
|
42
|
+
format: "data",
|
|
43
|
+
outPath,
|
|
44
|
+
...raw
|
|
45
|
+
};
|
|
46
|
+
break;
|
|
47
|
+
case ".md":
|
|
48
|
+
case ".mdx": {
|
|
49
|
+
const rawContent = await raw.read();
|
|
50
|
+
const { data, content } = fumaMatter(rawContent);
|
|
51
|
+
if (enforceMdx) outPath = outPath.slice(0, -path.extname(outPath).length) + ".mdx";
|
|
52
|
+
parsed = {
|
|
53
|
+
format: "content",
|
|
54
|
+
outPath,
|
|
55
|
+
frontmatter: frontmatterSchema.parse(data),
|
|
56
|
+
content,
|
|
57
|
+
...raw,
|
|
58
|
+
read() {
|
|
59
|
+
return rawContent;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
default: parsed = {
|
|
65
|
+
format: "media",
|
|
66
|
+
url: url(outPath, raw),
|
|
67
|
+
outPath,
|
|
68
|
+
...raw
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
storage.set(normalizedPath, parsed);
|
|
72
|
+
}
|
|
73
|
+
return { files: storage };
|
|
74
|
+
}
|
|
75
|
+
function createRenameOutput(preset) {
|
|
76
|
+
if (preset === "ignore") return (file) => file;
|
|
77
|
+
const occurrences = /* @__PURE__ */ new Map();
|
|
78
|
+
return (file) => {
|
|
79
|
+
const ext = path.extname(file);
|
|
80
|
+
const segs = file.slice(0, -ext.length).split("/");
|
|
81
|
+
for (let i = 0; i < segs.length; i++) segs[i] = slug(segs[i]);
|
|
82
|
+
let out = segs.join("/");
|
|
83
|
+
const o = occurrences.get(out) ?? 0;
|
|
84
|
+
occurrences.set(out, o + 1);
|
|
85
|
+
if (o > 0) out += `-${o}`;
|
|
86
|
+
return out + ext;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function normalize(filePath) {
|
|
90
|
+
filePath = slash(filePath);
|
|
91
|
+
if (filePath.startsWith("../")) throw new Error(`${filePath} points outside of vault folder`);
|
|
92
|
+
return filePath.startsWith("./") ? filePath.slice(2) : filePath;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/collections/obsidian/build-resolver.ts
|
|
97
|
+
function buildResolver(storage) {
|
|
98
|
+
const pathToFile = /* @__PURE__ */ new Map();
|
|
99
|
+
const nameToFile = /* @__PURE__ */ new Map();
|
|
100
|
+
for (const file of storage.files.values()) {
|
|
101
|
+
const parsed = path.parse(file.path);
|
|
102
|
+
nameToFile.set(parsed.name, file);
|
|
103
|
+
pathToFile.set(slash(path.join(parsed.dir, parsed.name)), file);
|
|
104
|
+
nameToFile.set(parsed.base, file);
|
|
105
|
+
pathToFile.set(file.path, file);
|
|
106
|
+
if (file.format === "content" && file.frontmatter?.aliases) for (const alias of file.frontmatter.aliases) nameToFile.set(alias, file);
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
resolveName(vaultName) {
|
|
110
|
+
return nameToFile.get(vaultName);
|
|
111
|
+
},
|
|
112
|
+
resolvePath(vaultPath) {
|
|
113
|
+
return pathToFile.get(vaultPath);
|
|
114
|
+
},
|
|
115
|
+
resolveAny(name, fromPath) {
|
|
116
|
+
const dir = path.dirname(fromPath);
|
|
117
|
+
if (name.startsWith("./") || name.startsWith("../")) return this.resolvePath(slash(path.join(dir, name)));
|
|
118
|
+
return this.resolvePath(name) ?? this.resolveName(name);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function resolveInternalHref(href, sourceFile, resolver) {
|
|
123
|
+
const [name, hash] = href.split("#", 2);
|
|
124
|
+
return [resolver.resolveAny(name, sourceFile.path), hash];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/utils/mdast/replace.ts
|
|
129
|
+
function replace(node, withObj) {
|
|
130
|
+
for (const k in node) delete node[k];
|
|
131
|
+
Object.assign(node, withObj);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/collections/obsidian/remark-block-id.ts
|
|
136
|
+
const Regex = /(?<!\\)\^(?<block_id>\w+)$/m;
|
|
137
|
+
function transformBlocks(tree) {
|
|
138
|
+
visit(tree, "paragraph", (node) => {
|
|
139
|
+
let id;
|
|
140
|
+
visit(node, [
|
|
141
|
+
"link",
|
|
142
|
+
"text",
|
|
143
|
+
"mdxJsxFlowElement"
|
|
144
|
+
], (textNode) => {
|
|
145
|
+
if (textNode.type !== "text") return "skip";
|
|
146
|
+
const value = textNode.value;
|
|
147
|
+
const match = Regex.exec(value);
|
|
148
|
+
if (!match) return false;
|
|
149
|
+
id = match[1];
|
|
150
|
+
textNode.value = value.slice(0, match.index).trimEnd() + value.slice(match.index + match[0].length);
|
|
151
|
+
return false;
|
|
152
|
+
}, true);
|
|
153
|
+
if (id) replace(node, {
|
|
154
|
+
type: "mdxJsxFlowElement",
|
|
155
|
+
name: "section",
|
|
156
|
+
attributes: [{
|
|
157
|
+
type: "mdxJsxAttribute",
|
|
158
|
+
name: "id",
|
|
159
|
+
value: `^${id}`
|
|
160
|
+
}],
|
|
161
|
+
children: [{ ...node }]
|
|
162
|
+
});
|
|
163
|
+
return "skip";
|
|
164
|
+
});
|
|
165
|
+
return tree;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/utils/mdast/separate.ts
|
|
170
|
+
function separate(splitter, nodes) {
|
|
171
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
172
|
+
const node = nodes[i];
|
|
173
|
+
if (node.type !== "text" && "children" in node) {
|
|
174
|
+
const result = separate(splitter, node.children);
|
|
175
|
+
if (!result) continue;
|
|
176
|
+
const before = nodes.slice(0, i);
|
|
177
|
+
before.push({
|
|
178
|
+
...node,
|
|
179
|
+
children: result[0]
|
|
180
|
+
});
|
|
181
|
+
const after = nodes.slice(i + 1);
|
|
182
|
+
after.unshift({
|
|
183
|
+
...node,
|
|
184
|
+
children: result[1]
|
|
185
|
+
});
|
|
186
|
+
return [before, after];
|
|
187
|
+
}
|
|
188
|
+
if (node.type === "text") {
|
|
189
|
+
const [left, right] = node.value.split(splitter, 2);
|
|
190
|
+
if (right === void 0) continue;
|
|
191
|
+
const before = nodes.slice(0, i);
|
|
192
|
+
before.push({
|
|
193
|
+
type: "text",
|
|
194
|
+
value: left
|
|
195
|
+
});
|
|
196
|
+
const after = nodes.slice(i + 1);
|
|
197
|
+
if (right.length > 0) after.unshift({
|
|
198
|
+
type: "text",
|
|
199
|
+
value: right
|
|
200
|
+
});
|
|
201
|
+
return [before, after];
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/utils/mdast/create.ts
|
|
208
|
+
function createCallout(type, title, children) {
|
|
209
|
+
return {
|
|
210
|
+
type: "mdxJsxFlowElement",
|
|
211
|
+
attributes: [{
|
|
212
|
+
type: "mdxJsxAttribute",
|
|
213
|
+
name: "type",
|
|
214
|
+
value: type
|
|
215
|
+
}],
|
|
216
|
+
name: "ObsidianCallout",
|
|
217
|
+
children: [{
|
|
218
|
+
type: "mdxJsxFlowElement",
|
|
219
|
+
name: "ObsidianCalloutTitle",
|
|
220
|
+
attributes: [],
|
|
221
|
+
children: title
|
|
222
|
+
}, {
|
|
223
|
+
type: "mdxJsxFlowElement",
|
|
224
|
+
name: "ObsidianCalloutBody",
|
|
225
|
+
attributes: [],
|
|
226
|
+
children
|
|
227
|
+
}]
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
//#endregion
|
|
232
|
+
//#region src/collections/obsidian/get-refs.ts
|
|
233
|
+
function getFileHref(ref, sourceFile, heading) {
|
|
234
|
+
if (ref.format === "media" && ref.url) return ref.url;
|
|
235
|
+
const dir = path.dirname(sourceFile.outPath);
|
|
236
|
+
let url = slash(path.relative(dir, ref.outPath));
|
|
237
|
+
if (!url.startsWith("../")) url = `./${url}`;
|
|
238
|
+
if (heading) url += `#${getHeadingHash(heading)}`;
|
|
239
|
+
return url;
|
|
240
|
+
}
|
|
241
|
+
function getHeadingHash(heading) {
|
|
242
|
+
return heading.startsWith("^") ? heading : slug(heading);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
//#endregion
|
|
246
|
+
//#region src/collections/obsidian/remark-convert.ts
|
|
247
|
+
const RegexCalloutHead = /^\[!(?<type>\w+)](?<collapsible>\+)?/;
|
|
248
|
+
function resolveCallout(node) {
|
|
249
|
+
const head = node.children[0];
|
|
250
|
+
if (!head || head.type !== "paragraph") return;
|
|
251
|
+
const textNode = head.children[0];
|
|
252
|
+
if (!textNode || textNode.type !== "text") return;
|
|
253
|
+
const match = RegexCalloutHead.exec(textNode.value);
|
|
254
|
+
if (!match) return;
|
|
255
|
+
textNode.value = textNode.value.slice(match[0].length).trimStart();
|
|
256
|
+
const [title, rest] = separate(/\r?\n/, head.children) ?? [head.children];
|
|
257
|
+
const body = node.children.slice(1);
|
|
258
|
+
if (rest) body.unshift({
|
|
259
|
+
type: "paragraph",
|
|
260
|
+
children: rest
|
|
261
|
+
});
|
|
262
|
+
return createCallout(match[1], [{
|
|
263
|
+
type: "paragraph",
|
|
264
|
+
children: title
|
|
265
|
+
}], body);
|
|
266
|
+
}
|
|
267
|
+
function transform(tree, sourceFile, resolver) {
|
|
268
|
+
visit(tree, [
|
|
269
|
+
"blockquote",
|
|
270
|
+
"link",
|
|
271
|
+
"image"
|
|
272
|
+
], (node) => {
|
|
273
|
+
if (node.type === "blockquote") {
|
|
274
|
+
const callout = resolveCallout(node);
|
|
275
|
+
if (callout) replace(node, callout);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
if (node.type === "link" || node.type === "image") {
|
|
279
|
+
if (node.type === "link" && node.data?.isWikiLink) return "skip";
|
|
280
|
+
const url = decodeURI(node.url);
|
|
281
|
+
if (node.type === "link" && url.startsWith("#")) node.url = `#${getHeadingHash(url.slice(1))}`;
|
|
282
|
+
else {
|
|
283
|
+
const [ref, heading] = resolveInternalHref(url, sourceFile, resolver);
|
|
284
|
+
if (!ref) return "skip";
|
|
285
|
+
node.url = getFileHref(ref, sourceFile, heading);
|
|
286
|
+
}
|
|
287
|
+
return "skip";
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
return tree;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
//#endregion
|
|
294
|
+
//#region src/collections/obsidian/remark-obsidian-comment.ts
|
|
295
|
+
const RegexDelimiter = /(?<!\\)%%/;
|
|
296
|
+
function removeComment(tree) {
|
|
297
|
+
function remove(nodes) {
|
|
298
|
+
const start = separate(RegexDelimiter, nodes);
|
|
299
|
+
if (!start) return nodes;
|
|
300
|
+
const [before, rest] = start;
|
|
301
|
+
const end = separate(RegexDelimiter, rest);
|
|
302
|
+
if (!end) return nodes;
|
|
303
|
+
return [...before, ...remove(end[1])];
|
|
304
|
+
}
|
|
305
|
+
tree.children = remove(tree.children);
|
|
306
|
+
return tree;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
//#endregion
|
|
310
|
+
//#region src/collections/obsidian/remark-wikilinks.ts
|
|
311
|
+
const RegexWikilink = /!?\[\[(?<content>([^\]]|\\])+)]]/g;
|
|
312
|
+
const RegexContent = /^(?<name>(?:\\#|\\\||[^#|])*)(?:#(?<heading>(?:\\\||[^|])+))?(?:\|(?<alias>.+))?$/;
|
|
313
|
+
function transformWikilinks(tree, sourceFile, resolver) {
|
|
314
|
+
visit(tree, "paragraph", (node, index, parent) => {
|
|
315
|
+
if (typeof index !== "number" || !parent) return;
|
|
316
|
+
const replaceParagraph = [node];
|
|
317
|
+
let parents = [];
|
|
318
|
+
function traverse(cur) {
|
|
319
|
+
if (cur.type === "text") {
|
|
320
|
+
const output = resolveParagraphText(cur.value, sourceFile, resolver);
|
|
321
|
+
const idx = parents[0].children.indexOf(cur);
|
|
322
|
+
let insertIdx = idx;
|
|
323
|
+
parents[0].children.splice(insertIdx, 1);
|
|
324
|
+
for (const item of output) if (item.inParagraph) {
|
|
325
|
+
parents[0].children.splice(insertIdx, 0, ...item.children);
|
|
326
|
+
insertIdx += item.children.length;
|
|
327
|
+
} else {
|
|
328
|
+
replaceParagraph.push(...item.children);
|
|
329
|
+
parents = structuredClone(parents);
|
|
330
|
+
parents[0].children.splice(idx, insertIdx - idx);
|
|
331
|
+
insertIdx = idx;
|
|
332
|
+
replaceParagraph.push(parents.at(-1));
|
|
333
|
+
}
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
if ("children" in cur && Array.isArray(cur.children)) {
|
|
337
|
+
parents.unshift(cur);
|
|
338
|
+
for (const child of cur.children) traverse(child);
|
|
339
|
+
parents.shift();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
traverse(node);
|
|
343
|
+
parent.children.splice(index, 1, ...replaceParagraph);
|
|
344
|
+
});
|
|
345
|
+
return tree;
|
|
346
|
+
}
|
|
347
|
+
function resolveParagraphText(text, sourceFile, resolver) {
|
|
348
|
+
const output = [];
|
|
349
|
+
let concat = [];
|
|
350
|
+
let lastIndex = 0;
|
|
351
|
+
let result;
|
|
352
|
+
function flush() {
|
|
353
|
+
if (concat.length === 0) return;
|
|
354
|
+
output.push({
|
|
355
|
+
inParagraph: true,
|
|
356
|
+
children: concat
|
|
357
|
+
});
|
|
358
|
+
concat = [];
|
|
359
|
+
}
|
|
360
|
+
while (result = RegexWikilink.exec(text)) {
|
|
361
|
+
const resolved = resolveWikilink(result[0].startsWith("!"), result[1], sourceFile, resolver);
|
|
362
|
+
if (!resolved) continue;
|
|
363
|
+
if (lastIndex < result.index) concat.push({
|
|
364
|
+
type: "text",
|
|
365
|
+
value: text.substring(lastIndex, result.index)
|
|
366
|
+
});
|
|
367
|
+
if (resolved.type === "mdxJsxFlowElement") {
|
|
368
|
+
flush();
|
|
369
|
+
output.push({
|
|
370
|
+
inParagraph: false,
|
|
371
|
+
children: [resolved]
|
|
372
|
+
});
|
|
373
|
+
} else concat.push(resolved);
|
|
374
|
+
lastIndex = result.index + result[0].length;
|
|
375
|
+
}
|
|
376
|
+
if (lastIndex < text.length) concat.push({
|
|
377
|
+
type: "text",
|
|
378
|
+
value: text.substring(lastIndex)
|
|
379
|
+
});
|
|
380
|
+
flush();
|
|
381
|
+
return output;
|
|
382
|
+
}
|
|
383
|
+
function resolveWikilink(isEmbed, content, sourceFile, resolver) {
|
|
384
|
+
const match = RegexContent.exec(content);
|
|
385
|
+
if (!match?.groups) return;
|
|
386
|
+
const { name, heading, alias } = match.groups;
|
|
387
|
+
const isHeadingOnly = name.length === 0 && heading;
|
|
388
|
+
if (isEmbed) {
|
|
389
|
+
const ref = isHeadingOnly ? sourceFile : resolver.resolveAny(name, sourceFile.path);
|
|
390
|
+
if (!ref || ref.format === "data") {
|
|
391
|
+
console.warn(`failed to resolve ${name} wikilink`);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
if (ref.format === "content") {
|
|
395
|
+
console.warn("some features of embed content blocks are not supported yet, use at your own risk.");
|
|
396
|
+
return {
|
|
397
|
+
type: "mdxJsxFlowElement",
|
|
398
|
+
name: "include",
|
|
399
|
+
attributes: [],
|
|
400
|
+
children: [{
|
|
401
|
+
type: "paragraph",
|
|
402
|
+
children: [{
|
|
403
|
+
type: "text",
|
|
404
|
+
value: getFileHref(ref, sourceFile, heading)
|
|
405
|
+
}]
|
|
406
|
+
}]
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
if (alias) console.warn("we do not support specifying image size like `![[image.png|300]].");
|
|
410
|
+
return {
|
|
411
|
+
type: "image",
|
|
412
|
+
url: ref.url ?? getFileHref(ref, sourceFile, heading),
|
|
413
|
+
alt: name
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
let url;
|
|
417
|
+
if (isHeadingOnly) url = `#${getHeadingHash(heading)}`;
|
|
418
|
+
else {
|
|
419
|
+
const ref = resolver.resolveAny(name, sourceFile.path);
|
|
420
|
+
if (!ref) {
|
|
421
|
+
console.warn(`failed to resolve ${name} wikilink`);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
url = getFileHref(ref, sourceFile, heading);
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
type: "link",
|
|
428
|
+
url,
|
|
429
|
+
data: { isWikiLink: true },
|
|
430
|
+
children: [{
|
|
431
|
+
type: "text",
|
|
432
|
+
value: alias ?? content
|
|
433
|
+
}]
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
//#endregion
|
|
438
|
+
//#region src/collections/obsidian/remark-obsidian.ts
|
|
439
|
+
function remarkObsidian() {
|
|
440
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
441
|
+
return async (tree, file) => {
|
|
442
|
+
if (file.data._obsidian_transformed) return tree;
|
|
443
|
+
const compiler = file.data._compiler;
|
|
444
|
+
if (!compiler || !(compiler.collection instanceof MDXCollection)) return tree;
|
|
445
|
+
const collection = compiler.collection;
|
|
446
|
+
let cached = cache.get(collection);
|
|
447
|
+
if (!cached) {
|
|
448
|
+
const storage = await buildStorage({
|
|
449
|
+
files: (await collection.getFiles()).map((file) => path.join(collection.dir, file)),
|
|
450
|
+
dir: collection.dir,
|
|
451
|
+
url: () => void 0,
|
|
452
|
+
outputPath: "ignore",
|
|
453
|
+
enforceMdx: false
|
|
454
|
+
});
|
|
455
|
+
cached = {
|
|
456
|
+
resolver: buildResolver(storage),
|
|
457
|
+
storage
|
|
458
|
+
};
|
|
459
|
+
cache.set(collection, cached);
|
|
460
|
+
}
|
|
461
|
+
const { storage, resolver } = cached;
|
|
462
|
+
const normalizedPath = normalize(path.relative(collection.dir, file.path));
|
|
463
|
+
const vault = storage.files.get(normalizedPath);
|
|
464
|
+
if (vault?.format === "content") {
|
|
465
|
+
tree = transformWikilinks(tree, vault, resolver);
|
|
466
|
+
tree = transform(tree, vault, resolver);
|
|
467
|
+
tree = removeComment(tree);
|
|
468
|
+
tree = transformBlocks(tree);
|
|
469
|
+
file.data._obsidian_transformed = true;
|
|
470
|
+
return tree;
|
|
471
|
+
}
|
|
472
|
+
return tree;
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
//#endregion
|
|
477
|
+
//#region src/collections/obsidian.ts
|
|
478
|
+
function mdxObsidianCollection(config) {
|
|
479
|
+
return mdxCollection({
|
|
480
|
+
...config,
|
|
481
|
+
preprocess: {
|
|
482
|
+
...config.preprocess,
|
|
483
|
+
remarkPlugins: [remarkObsidian, ...config.preprocess?.remarkPlugins ?? []]
|
|
484
|
+
},
|
|
485
|
+
async options(environment) {
|
|
486
|
+
const base = await config.options?.(environment);
|
|
487
|
+
return {
|
|
488
|
+
...base,
|
|
489
|
+
remarkPlugins: [remarkObsidian, ...base?.remarkPlugins ?? []]
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
//#endregion
|
|
496
|
+
export { mdxObsidianCollection };
|
|
497
|
+
//# sourceMappingURL=obsidian.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obsidian.js","names":[],"sources":["../../src/collections/obsidian/schema.ts","../../src/collections/obsidian/build-storage.ts","../../src/collections/obsidian/build-resolver.ts","../../src/utils/mdast/replace.ts","../../src/collections/obsidian/remark-block-id.ts","../../src/utils/mdast/separate.ts","../../src/utils/mdast/create.ts","../../src/collections/obsidian/get-refs.ts","../../src/collections/obsidian/remark-convert.ts","../../src/collections/obsidian/remark-obsidian-comment.ts","../../src/collections/obsidian/remark-wikilinks.ts","../../src/collections/obsidian/remark-obsidian.ts","../../src/collections/obsidian.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const frontmatterSchema = z\n .object({\n aliases: z.array(z.string()).optional(),\n })\n .loose()\n .optional();\n\nexport type Frontmatter = z.input<typeof frontmatterSchema>;\n","import path from \"node:path\";\nimport { type Frontmatter, frontmatterSchema } from \"./schema\";\nimport { slug } from \"github-slugger\";\nimport { slash } from \"@/utils/code-generator\";\nimport { Awaitable } from \"@/types\";\nimport { readFile } from \"node:fs/promises\";\nimport { fumaMatter } from \"../mdx/fuma-matter\";\n\ntype RenameOutputFn = (originalOutputPath: string, file: VaultFile) => string;\ntype RenameOutputPreset = \"ignore\" | \"simple\";\n\nexport interface VaultStorageOptions {\n files: string[];\n /** vault directory */\n dir: string;\n /**\n * rename output path\n *\n * @defaultValue 'simple'\n */\n outputPath?: RenameOutputFn | RenameOutputPreset;\n\n /**\n * generate URL from media file, default to original file path (normalized)\n */\n url?: (outputPath: string, mediaFile: VaultFile) => string | undefined;\n\n /**\n * enforce all Markdown documents to be MDX\n *\n * @defaultValue true\n */\n enforceMdx?: boolean;\n}\n\n/**\n * a virtual storage containing all files in the vault\n */\nexport interface VaultStorage {\n files: Map<string, ParsedFile>;\n}\n\nexport interface VaultFile {\n /**\n * paths relative to vault folder\n */\n path: string;\n\n _raw: {\n /**\n * original path, either:\n * - relative to cwd\n * - absolute\n */\n path: string;\n };\n\n read: () => Awaitable<string>;\n}\n\nexport type ParsedFile = ParsedContentFile | ParsedMediaFile | ParsedDataFile;\n\nexport interface ParsedContentFile extends VaultFile {\n format: \"content\";\n frontmatter: Frontmatter;\n\n /**\n * output path (relative to content directory)\n */\n outPath: string;\n content: string;\n}\n\nexport interface ParsedMediaFile extends VaultFile {\n format: \"media\";\n\n /**\n * output path (relative to asset directory)\n */\n outPath: string;\n /**\n * The output URL. When undefined, it means the file is only accessible via paths.\n */\n url?: string;\n}\n\nexport interface ParsedDataFile extends VaultFile {\n format: \"data\";\n outPath: string;\n}\n\n/**\n * Build virtual storage containing all files in the vault\n */\nexport async function buildStorage(options: VaultStorageOptions): Promise<VaultStorage> {\n const {\n files,\n dir,\n url = (file) => {\n const segs = normalize(file)\n .split(\"/\")\n .filter((v) => v.length > 0);\n return `/${segs.join(\"/\")}`;\n },\n outputPath: outputPathOption = \"simple\",\n enforceMdx = true,\n } = options;\n const getOutputPath =\n typeof outputPathOption === \"function\"\n ? outputPathOption\n : createRenameOutput(outputPathOption);\n\n const storage = new Map<string, ParsedFile>();\n\n for (const file of files) {\n const normalizedPath = normalize(path.relative(dir, file));\n const raw: VaultFile = {\n _raw: { path: file },\n path: normalizedPath,\n async read() {\n const res = await readFile(file);\n return res.toString();\n },\n };\n let outPath = getOutputPath(normalizedPath, raw);\n let parsed: ParsedFile;\n\n switch (path.extname(normalizedPath)) {\n case \".json\":\n case \".yaml\":\n case \".yml\":\n case \".toml\":\n parsed = {\n format: \"data\",\n outPath,\n ...raw,\n };\n break;\n case \".md\":\n case \".mdx\": {\n const rawContent = await raw.read();\n const { data, content } = fumaMatter(rawContent);\n if (enforceMdx) {\n outPath = outPath.slice(0, -path.extname(outPath).length) + \".mdx\";\n }\n\n parsed = {\n format: \"content\",\n outPath,\n frontmatter: frontmatterSchema.parse(data),\n content,\n ...raw,\n read() {\n return rawContent;\n },\n };\n break;\n }\n default:\n parsed = {\n format: \"media\",\n url: url(outPath, raw),\n outPath,\n ...raw,\n };\n }\n\n storage.set(normalizedPath, parsed);\n }\n\n return { files: storage };\n}\n\nfunction createRenameOutput(preset: RenameOutputPreset): RenameOutputFn {\n if (preset === \"ignore\") return (file) => file;\n\n const occurrences = new Map<string, number>();\n return (file) => {\n const ext = path.extname(file);\n const segs = file.slice(0, -ext.length).split(\"/\");\n for (let i = 0; i < segs.length; i++) {\n // preserve separators\n segs[i] = slug(segs[i]);\n }\n // we only count occurrences by the full path\n let out = segs.join(\"/\");\n const o = occurrences.get(out) ?? 0;\n occurrences.set(out, o + 1);\n if (o > 0) out += `-${o}`;\n return out + ext;\n };\n}\n\nexport function normalize(filePath: string): string {\n filePath = slash(filePath);\n if (filePath.startsWith(\"../\")) throw new Error(`${filePath} points outside of vault folder`);\n\n return filePath.startsWith(\"./\") ? filePath.slice(2) : filePath;\n}\n","import { slash } from \"@/utils/code-generator\";\nimport type { ParsedFile, VaultStorage } from \"./build-storage\";\nimport path from \"node:path\";\n\nexport interface VaultResolver {\n /**\n * resolve file by vault name\n */\n resolveName: (vaultName: string) => ParsedFile | undefined;\n\n /**\n * resolve file by vault path (from root directory)\n */\n resolvePath: (vaultPath: string) => ParsedFile | undefined;\n\n /**\n * resolve file by:\n * 1. relative vault path\n * 2. full vault path\n * 3. vault name/alias\n *\n * @param name - target\n * @param fromPath - the path of referencer vault file\n */\n resolveAny: (name: string, fromPath: string) => ParsedFile | undefined;\n}\n\nexport function buildResolver(storage: VaultStorage): VaultResolver {\n // a file should create two item in this map, one with extension, and one without.\n const pathToFile = new Map<string, ParsedFile>();\n // a file should create two item in this map, one with extension, and one without.\n const nameToFile = new Map<string, ParsedFile>();\n\n for (const file of storage.files.values()) {\n const parsed = path.parse(file.path);\n\n nameToFile.set(parsed.name, file);\n pathToFile.set(slash(path.join(parsed.dir, parsed.name)), file);\n\n nameToFile.set(parsed.base, file);\n pathToFile.set(file.path, file);\n\n // support aliases specified in frontmatter\n if (file.format === \"content\" && file.frontmatter?.aliases) {\n for (const alias of file.frontmatter.aliases) {\n nameToFile.set(alias, file);\n }\n }\n }\n\n return {\n resolveName(vaultName: string) {\n return nameToFile.get(vaultName);\n },\n resolvePath(vaultPath: string) {\n return pathToFile.get(vaultPath);\n },\n resolveAny(name, fromPath) {\n const dir = path.dirname(fromPath);\n\n if (name.startsWith(\"./\") || name.startsWith(\"../\")) {\n return this.resolvePath(slash(path.join(dir, name)));\n }\n\n // absolute path or name\n return this.resolvePath(name) ?? this.resolveName(name);\n },\n };\n}\n\nexport function resolveInternalHref(\n href: string,\n sourceFile: ParsedFile,\n resolver: VaultResolver,\n): [ParsedFile | undefined, hash: string | undefined] {\n const [name, hash] = href.split(\"#\", 2);\n return [resolver.resolveAny(name, sourceFile.path), hash];\n}\n","export function replace(node: object, withObj: object) {\n for (const k in node) {\n delete node[k as keyof object];\n }\n\n Object.assign(node, withObj);\n}\n","import { visit } from \"unist-util-visit\";\nimport type { Root } from \"mdast\";\nimport { replace } from \"../../utils/mdast/replace\";\nimport type { MdxJsxFlowElement } from \"mdast-util-mdx-jsx\";\n\nconst Regex = /(?<!\\\\)\\^(?<block_id>\\w+)$/m;\n\nexport function transformBlocks(tree: Root) {\n visit(tree, \"paragraph\", (node) => {\n let id: string | undefined;\n\n visit(\n node,\n [\"link\", \"text\", \"mdxJsxFlowElement\"],\n (textNode) => {\n if (textNode.type !== \"text\") return \"skip\";\n\n const value = textNode.value;\n const match = Regex.exec(value);\n // if last text node isn't a block id, skip\n if (!match) return false;\n\n id = match[1];\n textNode.value =\n value.slice(0, match.index).trimEnd() + value.slice(match.index + match[0].length);\n return false;\n },\n true,\n );\n\n if (id) {\n replace(node, {\n type: \"mdxJsxFlowElement\",\n name: \"section\",\n attributes: [\n {\n type: \"mdxJsxAttribute\",\n name: \"id\",\n value: `^${id}`,\n },\n ],\n children: [\n {\n ...node,\n },\n ],\n } satisfies MdxJsxFlowElement);\n }\n\n return \"skip\";\n });\n\n return tree;\n}\n","import type { RootContent } from \"mdast\";\n\nexport function separate(\n splitter: RegExp | string,\n nodes: RootContent[],\n): [before: RootContent[], after: RootContent[]] | undefined {\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n\n if (node.type !== \"text\" && \"children\" in node) {\n const result = separate(splitter, node.children);\n if (!result) continue;\n\n const before = nodes.slice(0, i);\n before.push({\n ...node,\n children: result[0],\n } as RootContent);\n\n const after = nodes.slice(i + 1);\n after.unshift({\n ...node,\n children: result[1],\n } as RootContent);\n\n return [before, after];\n }\n\n if (node.type === \"text\") {\n const [left, right] = node.value.split(splitter, 2);\n if (right === undefined) continue;\n\n const before = nodes.slice(0, i);\n before.push({\n type: \"text\",\n value: left,\n });\n\n const after = nodes.slice(i + 1);\n if (right.length > 0) after.unshift({ type: \"text\", value: right });\n\n return [before, after];\n }\n }\n}\n","import type { BlockContent, DefinitionContent } from \"mdast\";\nimport type { MdxJsxFlowElement } from \"mdast-util-mdx-jsx\";\n\nexport function createCallout(\n type: string,\n title: (BlockContent | DefinitionContent)[],\n children: (BlockContent | DefinitionContent)[],\n): MdxJsxFlowElement {\n return {\n type: \"mdxJsxFlowElement\",\n attributes: [\n {\n type: \"mdxJsxAttribute\",\n name: \"type\",\n value: type,\n },\n ],\n name: \"ObsidianCallout\",\n children: [\n {\n type: \"mdxJsxFlowElement\",\n name: \"ObsidianCalloutTitle\",\n attributes: [],\n children: title,\n },\n {\n type: \"mdxJsxFlowElement\",\n name: \"ObsidianCalloutBody\",\n attributes: [],\n children,\n },\n ],\n };\n}\n","import type { ParsedFile } from \"./build-storage\";\nimport path from \"node:path\";\nimport { slug } from \"github-slugger\";\nimport { slash } from \"@/utils/code-generator\";\n\nexport function getFileHref(ref: ParsedFile, sourceFile: ParsedFile, heading?: string) {\n if (ref.format === \"media\" && ref.url) return ref.url;\n\n const dir = path.dirname(sourceFile.outPath);\n let url = slash(path.relative(dir, ref.outPath));\n if (!url.startsWith(\"../\")) url = `./${url}`;\n if (heading) url += `#${getHeadingHash(heading)}`;\n\n return url;\n}\n\nexport function getHeadingHash(heading: string) {\n // for refs to block Ids, ignore slugify\n return heading.startsWith(\"^\") ? heading : slug(heading);\n}\n","import type { Blockquote, PhrasingContent, Root } from \"mdast\";\nimport { visit } from \"unist-util-visit\";\nimport { separate } from \"../../utils/mdast/separate\";\nimport { createCallout } from \"../../utils/mdast/create\";\nimport { resolveInternalHref, VaultResolver } from \"./build-resolver\";\nimport { replace } from \"../../utils/mdast/replace\";\nimport { getFileHref, getHeadingHash } from \"./get-refs\";\nimport { ParsedContentFile } from \"./build-storage\";\n\nconst RegexCalloutHead = /^\\[!(?<type>\\w+)](?<collapsible>\\+)?/;\n\nexport interface RemarkConvertOptions {\n resolver: VaultResolver;\n}\n\nfunction resolveCallout(node: Blockquote) {\n const head = node.children[0];\n if (!head || head.type !== \"paragraph\") return;\n const textNode = head.children[0];\n if (!textNode || textNode.type !== \"text\") return;\n\n const match = RegexCalloutHead.exec(textNode.value);\n if (!match) return;\n\n textNode.value = textNode.value.slice(match[0].length).trimStart();\n\n const [title, rest] = separate(/\\r?\\n/, head.children) ?? [head.children];\n const body = node.children.slice(1);\n if (rest) {\n body.unshift({\n type: \"paragraph\",\n children: rest as PhrasingContent[],\n });\n }\n\n return createCallout(\n match[1],\n [\n {\n type: \"paragraph\",\n children: title as PhrasingContent[],\n },\n ],\n body,\n );\n}\n\nexport function transform(tree: Root, sourceFile: ParsedContentFile, resolver: VaultResolver) {\n visit(tree, [\"blockquote\", \"link\", \"image\"], (node) => {\n if (node.type === \"blockquote\") {\n const callout = resolveCallout(node);\n if (callout) replace(node, callout);\n\n return;\n }\n\n if (node.type === \"link\" || node.type === \"image\") {\n if (node.type === \"link\" && node.data?.isWikiLink) return \"skip\";\n\n const url = decodeURI(node.url);\n if (node.type === \"link\" && url.startsWith(\"#\")) {\n const heading = url.slice(1);\n node.url = `#${getHeadingHash(heading)}`;\n } else {\n const [ref, heading] = resolveInternalHref(url, sourceFile, resolver);\n if (!ref) return \"skip\";\n\n node.url = getFileHref(ref, sourceFile, heading);\n }\n\n return \"skip\";\n }\n });\n return tree;\n}\n","import type { Root, RootContent } from \"mdast\";\nimport { separate } from \"../../utils/mdast/separate\";\n\nconst RegexDelimiter = /(?<!\\\\)%%/;\n\nexport function removeComment(tree: Root) {\n function remove(nodes: RootContent[]): RootContent[] {\n const start = separate(RegexDelimiter, nodes);\n if (!start) return nodes;\n const [before, rest] = start;\n\n const end = separate(RegexDelimiter, rest);\n if (!end) return nodes;\n\n return [...before, ...remove(end[1])];\n }\n\n tree.children = remove(tree.children);\n return tree;\n}\n","import { visit } from \"unist-util-visit\";\nimport type { Paragraph, Parent, PhrasingContent, Root, RootContent } from \"mdast\";\nimport type { MdxJsxFlowElement } from \"mdast-util-mdx-jsx\";\nimport { getFileHref, getHeadingHash } from \"./get-refs\";\nimport { ParsedContentFile, ParsedFile } from \"./build-storage\";\nimport { VaultResolver } from \"./build-resolver\";\n\ndeclare module \"mdast\" {\n interface LinkData {\n isWikiLink?: boolean;\n }\n}\n\nconst RegexWikilink = /!?\\[\\[(?<content>([^\\]]|\\\\])+)]]/g;\nconst RegexContent =\n /^(?<name>(?:\\\\#|\\\\\\||[^#|])*)(?:#(?<heading>(?:\\\\\\||[^|])+))?(?:\\|(?<alias>.+))?$/;\n\nexport function transformWikilinks(\n tree: Root,\n sourceFile: ParsedContentFile,\n resolver: VaultResolver,\n) {\n visit(tree, \"paragraph\", (node, index, parent) => {\n if (typeof index !== \"number\" || !parent) return;\n\n const replaceParagraph: RootContent[] = [node];\n let parents: Parent[] = [];\n\n function traverse(cur: RootContent) {\n if (cur.type === \"text\") {\n const output = resolveParagraphText(cur.value, sourceFile, resolver);\n const idx = parents[0].children.indexOf(cur);\n let insertIdx = idx;\n\n parents[0].children.splice(insertIdx, 1);\n for (const item of output) {\n if (item.inParagraph) {\n parents[0].children.splice(insertIdx, 0, ...item.children);\n insertIdx += item.children.length;\n } else {\n replaceParagraph.push(...item.children);\n // clone parents\n parents = structuredClone(parents);\n // removed inserted elements\n parents[0].children.splice(idx, insertIdx - idx);\n insertIdx = idx;\n replaceParagraph.push(parents.at(-1) as Paragraph);\n }\n }\n\n return;\n }\n\n if (\"children\" in cur && Array.isArray(cur.children)) {\n parents.unshift(cur);\n for (const child of cur.children) {\n traverse(child);\n }\n parents.shift();\n }\n }\n\n traverse(node);\n parent.children.splice(index, 1, ...replaceParagraph);\n });\n return tree;\n}\n\ntype ResolveParagraphTextResult =\n | {\n inParagraph: true;\n children: PhrasingContent[];\n }\n | {\n inParagraph: false;\n children: RootContent[];\n };\n\nfunction resolveParagraphText(\n text: string,\n sourceFile: ParsedFile,\n resolver: VaultResolver,\n): ResolveParagraphTextResult[] {\n const output: ResolveParagraphTextResult[] = [];\n let concat: PhrasingContent[] = [];\n let lastIndex = 0;\n let result: RegExpExecArray | null;\n\n function flush() {\n if (concat.length === 0) return;\n\n output.push({\n inParagraph: true,\n children: concat,\n });\n concat = [];\n }\n\n while ((result = RegexWikilink.exec(text))) {\n const resolved = resolveWikilink(result[0].startsWith(\"!\"), result[1], sourceFile, resolver);\n if (!resolved) continue;\n if (lastIndex < result.index) {\n concat.push({\n type: \"text\",\n value: text.substring(lastIndex, result.index),\n });\n }\n\n // for blocks, separate paragraphs\n if (resolved.type === \"mdxJsxFlowElement\") {\n flush();\n output.push({\n inParagraph: false,\n children: [resolved],\n });\n } else {\n concat.push(resolved as PhrasingContent);\n }\n\n lastIndex = result.index + result[0].length;\n }\n\n if (lastIndex < text.length) {\n concat.push({\n type: \"text\",\n value: text.substring(lastIndex),\n });\n }\n\n flush();\n return output;\n}\n\nfunction resolveWikilink(\n isEmbed: boolean,\n content: string,\n sourceFile: ParsedFile,\n resolver: VaultResolver,\n): RootContent | undefined {\n const match = RegexContent.exec(content);\n if (!match?.groups) return;\n\n const { name, heading, alias } = match.groups as {\n name: string;\n heading?: string;\n alias?: string;\n };\n\n const isHeadingOnly = name.length === 0 && heading;\n\n if (isEmbed) {\n const ref = isHeadingOnly ? sourceFile : resolver.resolveAny(name, sourceFile.path);\n\n if (!ref || ref.format === \"data\") {\n console.warn(`failed to resolve ${name} wikilink`);\n return;\n }\n\n if (ref.format === \"content\") {\n console.warn(\n \"some features of embed content blocks are not supported yet, use at your own risk.\",\n );\n\n return {\n type: \"mdxJsxFlowElement\",\n name: \"include\",\n attributes: [],\n children: [\n {\n type: \"paragraph\",\n children: [\n {\n type: \"text\",\n value: getFileHref(ref, sourceFile, heading),\n },\n ],\n },\n ],\n } satisfies MdxJsxFlowElement;\n }\n\n if (alias) console.warn(\"we do not support specifying image size like `![[image.png|300]].\");\n\n return {\n type: \"image\",\n url: ref.url ?? getFileHref(ref, sourceFile, heading),\n alt: name,\n };\n }\n\n let url: string;\n\n if (isHeadingOnly) {\n url = `#${getHeadingHash(heading)}`;\n } else {\n const ref = resolver.resolveAny(name, sourceFile.path);\n\n if (!ref) {\n console.warn(`failed to resolve ${name} wikilink`);\n return;\n }\n\n url = getFileHref(ref, sourceFile, heading);\n }\n\n return {\n type: \"link\",\n url,\n data: {\n isWikiLink: true,\n },\n children: [\n {\n type: \"text\",\n value: alias ?? content,\n },\n ],\n };\n}\n","import type { Processor, Transformer } from \"unified\";\nimport type { Root } from \"mdast\";\nimport { buildStorage, normalize, VaultStorage } from \"./build-storage\";\nimport { buildResolver, VaultResolver } from \"./build-resolver\";\nimport path from \"node:path\";\nimport { transformBlocks } from \"./remark-block-id\";\nimport { transform } from \"./remark-convert\";\nimport { removeComment } from \"./remark-obsidian-comment\";\nimport { transformWikilinks } from \"./remark-wikilinks\";\nimport { MDXCollection } from \"../mdx\";\n\ndeclare module \"vfile\" {\n interface DataMap {\n _obsidian_transformed?: boolean;\n }\n}\n\nexport function remarkObsidian(this: Processor): Transformer<Root, Root> {\n const cache = new WeakMap<\n MDXCollection,\n {\n resolver: VaultResolver;\n storage: VaultStorage;\n }\n >();\n\n return async (tree, file) => {\n if (file.data._obsidian_transformed) return tree;\n const compiler = file.data._compiler;\n\n if (!compiler || !(compiler.collection instanceof MDXCollection)) return tree;\n const collection = compiler.collection;\n let cached = cache.get(collection);\n\n if (!cached) {\n const files = await collection.getFiles();\n const storage = await buildStorage({\n files: files.map((file) => path.join(collection.dir, file)),\n dir: collection.dir,\n url: () => undefined,\n outputPath: \"ignore\",\n enforceMdx: false,\n });\n const resolver = buildResolver(storage);\n\n cached = { resolver, storage };\n cache.set(collection, cached);\n }\n\n const { storage, resolver } = cached;\n const normalizedPath = normalize(path.relative(collection.dir, file.path));\n const vault = storage.files.get(normalizedPath);\n\n if (vault?.format === \"content\") {\n tree = transformWikilinks(tree, vault, resolver);\n tree = transform(tree, vault, resolver);\n tree = removeComment(tree);\n tree = transformBlocks(tree);\n file.data._obsidian_transformed = true;\n return tree;\n }\n\n return tree;\n };\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { mdxCollection, type MDXCollectionConfig } from \"./mdx\";\nimport { remarkObsidian } from \"./obsidian/remark-obsidian\";\n\nexport function mdxObsidianCollection<\n FrontmatterSchema extends StandardSchemaV1 | undefined = undefined,\n>(config: MDXCollectionConfig<FrontmatterSchema>) {\n return mdxCollection({\n ...config,\n preprocess: {\n ...config.preprocess,\n remarkPlugins: [remarkObsidian, ...(config.preprocess?.remarkPlugins ?? [])],\n },\n async options(environment) {\n const base = await config.options?.(environment);\n\n return {\n ...base,\n remarkPlugins: [remarkObsidian, ...(base?.remarkPlugins ?? [])],\n };\n },\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
import "../../core-
|
|
2
|
-
import "
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import "../../core-FjA_Xoho.js";
|
|
2
|
+
import { MapCollectionStore } from "./store.js";
|
|
3
|
+
|
|
4
|
+
//#region src/collections/runtime/file-store.d.ts
|
|
5
|
+
interface FileInfo {
|
|
6
|
+
/**
|
|
7
|
+
* path relative to content directory
|
|
8
|
+
*/
|
|
9
|
+
path: string;
|
|
10
|
+
/**
|
|
11
|
+
* the full file path in file system
|
|
12
|
+
*/
|
|
13
|
+
fullPath: string;
|
|
14
|
+
}
|
|
15
|
+
declare class FileCollectionStore<V> extends MapCollectionStore<string, FileInfo & V> {
|
|
16
|
+
constructor(base: string, glob: Record<string, V>);
|
|
17
|
+
castData<T>(_cast: (input: FileInfo & V) => FileInfo & T): FileCollectionStore<T>;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { FileCollectionStore, FileInfo };
|
|
21
|
+
//# sourceMappingURL=file-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-store.d.ts","names":[],"sources":["../../../src/collections/runtime/file-store.ts"],"mappings":";;;;UAGiB,QAAA;;;AAAjB;EAIE,IAAA;;;;EAKA,QAAA;AAAA;AAAA,cAWW,mBAAA,YAA+B,kBAAA,SAA2B,QAAA,GAAW,CAAA;cACpE,IAAA,UAAc,IAAA,EAAM,MAAA,SAAe,CAAA;EAa/C,QAAA,GAAA,CAAY,KAAA,GAAQ,KAAA,EAAO,QAAA,GAAW,CAAA,KAAM,QAAA,GAAW,CAAA,GAAI,mBAAA,CAAoB,CAAA;AAAA"}
|
|
@@ -1,3 +1,31 @@
|
|
|
1
|
-
import "../../core-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { S as Awaitable } from "../../core-FjA_Xoho.js";
|
|
2
|
+
|
|
3
|
+
//#region src/collections/runtime/store.d.ts
|
|
4
|
+
interface CollectionStore<Id, Data> {
|
|
5
|
+
/**
|
|
6
|
+
* type-only operation to cast data type, doesn't do any runtime transformation.
|
|
7
|
+
*/
|
|
8
|
+
castData: <T>(_cast: (input: Data) => T) => CollectionStore<Id, T>;
|
|
9
|
+
get: (id: Id) => Awaitable<Data | undefined>;
|
|
10
|
+
list: () => Awaitable<Data[]>;
|
|
11
|
+
/**
|
|
12
|
+
* For typescript to infer data types, don't access the value of this property.
|
|
13
|
+
*/
|
|
14
|
+
$inferData: Data;
|
|
15
|
+
}
|
|
16
|
+
declare class MapCollectionStore<Id, Data> implements CollectionStore<Id, Data> {
|
|
17
|
+
private readonly dataMap;
|
|
18
|
+
private readonly dataList;
|
|
19
|
+
constructor(input: Map<Id, Data>);
|
|
20
|
+
get(id: Id): Data | undefined;
|
|
21
|
+
list(): Data[];
|
|
22
|
+
castData<T>(_cast: (input: Data) => T): MapCollectionStore<Id, T>;
|
|
23
|
+
/**
|
|
24
|
+
* transform entry and create a new store
|
|
25
|
+
*/
|
|
26
|
+
transform<$Id, T>(fn: (id: Id, data: Data) => [$Id, T]): MapCollectionStore<$Id, T>;
|
|
27
|
+
get $inferData(): Data;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { CollectionStore, MapCollectionStore };
|
|
31
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","names":[],"sources":["../../../src/collections/runtime/store.ts"],"mappings":";;;UAEiB,eAAA;;AAAjB;;EAIE,QAAA,MAAc,KAAA,GAAQ,KAAA,EAAO,IAAA,KAAS,CAAA,KAAM,eAAA,CAAgB,EAAA,EAAI,CAAA;EAEhE,GAAA,GAAM,EAAA,EAAI,EAAA,KAAO,SAAA,CAAU,IAAA;EAC3B,IAAA,QAAY,SAAA,CAAU,IAAA;EAHsC;;;EAQ5D,UAAA,EAAY,IAAA;AAAA;AAAA,cAGD,kBAAA,sBAAwC,eAAA,CAAgB,EAAA,EAAI,IAAA;EAAA,iBACtD,OAAA;EAAA,iBACA,QAAA;cAEL,KAAA,EAAO,GAAA,CAAI,EAAA,EAAI,IAAA;EAK3B,GAAA,CAAI,EAAA,EAAI,EAAA,GAAK,IAAA;EAIb,IAAA,CAAA,GAAQ,IAAA;EAIR,QAAA,GAAA,CAAY,KAAA,GAAQ,KAAA,EAAO,IAAA,KAAS,CAAA,GAAI,kBAAA,CAAmB,EAAA,EAAI,CAAA;EAhC5B;;;EAuCnC,SAAA,QAAA,CAAkB,EAAA,GAAK,EAAA,EAAI,EAAA,EAAI,IAAA,EAAM,IAAA,MAAU,GAAA,EAAK,CAAA,IAAK,kBAAA,CAAmB,GAAA,EAAK,CAAA;EAAA,IAW7E,UAAA,CAAA,GAAc,IAAA;AAAA"}
|