@eqtylab/docs 0.3.5 → 0.4.0
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/README.md +45 -12
- package/dist/{chunk-VJN3HXKM.js → chunk-LNQV7TVH.js} +18 -6
- package/dist/chunk-LNQV7TVH.js.map +1 -0
- package/dist/chunk-OM7745ZQ.js +77 -0
- package/dist/chunk-OM7745ZQ.js.map +1 -0
- package/dist/{chunk-IWKZQ4CW.js → chunk-VNQZJMDO.js} +4 -2
- package/dist/chunk-VNQZJMDO.js.map +1 -0
- package/dist/{chunk-K7PJRTK3.js → chunk-X4LT7ASQ.js} +31 -4
- package/dist/chunk-X4LT7ASQ.js.map +1 -0
- package/dist/config.d.ts +10 -1
- package/dist/config.js +1 -1
- package/dist/index.js +295 -28
- package/dist/index.js.map +1 -1
- package/dist/internal/extract-versions.d.ts +33 -0
- package/dist/internal/rehype-base-url.d.ts +9 -2
- package/dist/internal/rehype-base-url.js +1 -1
- package/dist/internal/remark-archive-document.d.ts +6 -0
- package/dist/loaders.d.ts +5 -5
- package/dist/loaders.js +18 -7
- package/dist/loaders.js.map +1 -1
- package/dist/nav.d.ts +4 -0
- package/dist/nav.js +21 -7
- package/dist/nav.js.map +1 -1
- package/dist/paths.d.ts +25 -3
- package/dist/paths.js +1 -1
- package/dist/runtime/chrome/GlobalSearch.tsx +7 -2
- package/dist/runtime/chrome/Header.astro +8 -3
- package/dist/runtime/chrome/NavDrawer.astro +44 -1
- package/dist/runtime/chrome/NavTree.astro +1 -11
- package/dist/runtime/chrome/Prose.astro +17 -3
- package/dist/runtime/chrome/VersionBanner.astro +19 -0
- package/dist/runtime/chrome/VersionSwitcher.tsx +105 -0
- package/dist/runtime/layouts/DocsPage.astro +36 -4
- package/dist/runtime/layouts/DocsShell.astro +4 -2
- package/dist/runtime/layouts/RedirectPage.astro +19 -0
- package/dist/runtime/lib/nav-data.ts +44 -15
- package/dist/runtime/lib/versions-ui.ts +12 -0
- package/dist/runtime/routes/docs-md.ts +50 -11
- package/dist/runtime/routes/docs.astro +182 -73
- package/dist/runtime/routes/llms-txt.ts +2 -1
- package/dist/runtime/routes/not-found.astro +27 -0
- package/dist/schema.d.ts +1 -0
- package/dist/schema.js +1 -1
- package/dist/versions.d.ts +37 -0
- package/package.json +2 -2
- package/dist/chunk-GSSSQTEV.js +0 -51
- package/dist/chunk-GSSSQTEV.js.map +0 -1
- package/dist/chunk-IWKZQ4CW.js.map +0 -1
- package/dist/chunk-K7PJRTK3.js.map +0 -1
- package/dist/chunk-VJN3HXKM.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import './chunk-55J6XMHW.js';
|
|
2
|
-
import { rehypeBaseUrl } from './chunk-
|
|
3
|
-
import { resolveConfig } from './chunk-
|
|
4
|
-
export { resolveConfig } from './chunk-
|
|
2
|
+
import { rehypeBaseUrl, versionFromPath } from './chunk-OM7745ZQ.js';
|
|
3
|
+
import { resolveConfig } from './chunk-X4LT7ASQ.js';
|
|
4
|
+
export { resolveConfig } from './chunk-X4LT7ASQ.js';
|
|
5
5
|
import { resolveDocsEnv } from './chunk-ZZ45WAVR.js';
|
|
6
6
|
export { resolveDocsEnv } from './chunk-ZZ45WAVR.js';
|
|
7
|
-
import { docsHref, isExternalHref } from './chunk-
|
|
8
|
-
export { badgeSchema, docsSchema, groupSchema } from './chunk-
|
|
9
|
-
import
|
|
7
|
+
import { docsHref, isExternalHref } from './chunk-LNQV7TVH.js';
|
|
8
|
+
export { badgeSchema, docsSchema, groupSchema } from './chunk-VNQZJMDO.js';
|
|
9
|
+
import path5 from 'path';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
11
|
import { globSync } from 'tinyglobby';
|
|
12
|
+
import { execFileSync } from 'child_process';
|
|
12
13
|
import fs, { readdirSync, readFileSync } from 'fs';
|
|
13
14
|
import { createRequire } from 'module';
|
|
14
15
|
import { visit, SKIP } from 'unist-util-visit';
|
|
@@ -24,7 +25,7 @@ function assertMdxOnly(contentDir) {
|
|
|
24
25
|
if (strays.length === 0) return;
|
|
25
26
|
const list = strays.sort().map((file) => ` - ${file} -> ${file.replace(/\.md$/i, ".mdx")}`).join("\n");
|
|
26
27
|
throw new Error(
|
|
27
|
-
`[@eqtylab/docs] Found ${strays.length} Markdown file${strays.length > 1 ? "s" : ""} in ${
|
|
28
|
+
`[@eqtylab/docs] Found ${strays.length} Markdown file${strays.length > 1 ? "s" : ""} in ${path5.relative(process.cwd(), dir) || dir}:
|
|
28
29
|
${list}
|
|
29
30
|
|
|
30
31
|
Docs content must be .mdx. Only MDX supports the component overrides that render
|
|
@@ -33,12 +34,242 @@ different from every other page. Renaming is usually the only change needed --
|
|
|
33
34
|
MDX is a superset of Markdown.`
|
|
34
35
|
);
|
|
35
36
|
}
|
|
37
|
+
|
|
38
|
+
// src/versions.ts
|
|
39
|
+
var SEMVER = /(?:^|[^0-9.])(\d+)\.(\d+)\.(\d+)$/;
|
|
40
|
+
var LEVELS = ["patch", "minor", "major"];
|
|
41
|
+
function parseTag(tag) {
|
|
42
|
+
const m = SEMVER.exec(tag.trim());
|
|
43
|
+
if (!m) return null;
|
|
44
|
+
const major = Number(m[1]);
|
|
45
|
+
const minor = Number(m[2]);
|
|
46
|
+
const patch = Number(m[3]);
|
|
47
|
+
return { tag, major, minor, patch, version: `${major}.${minor}.${patch}` };
|
|
48
|
+
}
|
|
49
|
+
function compareTags(a, b) {
|
|
50
|
+
return a.major - b.major || a.minor - b.minor || a.patch - b.patch;
|
|
51
|
+
}
|
|
52
|
+
function groupOf(v, granularity) {
|
|
53
|
+
if (granularity === "major") return `${v.major}`;
|
|
54
|
+
if (granularity === "minor") return `${v.major}.${v.minor}`;
|
|
55
|
+
return v.version;
|
|
56
|
+
}
|
|
57
|
+
function idOf(group) {
|
|
58
|
+
return `v${group}`;
|
|
59
|
+
}
|
|
60
|
+
function suffixOf(id) {
|
|
61
|
+
return id.replace(/\./g, "_");
|
|
62
|
+
}
|
|
63
|
+
function highestTag(tags) {
|
|
64
|
+
const parsed = tags.map(parseTag).filter((t) => t !== null);
|
|
65
|
+
if (!parsed.length) return null;
|
|
66
|
+
return parsed.sort(compareTags)[parsed.length - 1];
|
|
67
|
+
}
|
|
68
|
+
function selectVersions(tags, current, granularity, skippedGroups = []) {
|
|
69
|
+
const cur = parseTag(current);
|
|
70
|
+
if (!cur) {
|
|
71
|
+
throw new Error(`[@eqtylab/docs] versions.current "${current}" is not MAJOR.MINOR.PATCH`);
|
|
72
|
+
}
|
|
73
|
+
const skipped = [];
|
|
74
|
+
const above = [];
|
|
75
|
+
const parsed = [];
|
|
76
|
+
for (const tag of tags) {
|
|
77
|
+
const p = parseTag(tag);
|
|
78
|
+
if (p) parsed.push(p);
|
|
79
|
+
else skipped.push(tag);
|
|
80
|
+
}
|
|
81
|
+
parsed.sort(compareTags);
|
|
82
|
+
const currentGroup = groupOf(cur, granularity);
|
|
83
|
+
const skip = new Set(skippedGroups);
|
|
84
|
+
const byGroup = /* @__PURE__ */ new Map();
|
|
85
|
+
const inCurrent = [];
|
|
86
|
+
const covered = [];
|
|
87
|
+
for (const p of parsed) {
|
|
88
|
+
if (compareTags(p, cur) > 0) {
|
|
89
|
+
above.push(p.tag);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
covered.push(p);
|
|
93
|
+
const g = groupOf(p, granularity);
|
|
94
|
+
if (g === currentGroup) {
|
|
95
|
+
inCurrent.push(p);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (!byGroup.has(g)) byGroup.set(g, []);
|
|
99
|
+
byGroup.get(g).push(p);
|
|
100
|
+
}
|
|
101
|
+
const copies = [];
|
|
102
|
+
const picks = [];
|
|
103
|
+
const coverOf = /* @__PURE__ */ new Map();
|
|
104
|
+
let lastCovered = null;
|
|
105
|
+
for (const [g, members] of byGroup) {
|
|
106
|
+
if (skip.has(g)) {
|
|
107
|
+
coverOf.set(g, lastCovered);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const pick = members[members.length - 1];
|
|
111
|
+
const id = idOf(g);
|
|
112
|
+
copies.push({ id, suffix: suffixOf(id), group: g, tag: pick.tag });
|
|
113
|
+
picks.push(pick);
|
|
114
|
+
coverOf.set(g, id);
|
|
115
|
+
lastCovered = id;
|
|
116
|
+
}
|
|
117
|
+
const redirects = [];
|
|
118
|
+
for (const [g, members] of byGroup) {
|
|
119
|
+
const to = coverOf.get(g) ?? null;
|
|
120
|
+
for (const p of members) {
|
|
121
|
+
const id = idOf(p.version);
|
|
122
|
+
if (id === to) continue;
|
|
123
|
+
redirects.push({ id, to });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
for (const p of inCurrent) redirects.push({ id: idOf(p.version), to: null });
|
|
127
|
+
copies.reverse();
|
|
128
|
+
picks.reverse();
|
|
129
|
+
const emittedIds = new Set(redirects.map((r) => r.id));
|
|
130
|
+
const copyIds = new Set(copies.map((c) => c.id));
|
|
131
|
+
const stubSources = copies.length ? covered.some((p) => p.version === cur.version) ? covered : [...covered, cur] : [];
|
|
132
|
+
for (const level of LEVELS.slice(LEVELS.indexOf(granularity))) {
|
|
133
|
+
const seenGroups = /* @__PURE__ */ new Set();
|
|
134
|
+
for (let i = stubSources.length - 1; i >= 0; i--) {
|
|
135
|
+
const group = groupOf(stubSources[i], level);
|
|
136
|
+
if (seenGroups.has(group)) continue;
|
|
137
|
+
seenGroups.add(group);
|
|
138
|
+
const id = idOf(group);
|
|
139
|
+
if (copyIds.has(id) || emittedIds.has(id)) continue;
|
|
140
|
+
const holdsCurrent = groupOf(cur, level) === group;
|
|
141
|
+
let cover = null;
|
|
142
|
+
for (let c = 0; !holdsCurrent && c < copies.length; c++) {
|
|
143
|
+
if (groupOf(picks[c], level) === group) {
|
|
144
|
+
cover = copies[c].id;
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (!holdsCurrent && cover === null) continue;
|
|
149
|
+
redirects.push({ id, to: cover });
|
|
150
|
+
emittedIds.add(id);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return { copies, redirects, skipped, above };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// src/internal/extract-versions.ts
|
|
157
|
+
var EMPTY_VERSIONS = {
|
|
158
|
+
currentVersion: null,
|
|
159
|
+
versionManifest: [],
|
|
160
|
+
versionRedirects: []
|
|
161
|
+
};
|
|
162
|
+
var TAG = "[@eqtylab/docs] versions:";
|
|
163
|
+
function git(cwd, ...args) {
|
|
164
|
+
return execFileSync("git", args, {
|
|
165
|
+
cwd,
|
|
166
|
+
encoding: "utf8",
|
|
167
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
168
|
+
}).trim();
|
|
169
|
+
}
|
|
170
|
+
function realpath(p) {
|
|
171
|
+
try {
|
|
172
|
+
return fs.realpathSync(p);
|
|
173
|
+
} catch {
|
|
174
|
+
return p;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function hasPathAtTag(repoRoot, tag, rel) {
|
|
178
|
+
try {
|
|
179
|
+
execFileSync("git", ["cat-file", "-e", `${tag}:${rel}`], { cwd: repoRoot, stdio: "ignore" });
|
|
180
|
+
return true;
|
|
181
|
+
} catch {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function extractVersions(o) {
|
|
186
|
+
let repoRoot;
|
|
187
|
+
try {
|
|
188
|
+
repoRoot = git(o.root, "rev-parse", "--show-toplevel");
|
|
189
|
+
} catch {
|
|
190
|
+
o.logger.warn(
|
|
191
|
+
`${TAG} not a git repository, or git is missing. Versioning is off for this build.`
|
|
192
|
+
);
|
|
193
|
+
return EMPTY_VERSIONS;
|
|
194
|
+
}
|
|
195
|
+
if (git(o.root, "rev-parse", "--is-shallow-repository") === "true") {
|
|
196
|
+
o.logger.warn(`${TAG} shallow clone; tags may be incomplete. Check out with fetch-depth: 0.`);
|
|
197
|
+
}
|
|
198
|
+
const tags = git(o.root, "tag", "--list", o.tags).split("\n").filter(Boolean);
|
|
199
|
+
const currentVersion = o.current ?? highestTag(tags)?.version;
|
|
200
|
+
if (!currentVersion) {
|
|
201
|
+
o.logger.info(
|
|
202
|
+
`${TAG} on and dormant. No tag matches "${o.tags}"; versioning activates at the first release tag.`
|
|
203
|
+
);
|
|
204
|
+
return EMPTY_VERSIONS;
|
|
205
|
+
}
|
|
206
|
+
const contentRel = path5.relative(realpath(repoRoot), realpath(o.contentDirAbs)).split(path5.sep).join("/");
|
|
207
|
+
let selection = selectVersions(tags, currentVersion, o.granularity);
|
|
208
|
+
for (const tag of selection.skipped) {
|
|
209
|
+
o.logger.warn(`${TAG} tag "${tag}" is not MAJOR.MINOR.PATCH; skipped.`);
|
|
210
|
+
}
|
|
211
|
+
if (selection.above.length) {
|
|
212
|
+
o.logger.warn(
|
|
213
|
+
`${TAG} tags above current ${currentVersion} ignored: ${selection.above.join(", ")}.`
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
const missing = selection.copies.filter((c) => !hasPathAtTag(repoRoot, c.tag, contentRel));
|
|
217
|
+
if (missing.length) {
|
|
218
|
+
for (const c of missing) {
|
|
219
|
+
o.logger.warn(
|
|
220
|
+
`${TAG} ${c.tag} has no ${contentRel}; skipping ${c.id}. Its releases redirect to the copy below.`
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
selection = selectVersions(
|
|
224
|
+
tags,
|
|
225
|
+
currentVersion,
|
|
226
|
+
o.granularity,
|
|
227
|
+
missing.map((c) => c.group)
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
const versionsDir = path5.join(o.cacheDir, "versions");
|
|
231
|
+
fs.rmSync(versionsDir, { recursive: true, force: true });
|
|
232
|
+
const versionManifest = selection.copies.map((c) => {
|
|
233
|
+
const dir = path5.join(versionsDir, c.id);
|
|
234
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
235
|
+
try {
|
|
236
|
+
const archive = execFileSync("git", ["archive", `${c.tag}:${contentRel}`], {
|
|
237
|
+
cwd: repoRoot,
|
|
238
|
+
maxBuffer: 512 * 1024 * 1024,
|
|
239
|
+
stdio: ["ignore", "pipe", "inherit"]
|
|
240
|
+
});
|
|
241
|
+
execFileSync("tar", ["-x", "-C", dir], {
|
|
242
|
+
input: archive,
|
|
243
|
+
stdio: ["pipe", "ignore", "inherit"]
|
|
244
|
+
});
|
|
245
|
+
} catch (cause) {
|
|
246
|
+
throw new Error(`${TAG} ${c.tag} failed to extract ${contentRel} into ${dir}`, { cause });
|
|
247
|
+
}
|
|
248
|
+
if (!fs.readdirSync(dir).length) {
|
|
249
|
+
throw new Error(`${TAG} ${c.tag} extracted no files into ${dir}`);
|
|
250
|
+
}
|
|
251
|
+
return { ...c, dir };
|
|
252
|
+
});
|
|
253
|
+
const cur = parseTag(currentVersion);
|
|
254
|
+
const group = groupOf(cur, o.granularity);
|
|
255
|
+
const result = {
|
|
256
|
+
currentVersion: { id: idOf(group), group, version: cur.version },
|
|
257
|
+
versionManifest,
|
|
258
|
+
versionRedirects: selection.redirects
|
|
259
|
+
};
|
|
260
|
+
fs.mkdirSync(o.cacheDir, { recursive: true });
|
|
261
|
+
fs.writeFileSync(path5.join(o.cacheDir, "versions.json"), JSON.stringify(result, null, 2));
|
|
262
|
+
o.logger.info(
|
|
263
|
+
`${TAG} current ${result.currentVersion.id}; ${versionManifest.length} older ${versionManifest.length === 1 ? "copy" : "copies"}, ${selection.redirects.length} redirects.`
|
|
264
|
+
);
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
36
267
|
var GRAMMAR_IMPORT = "grammars/${";
|
|
37
268
|
function findGrammarDir(projectRoot) {
|
|
38
269
|
const requireFromProject = createRequire(new URL("package.json", projectRoot));
|
|
39
270
|
const equalityEntry = requireFromProject.resolve("@eqtylab/equality");
|
|
40
271
|
const requireFromEquality = createRequire(equalityEntry);
|
|
41
|
-
return
|
|
272
|
+
return path5.resolve(path5.dirname(requireFromEquality.resolve("microlighter")), "grammars");
|
|
42
273
|
}
|
|
43
274
|
function microlighterGrammarsPlugin(projectRoot, logger) {
|
|
44
275
|
return {
|
|
@@ -46,7 +277,7 @@ function microlighterGrammarsPlugin(projectRoot, logger) {
|
|
|
46
277
|
apply: "build",
|
|
47
278
|
generateBundle(_options, bundle) {
|
|
48
279
|
const directories = new Set(
|
|
49
|
-
Object.values(bundle).filter((output) => output.type === "chunk" && output.code.includes(GRAMMAR_IMPORT)).map((output) =>
|
|
280
|
+
Object.values(bundle).filter((output) => output.type === "chunk" && output.code.includes(GRAMMAR_IMPORT)).map((output) => path5.posix.dirname(output.fileName))
|
|
50
281
|
);
|
|
51
282
|
if (directories.size === 0) return;
|
|
52
283
|
let grammarDir;
|
|
@@ -66,7 +297,7 @@ function microlighterGrammarsPlugin(projectRoot, logger) {
|
|
|
66
297
|
this.emitFile({
|
|
67
298
|
type: "asset",
|
|
68
299
|
fileName: directory === "." ? `grammars/${grammar}` : `${directory}/grammars/${grammar}`,
|
|
69
|
-
source: readFileSync(
|
|
300
|
+
source: readFileSync(path5.resolve(grammarDir, grammar), "utf8")
|
|
70
301
|
});
|
|
71
302
|
}
|
|
72
303
|
}
|
|
@@ -97,7 +328,7 @@ function pagefindIntegration() {
|
|
|
97
328
|
name: "@eqtylab/docs/pagefind",
|
|
98
329
|
hooks: {
|
|
99
330
|
"astro:config:setup"({ config, logger }) {
|
|
100
|
-
indexDir =
|
|
331
|
+
indexDir = path5.join(fileURLToPath(config.outDir), INDEX_DIR);
|
|
101
332
|
if (config.output === "server") {
|
|
102
333
|
logger.warn(
|
|
103
334
|
'Output "server" emits no static HTML, so there is nothing for Pagefind to index.'
|
|
@@ -113,9 +344,9 @@ function pagefindIntegration() {
|
|
|
113
344
|
server.middlewares.use((req, res, next) => {
|
|
114
345
|
const requested = indexRequest(req.url, base);
|
|
115
346
|
if (requested === null) return next();
|
|
116
|
-
const file =
|
|
117
|
-
if (!file.startsWith(indexDir +
|
|
118
|
-
res.setHeader("Content-Type", MIME[
|
|
347
|
+
const file = path5.join(indexDir, requested);
|
|
348
|
+
if (!file.startsWith(indexDir + path5.sep) || !fs.existsSync(file)) return next();
|
|
349
|
+
res.setHeader("Content-Type", MIME[path5.extname(file)] ?? "application/octet-stream");
|
|
119
350
|
res.setHeader("Cache-Control", "no-store");
|
|
120
351
|
fs.createReadStream(file).pipe(res);
|
|
121
352
|
});
|
|
@@ -130,7 +361,7 @@ function pagefindIntegration() {
|
|
|
130
361
|
const { page_count, errors: addErrors } = await index.addDirectory({ path: outDir });
|
|
131
362
|
failOn(addErrors, logger, "index the built output");
|
|
132
363
|
const { outputPath, errors: writeErrors } = await index.writeFiles({
|
|
133
|
-
outputPath:
|
|
364
|
+
outputPath: path5.join(outDir, INDEX_DIR)
|
|
134
365
|
});
|
|
135
366
|
failOn(writeErrors, logger, "write the index");
|
|
136
367
|
logger.info(`indexed ${page_count} pages to ${outputPath}`);
|
|
@@ -202,9 +433,9 @@ function rehypeProseScope() {
|
|
|
202
433
|
}
|
|
203
434
|
var CONTENT_EXTENSIONS = [".mdx", ".md"];
|
|
204
435
|
function hasEntry(contentRoot, id) {
|
|
205
|
-
const stem =
|
|
436
|
+
const stem = path5.join(contentRoot, id);
|
|
206
437
|
return CONTENT_EXTENSIONS.some(
|
|
207
|
-
(ext) => fs.existsSync(stem + ext) || fs.existsSync(
|
|
438
|
+
(ext) => fs.existsSync(stem + ext) || fs.existsSync(path5.join(stem, `index${ext}`))
|
|
208
439
|
);
|
|
209
440
|
}
|
|
210
441
|
function splitTarget(href) {
|
|
@@ -220,18 +451,18 @@ function rehypeRelativeLinks(options) {
|
|
|
220
451
|
return function transformer(tree, file) {
|
|
221
452
|
const filePath = file?.path;
|
|
222
453
|
if (!filePath) return;
|
|
223
|
-
const fromRoot =
|
|
224
|
-
if (!fromRoot || fromRoot.startsWith("..") ||
|
|
454
|
+
const fromRoot = path5.relative(contentRoot, filePath);
|
|
455
|
+
if (!fromRoot || fromRoot.startsWith("..") || path5.isAbsolute(fromRoot)) return;
|
|
225
456
|
visit(tree, "element", (node) => {
|
|
226
457
|
const props = node.properties;
|
|
227
458
|
const href = props?.href;
|
|
228
459
|
if (!props || typeof href !== "string") return;
|
|
229
460
|
const split = splitTarget(href);
|
|
230
461
|
if (!split) return;
|
|
231
|
-
const absolute =
|
|
232
|
-
const relative =
|
|
233
|
-
if (!relative || relative.startsWith("..") ||
|
|
234
|
-
const id = relative.split(
|
|
462
|
+
const absolute = path5.resolve(path5.dirname(filePath), split.target);
|
|
463
|
+
const relative = path5.relative(contentRoot, absolute);
|
|
464
|
+
if (!relative || relative.startsWith("..") || path5.isAbsolute(relative)) return;
|
|
465
|
+
const id = relative.split(path5.sep).join("/").replace(/\.mdx?$/i, "").replace(/\/index$/, "");
|
|
235
466
|
if (!hasEntry(contentRoot, id)) onMissing?.(href, filePath);
|
|
236
467
|
props.href = docsHref(id, ctx) + split.suffix;
|
|
237
468
|
});
|
|
@@ -268,10 +499,31 @@ function rehypeTableColumns() {
|
|
|
268
499
|
});
|
|
269
500
|
};
|
|
270
501
|
}
|
|
502
|
+
|
|
503
|
+
// src/internal/remark-archive-document.ts
|
|
504
|
+
var MDX_NODES = /* @__PURE__ */ new Set([
|
|
505
|
+
"mdxjsEsm",
|
|
506
|
+
"mdxJsxFlowElement",
|
|
507
|
+
"mdxJsxTextElement",
|
|
508
|
+
"mdxFlowExpression",
|
|
509
|
+
"mdxTextExpression"
|
|
510
|
+
]);
|
|
511
|
+
function prune(node) {
|
|
512
|
+
if (!Array.isArray(node.children)) return;
|
|
513
|
+
node.children = node.children.filter((child) => !MDX_NODES.has(child.type));
|
|
514
|
+
for (const child of node.children) prune(child);
|
|
515
|
+
}
|
|
516
|
+
function remarkArchiveDocument(options) {
|
|
517
|
+
return function transformer(tree, file) {
|
|
518
|
+
const version = versionFromPath(file?.path ?? file?.history?.[0], options.versionsDir);
|
|
519
|
+
if (!version) return;
|
|
520
|
+
prune(tree);
|
|
521
|
+
};
|
|
522
|
+
}
|
|
271
523
|
var PAGE_EXTENSIONS = ["astro", "md", "mdx", "html", "ts", "js"];
|
|
272
524
|
function toRoutePath(relative) {
|
|
273
525
|
const withoutExt = relative.replace(/\.[^./]+$/, "");
|
|
274
|
-
const segments = withoutExt.split(
|
|
526
|
+
const segments = withoutExt.split(path5.sep).join("/").split("/").filter(Boolean);
|
|
275
527
|
if (segments.at(-1) === "index") segments.pop();
|
|
276
528
|
return "/" + segments.join("/");
|
|
277
529
|
}
|
|
@@ -289,7 +541,7 @@ function scanConsumerPages(srcDir) {
|
|
|
289
541
|
const ownedPaths = [];
|
|
290
542
|
const claimedPatterns = /* @__PURE__ */ new Set();
|
|
291
543
|
for (const file of files) {
|
|
292
|
-
if (file.split(
|
|
544
|
+
if (file.split(path5.sep).some((segment) => segment.startsWith("_"))) continue;
|
|
293
545
|
const routePath = toRoutePath(file);
|
|
294
546
|
claimedPatterns.add(routePath === "" ? "/" : routePath);
|
|
295
547
|
if (!/[[\]]/.test(file)) {
|
|
@@ -353,6 +605,15 @@ function docs(options = {}) {
|
|
|
353
605
|
async "astro:config:setup"(params) {
|
|
354
606
|
const { config, injectRoute, injectScript, updateConfig, addWatchFile, logger, command } = params;
|
|
355
607
|
assertMdxOnly(new URL(`./${cfg.contentDir}/`, config.srcDir));
|
|
608
|
+
const versionData = cfg.versions === false ? EMPTY_VERSIONS : extractVersions({
|
|
609
|
+
root: fileURLToPath(config.root),
|
|
610
|
+
contentDirAbs: fileURLToPath(new URL(`./${cfg.contentDir}/`, config.srcDir)),
|
|
611
|
+
cacheDir: fileURLToPath(new URL("./.astro/eqty-docs/", config.root)),
|
|
612
|
+
current: cfg.versions.current,
|
|
613
|
+
tags: cfg.versions.tags,
|
|
614
|
+
granularity: cfg.versions.granularity,
|
|
615
|
+
logger
|
|
616
|
+
});
|
|
356
617
|
const consumer = scanConsumerPages(config.srcDir);
|
|
357
618
|
for (const route of plannedRoutes(cfg)) {
|
|
358
619
|
if (consumer.claimedPatterns.has(route.pattern)) {
|
|
@@ -367,7 +628,8 @@ function docs(options = {}) {
|
|
|
367
628
|
...cfg,
|
|
368
629
|
env,
|
|
369
630
|
// Read by the catch-all's getStaticPaths so no path is emitted twice.
|
|
370
|
-
ownedByConsumer: consumer.ownedPaths
|
|
631
|
+
ownedByConsumer: consumer.ownedPaths,
|
|
632
|
+
...versionData
|
|
371
633
|
};
|
|
372
634
|
if (command === "dev") {
|
|
373
635
|
addWatchFile(new URL(`./${cfg.contentDir}/`, config.srcDir));
|
|
@@ -414,8 +676,10 @@ function docs(options = {}) {
|
|
|
414
676
|
};
|
|
415
677
|
markdown.gfm = true;
|
|
416
678
|
markdown.smartypants = true;
|
|
679
|
+
const versionsDir = fileURLToPath(new URL("./.astro/eqty-docs/versions/", config.root));
|
|
680
|
+
markdown.remarkPlugins = [[remarkArchiveDocument, { versionsDir }]];
|
|
417
681
|
markdown.rehypePlugins = [
|
|
418
|
-
[rehypeBaseUrl, { base: config.base }],
|
|
682
|
+
[rehypeBaseUrl, { base: config.base, pathPrefix: cfg.pathPrefix, versionsDir }],
|
|
419
683
|
// Must follow rehypeBaseUrl: the hrefs this emits already carry `base`, and
|
|
420
684
|
// rehypeBaseUrl would prefix them a second time.
|
|
421
685
|
[
|
|
@@ -425,7 +689,7 @@ function docs(options = {}) {
|
|
|
425
689
|
base: config.base,
|
|
426
690
|
pathPrefix: cfg.pathPrefix,
|
|
427
691
|
onMissing: (href, filePath) => logger.warn(
|
|
428
|
-
`${
|
|
692
|
+
`${path5.relative(fileURLToPath(config.root), filePath)} links to ${href}, which is not a page in ${cfg.contentDir}`
|
|
429
693
|
)
|
|
430
694
|
}
|
|
431
695
|
],
|
|
@@ -454,6 +718,9 @@ function docs(options = {}) {
|
|
|
454
718
|
` const config: import('@eqtylab/docs').DocsConfig & {`,
|
|
455
719
|
` env: import('@eqtylab/docs').DocsEnv;`,
|
|
456
720
|
` ownedByConsumer: string[];`,
|
|
721
|
+
` currentVersion: { id: string; group: string; version: string } | null;`,
|
|
722
|
+
` versionManifest: Array<{ id: string; suffix: string; group: string; tag: string; dir: string }>;`,
|
|
723
|
+
` versionRedirects: Array<{ id: string; to: string | null }>;`,
|
|
457
724
|
` };`,
|
|
458
725
|
` export default config;`,
|
|
459
726
|
`}`,
|