blume 2.2.2 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/cli/{chunk-080mfch6.js → chunk-0wt5amrk.js} +15 -15
- package/dist/cli/{chunk-k45sq16q.js → chunk-0xyedh7k.js} +39 -23
- package/dist/cli/{chunk-k45sq16q.js.map → chunk-0xyedh7k.js.map} +3 -3
- package/dist/cli/{chunk-f260jdrn.js → chunk-0ynr0fr7.js} +5 -5
- package/dist/cli/{chunk-e1n41w9m.js → chunk-1ay3hzn0.js} +3 -3
- package/dist/cli/{chunk-b680sv30.js → chunk-2f6btenb.js} +10 -8
- package/dist/cli/chunk-2f6btenb.js.map +13 -0
- package/dist/cli/{chunk-gwy55cx3.js → chunk-426rytg6.js} +2 -2
- package/dist/cli/{chunk-9h8mh2tk.js → chunk-5f96yq2c.js} +1 -1
- package/dist/cli/{chunk-x60e15st.js → chunk-5xq12jz7.js} +17 -17
- package/dist/cli/{chunk-x7bh6d9j.js → chunk-6xag1c83.js} +4 -4
- package/dist/cli/{chunk-487b95qy.js → chunk-88q28zav.js} +41 -25
- package/dist/cli/{chunk-487b95qy.js.map → chunk-88q28zav.js.map} +3 -3
- package/dist/cli/{chunk-yg8ckc3g.js → chunk-88zkpg89.js} +2 -2
- package/dist/cli/{chunk-ppa6mg4d.js → chunk-8fm3b4vm.js} +6 -6
- package/dist/cli/{chunk-rtvgmg2j.js → chunk-8h2t2vyj.js} +2 -2
- package/dist/cli/{chunk-2ssh60qh.js → chunk-982qfeny.js} +6 -6
- package/dist/cli/{chunk-t2h8pwy1.js → chunk-9emfspcp.js} +4 -4
- package/dist/cli/{chunk-9jqmq5hv.js → chunk-akj2p7k1.js} +6 -6
- package/dist/cli/{chunk-beb0z983.js → chunk-b664x65a.js} +16 -16
- package/dist/cli/{chunk-kmswjxj9.js → chunk-b7n58hgj.js} +3 -3
- package/dist/cli/{chunk-fnxgtjeq.js → chunk-c0qddrxr.js} +1 -1
- package/dist/cli/{chunk-p834rkcn.js → chunk-g62vnvaw.js} +5 -5
- package/dist/cli/{chunk-zxd5jrgx.js → chunk-gc7knd2s.js} +76 -34
- package/dist/cli/{chunk-zxd5jrgx.js.map → chunk-gc7knd2s.js.map} +4 -4
- package/dist/cli/{chunk-r5nm9w0c.js → chunk-hwjspffr.js} +105 -36
- package/dist/cli/{chunk-r5nm9w0c.js.map → chunk-hwjspffr.js.map} +11 -10
- package/dist/cli/{chunk-40vk8kgf.js → chunk-p4fe7tax.js} +7 -7
- package/dist/cli/{chunk-34wap3ed.js → chunk-psg2za5z.js} +3 -3
- package/dist/cli/{chunk-hktq4j5r.js → chunk-pxp1y6yz.js} +16 -10
- package/dist/cli/{chunk-hktq4j5r.js.map → chunk-pxp1y6yz.js.map} +4 -4
- package/dist/cli/{chunk-qcyxkj44.js → chunk-qax1aekz.js} +43 -17
- package/dist/cli/chunk-qax1aekz.js.map +15 -0
- package/dist/cli/{chunk-h0qwdbem.js → chunk-r5ajrw1g.js} +2 -2
- package/dist/cli/{chunk-q1wwrxzw.js → chunk-rc2qk3qx.js} +3 -3
- package/dist/cli/chunk-rc2qk3qx.js.map +10 -0
- package/dist/cli/{chunk-69rjf786.js → chunk-ry2ymbxf.js} +5 -5
- package/dist/cli/{chunk-gxhcf2hs.js → chunk-t43g7v22.js} +2 -2
- package/dist/cli/{chunk-ydqzkhjn.js → chunk-x0jqyq1g.js} +6 -6
- package/dist/cli/{chunk-aafhwx74.js → chunk-x25s4gph.js} +1 -1
- package/dist/cli/{chunk-nqna8dzp.js → chunk-xkx216rd.js} +17 -17
- package/dist/cli/{chunk-etckvbrh.js → chunk-xv8nkt56.js} +14 -14
- package/dist/cli/{chunk-hn3g2b89.js → chunk-yrmw5n2b.js} +9 -9
- package/dist/cli/{chunk-4zxh25hc.js → chunk-zgca0vxs.js} +2 -2
- package/dist/cli/{chunk-c5bjxq8v.js → chunk-zj6bcx0n.js} +2 -2
- package/dist/cli/{chunk-1ch3ct3r.js → chunk-zjfwzrvd.js} +14 -14
- package/dist/cli/{chunk-j4nfgn2j.js → chunk-znwhf37a.js} +1 -1
- package/dist/cli/index.js +18 -18
- package/dist/types/ai/ask-context.d.ts +8 -0
- package/dist/types/ai/link-text.d.ts +5 -0
- package/dist/types/ai/relative-links.d.ts +26 -6
- package/dist/types/core/config-input.d.ts +35 -1
- package/dist/types/core/data.d.ts +14 -0
- package/dist/types/core/last-modified.d.ts +33 -18
- package/dist/types/core/links.d.ts +16 -0
- package/dist/types/core/schema.d.ts +16 -1
- package/dist/types/core/types.d.ts +10 -0
- package/dist/types/deploy/sitemap.d.ts +9 -0
- package/dist/types/search/documents.d.ts +3 -1
- package/dist/types/search/fold.d.ts +33 -0
- package/dist/types/search/orama-index.d.ts +4 -4
- package/dist/types/seo/jsonld.d.ts +33 -0
- package/docs/configuration/search.mdx +2 -2
- package/docs/content/frontmatter.mdx +1 -1
- package/docs/content/i18n.mdx +1 -1
- package/docs/content/sources/remote-mdx.mdx +1 -1
- package/docs/discoverability/open-graph.mdx +16 -1
- package/docs/discoverability/sitemap-and-robots.mdx +12 -0
- package/docs/discoverability/structured-data.mdx +44 -0
- package/package.json +1 -1
- package/src/ai/ask-context.ts +52 -14
- package/src/ai/ask-data.ts +4 -1
- package/src/ai/ask-tools.ts +17 -5
- package/src/ai/link-text.ts +6 -0
- package/src/ai/llms.ts +1 -7
- package/src/ai/markdown.ts +8 -4
- package/src/ai/relative-links.ts +155 -48
- package/src/ai/site-skill.ts +1 -4
- package/src/astro/generate.ts +7 -0
- package/src/astro/templates.ts +36 -20
- package/src/components/layout/PageLayout.astro +25 -12
- package/src/components/layout/RootLayout.astro +7 -0
- package/src/components/layout/locale-redirect.ts +38 -19
- package/src/components/layout/search/types.ts +12 -4
- package/src/core/config-input.ts +34 -1
- package/src/core/config.ts +5 -2
- package/src/core/data.ts +14 -0
- package/src/core/last-modified.ts +80 -34
- package/src/core/links.ts +43 -2
- package/src/core/manifest.ts +2 -0
- package/src/core/project-graph.ts +83 -43
- package/src/core/schema.ts +47 -9
- package/src/core/types.ts +10 -0
- package/src/deploy/sitemap.ts +127 -49
- package/src/search/documents.ts +34 -11
- package/src/search/fold.ts +175 -0
- package/src/search/orama-index.ts +40 -49
- package/src/seo/jsonld.ts +100 -23
- package/dist/cli/chunk-b680sv30.js.map +0 -13
- package/dist/cli/chunk-q1wwrxzw.js.map +0 -10
- package/dist/cli/chunk-qcyxkj44.js.map +0 -14
- /package/dist/cli/{chunk-080mfch6.js.map → chunk-0wt5amrk.js.map} +0 -0
- /package/dist/cli/{chunk-f260jdrn.js.map → chunk-0ynr0fr7.js.map} +0 -0
- /package/dist/cli/{chunk-e1n41w9m.js.map → chunk-1ay3hzn0.js.map} +0 -0
- /package/dist/cli/{chunk-gwy55cx3.js.map → chunk-426rytg6.js.map} +0 -0
- /package/dist/cli/{chunk-9h8mh2tk.js.map → chunk-5f96yq2c.js.map} +0 -0
- /package/dist/cli/{chunk-x60e15st.js.map → chunk-5xq12jz7.js.map} +0 -0
- /package/dist/cli/{chunk-x7bh6d9j.js.map → chunk-6xag1c83.js.map} +0 -0
- /package/dist/cli/{chunk-yg8ckc3g.js.map → chunk-88zkpg89.js.map} +0 -0
- /package/dist/cli/{chunk-ppa6mg4d.js.map → chunk-8fm3b4vm.js.map} +0 -0
- /package/dist/cli/{chunk-rtvgmg2j.js.map → chunk-8h2t2vyj.js.map} +0 -0
- /package/dist/cli/{chunk-2ssh60qh.js.map → chunk-982qfeny.js.map} +0 -0
- /package/dist/cli/{chunk-t2h8pwy1.js.map → chunk-9emfspcp.js.map} +0 -0
- /package/dist/cli/{chunk-9jqmq5hv.js.map → chunk-akj2p7k1.js.map} +0 -0
- /package/dist/cli/{chunk-beb0z983.js.map → chunk-b664x65a.js.map} +0 -0
- /package/dist/cli/{chunk-kmswjxj9.js.map → chunk-b7n58hgj.js.map} +0 -0
- /package/dist/cli/{chunk-fnxgtjeq.js.map → chunk-c0qddrxr.js.map} +0 -0
- /package/dist/cli/{chunk-p834rkcn.js.map → chunk-g62vnvaw.js.map} +0 -0
- /package/dist/cli/{chunk-40vk8kgf.js.map → chunk-p4fe7tax.js.map} +0 -0
- /package/dist/cli/{chunk-34wap3ed.js.map → chunk-psg2za5z.js.map} +0 -0
- /package/dist/cli/{chunk-h0qwdbem.js.map → chunk-r5ajrw1g.js.map} +0 -0
- /package/dist/cli/{chunk-69rjf786.js.map → chunk-ry2ymbxf.js.map} +0 -0
- /package/dist/cli/{chunk-gxhcf2hs.js.map → chunk-t43g7v22.js.map} +0 -0
- /package/dist/cli/{chunk-ydqzkhjn.js.map → chunk-x0jqyq1g.js.map} +0 -0
- /package/dist/cli/{chunk-aafhwx74.js.map → chunk-x25s4gph.js.map} +0 -0
- /package/dist/cli/{chunk-nqna8dzp.js.map → chunk-xkx216rd.js.map} +0 -0
- /package/dist/cli/{chunk-etckvbrh.js.map → chunk-xv8nkt56.js.map} +0 -0
- /package/dist/cli/{chunk-hn3g2b89.js.map → chunk-yrmw5n2b.js.map} +0 -0
- /package/dist/cli/{chunk-4zxh25hc.js.map → chunk-zgca0vxs.js.map} +0 -0
- /package/dist/cli/{chunk-c5bjxq8v.js.map → chunk-zj6bcx0n.js.map} +0 -0
- /package/dist/cli/{chunk-1ch3ct3r.js.map → chunk-zjfwzrvd.js.map} +0 -0
- /package/dist/cli/{chunk-j4nfgn2j.js.map → chunk-znwhf37a.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
locateMdxFailure
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-gc7knd2s.js";
|
|
5
5
|
|
|
6
6
|
// src/cli/build-failure.ts
|
|
7
7
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -154,4 +154,4 @@ var buildFailureLocator = (project) => (file, failure) => {
|
|
|
154
154
|
export { astroBuildDiagnostics, buildFailureLocator };
|
|
155
155
|
|
|
156
156
|
//# debugId=A5E390AFCF69E70164756E2164756E21
|
|
157
|
-
//# sourceMappingURL=chunk-
|
|
157
|
+
//# sourceMappingURL=chunk-zgca0vxs.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
packageSrc,
|
|
8
8
|
registry,
|
|
9
9
|
findItem
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-5f96yq2c.js";
|
|
11
11
|
|
|
12
12
|
// src/cli/commands/add.ts
|
|
13
13
|
import { existsSync } from "node:fs";
|
|
@@ -96,4 +96,4 @@ export {
|
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
//# debugId=B640E77C94BA0A0364756E2164756E21
|
|
99
|
-
//# sourceMappingURL=chunk-
|
|
99
|
+
//# sourceMappingURL=chunk-zj6bcx0n.js.map
|
|
@@ -8,28 +8,28 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
commandsFor,
|
|
10
10
|
detectProjectPackageManager
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-hwjspffr.js";
|
|
12
12
|
import"./chunk-zccbjcj0.js";
|
|
13
|
-
import"./chunk-
|
|
14
|
-
import"./chunk-
|
|
15
|
-
import"./chunk-
|
|
16
|
-
import"./chunk-
|
|
17
|
-
import"./chunk-
|
|
18
|
-
import"./chunk-
|
|
13
|
+
import"./chunk-pxp1y6yz.js";
|
|
14
|
+
import"./chunk-gc7knd2s.js";
|
|
15
|
+
import"./chunk-2f6btenb.js";
|
|
16
|
+
import"./chunk-0xyedh7k.js";
|
|
17
|
+
import"./chunk-8h2t2vyj.js";
|
|
18
|
+
import"./chunk-znwhf37a.js";
|
|
19
19
|
import"./chunk-jq5n4avg.js";
|
|
20
|
-
import"./chunk-
|
|
21
|
-
import"./chunk-
|
|
20
|
+
import"./chunk-88q28zav.js";
|
|
21
|
+
import"./chunk-5f96yq2c.js";
|
|
22
22
|
import {
|
|
23
23
|
updatePackageScripts,
|
|
24
24
|
isEjectedProject
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-1ay3hzn0.js";
|
|
26
26
|
import {
|
|
27
27
|
eject
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-p4fe7tax.js";
|
|
29
29
|
import {
|
|
30
30
|
refuseIfDevRunning
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import"./chunk-
|
|
31
|
+
} from "./chunk-r5ajrw1g.js";
|
|
32
|
+
import"./chunk-rc2qk3qx.js";
|
|
33
33
|
|
|
34
34
|
// src/cli/commands/eject.ts
|
|
35
35
|
import { defineCommand } from "citty";
|
|
@@ -95,4 +95,4 @@ export {
|
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
//# debugId=9A7F310B3D4EBEE364756E2164756E21
|
|
98
|
-
//# sourceMappingURL=chunk-
|
|
98
|
+
//# sourceMappingURL=chunk-zjfwzrvd.js.map
|
|
@@ -390,4 +390,4 @@ var analyzeComponentOverrides = (source, filePath) => {
|
|
|
390
390
|
export { emptyComponentOverrides, ComponentOverridesError, analyzeComponentOverrides };
|
|
391
391
|
|
|
392
392
|
//# debugId=59653B23465A56F364756E2164756E21
|
|
393
|
-
//# sourceMappingURL=chunk-
|
|
393
|
+
//# sourceMappingURL=chunk-znwhf37a.js.map
|
package/dist/cli/index.js
CHANGED
|
@@ -725,24 +725,24 @@ var main = defineCommand({
|
|
|
725
725
|
version: getBlumeVersion()
|
|
726
726
|
},
|
|
727
727
|
subCommands: {
|
|
728
|
-
add: lazyCommand(commandMeta.add, () => import("./chunk-
|
|
729
|
-
audit: lazyCommand(commandMeta.audit, () => import("./chunk-
|
|
730
|
-
build: lazyCommand(commandMeta.build, () => import("./chunk-
|
|
731
|
-
check: lazyCommand(commandMeta.check, () => import("./chunk-
|
|
732
|
-
dev: lazyCommand(commandMeta.dev, () => import("./chunk-
|
|
733
|
-
doctor: lazyCommand(commandMeta.doctor, () => import("./chunk-
|
|
734
|
-
eject: lazyCommand(commandMeta.eject, () => import("./chunk-
|
|
735
|
-
eval: lazyCommand(commandMeta.eval, () => import("./chunk-
|
|
736
|
-
init: lazyCommand(commandMeta.init, () => import("./chunk-
|
|
737
|
-
"mcp-stdio": lazyCommand(commandMeta["mcp-stdio"], () => import("./chunk-
|
|
738
|
-
migrate: lazyCommand(commandMeta.migrate, () => import("./chunk-
|
|
739
|
-
preview: lazyCommand(commandMeta.preview, () => import("./chunk-
|
|
740
|
-
skill: lazyCommand(commandMeta.skill, () => import("./chunk-
|
|
741
|
-
sync: lazyCommand(commandMeta.sync, () => import("./chunk-
|
|
742
|
-
translate: lazyCommand(commandMeta.translate, () => import("./chunk-
|
|
743
|
-
upgrade: lazyCommand(commandMeta.upgrade, () => import("./chunk-
|
|
744
|
-
validate: lazyCommand(commandMeta.validate, () => import("./chunk-
|
|
745
|
-
version: lazyCommand(commandMeta.version, () => import("./chunk-
|
|
728
|
+
add: lazyCommand(commandMeta.add, () => import("./chunk-zj6bcx0n.js"), "addCommand"),
|
|
729
|
+
audit: lazyCommand(commandMeta.audit, () => import("./chunk-982qfeny.js"), "auditCommand"),
|
|
730
|
+
build: lazyCommand(commandMeta.build, () => import("./chunk-xkx216rd.js"), "buildCommand"),
|
|
731
|
+
check: lazyCommand(commandMeta.check, () => import("./chunk-b664x65a.js"), "checkCommand"),
|
|
732
|
+
dev: lazyCommand(commandMeta.dev, () => import("./chunk-5xq12jz7.js"), "devCommand"),
|
|
733
|
+
doctor: lazyCommand(commandMeta.doctor, () => import("./chunk-yrmw5n2b.js"), "doctorCommand"),
|
|
734
|
+
eject: lazyCommand(commandMeta.eject, () => import("./chunk-zjfwzrvd.js"), "ejectCommand"),
|
|
735
|
+
eval: lazyCommand(commandMeta.eval, () => import("./chunk-akj2p7k1.js"), "evalCommand"),
|
|
736
|
+
init: lazyCommand(commandMeta.init, () => import("./chunk-xv8nkt56.js"), "initCommand"),
|
|
737
|
+
"mcp-stdio": lazyCommand(commandMeta["mcp-stdio"], () => import("./chunk-qax1aekz.js"), "mcpStdioCommand"),
|
|
738
|
+
migrate: lazyCommand(commandMeta.migrate, () => import("./chunk-88zkpg89.js"), "migrateCommand"),
|
|
739
|
+
preview: lazyCommand(commandMeta.preview, () => import("./chunk-ry2ymbxf.js"), "previewCommand"),
|
|
740
|
+
skill: lazyCommand(commandMeta.skill, () => import("./chunk-g62vnvaw.js"), "skillCommand"),
|
|
741
|
+
sync: lazyCommand(commandMeta.sync, () => import("./chunk-0wt5amrk.js"), "syncCommand"),
|
|
742
|
+
translate: lazyCommand(commandMeta.translate, () => import("./chunk-0ynr0fr7.js"), "translateCommand"),
|
|
743
|
+
upgrade: lazyCommand(commandMeta.upgrade, () => import("./chunk-x0jqyq1g.js"), "upgradeCommand"),
|
|
744
|
+
validate: lazyCommand(commandMeta.validate, () => import("./chunk-8fm3b4vm.js"), "validateCommand"),
|
|
745
|
+
version: lazyCommand(commandMeta.version, () => import("./chunk-6xag1c83.js"), "versionCommand")
|
|
746
746
|
}
|
|
747
747
|
});
|
|
748
748
|
loadEnvFiles(process.cwd());
|
|
@@ -52,6 +52,14 @@ export interface AskRetrievalOptions {
|
|
|
52
52
|
*/
|
|
53
53
|
maxResults?: number;
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* An excerpt's heading: the Markdown link the model cites the page with. A
|
|
57
|
+
* bracket or backslash in the title, or whitespace or a parenthesis in the
|
|
58
|
+
* route, would break the link, and a `%` in the route would read back as an
|
|
59
|
+
* escape (`read_page` decodes them), so those are escaped; the rest of the
|
|
60
|
+
* route stays as the reader sees it (`/ja/ポイント`).
|
|
61
|
+
*/
|
|
62
|
+
export declare const excerptHeading: (doc: Pick<OramaDoc, "route" | "title">) => string;
|
|
55
63
|
/**
|
|
56
64
|
* Excerpt the region of `content` most relevant to `query`, not just its head.
|
|
57
65
|
*
|
|
@@ -6,7 +6,9 @@ import type { BlumeProject } from "../core/project-graph.ts";
|
|
|
6
6
|
* link lands on `/install`; the rendered page rewrites it to the route it
|
|
7
7
|
* means (`markdown/relative-links.ts`), and the Markdown an agent reads gets
|
|
8
8
|
* the same rewrite from the same resolver (`resolveRelativeHref`), so both
|
|
9
|
-
* point at one page.
|
|
9
|
+
* point at one page. A raw HTML `<a href>` ships as written, so a relative
|
|
10
|
+
* one lands where the browser takes it from the page's URL
|
|
11
|
+
* (`resolveRawRelativeHref`). Root-relative links (`[x](/guide)`,
|
|
10
12
|
* `<Card href="/guide">`, ``) get what the rendered page
|
|
11
13
|
* gives them too (`markdown/base-links.ts`,
|
|
12
14
|
* `components/content/base-href.ts`): a page link the `deployment.base` +
|
|
@@ -18,18 +20,36 @@ import type { BlumeProject } from "../core/project-graph.ts";
|
|
|
18
20
|
* (`resolveRootFileHref`). Inline links, images, component
|
|
19
21
|
* `href`s, and reference definitions are rewritten; fenced and inline code,
|
|
20
22
|
* relative images and asset links, and external URLs are left as written.
|
|
23
|
+
* The assistant's snapshot takes the links that name a page by its path or
|
|
24
|
+
* file alone, as the routes it keys pages by (`assistant`).
|
|
21
25
|
*/
|
|
22
26
|
/** The page a Markdown text was written for. */
|
|
23
27
|
export interface LinkedPage {
|
|
28
|
+
/**
|
|
29
|
+
* A staged page's path under its staging dir, which its links resolve from
|
|
30
|
+
* when it has no `sourcePath` (a remote or CMS source).
|
|
31
|
+
*/
|
|
32
|
+
entryId?: string;
|
|
24
33
|
route: string;
|
|
25
34
|
sourcePath?: string;
|
|
26
35
|
}
|
|
27
36
|
/** Rewrite a page's relative page links to the routes they mean. */
|
|
28
37
|
export type RelativeLinkRewriter = (text: string, page: LinkedPage) => string;
|
|
38
|
+
/** Who reads the rewritten links. */
|
|
39
|
+
export interface RelativeLinkOptions {
|
|
40
|
+
/**
|
|
41
|
+
* The assistant's snapshot, rather than a page an agent fetches by URL.
|
|
42
|
+
* Only a link that names a page by its relative path or its content file
|
|
43
|
+
* changes, to the route the snapshot keys that page by: without the
|
|
44
|
+
* `deployment.base`, since the chat panel mounts every link it renders
|
|
45
|
+
* under it, and a locale's fallback copy as the page it renders, since the
|
|
46
|
+
* snapshot holds that page instead. Root page links and images stay as
|
|
47
|
+
* written.
|
|
48
|
+
*/
|
|
49
|
+
assistant?: boolean;
|
|
50
|
+
}
|
|
29
51
|
/**
|
|
30
|
-
* Build the rewriter for a project
|
|
31
|
-
*
|
|
32
|
-
* publishes once per locale, and the default locale's route stands for it;
|
|
33
|
-
* fallback copies render another locale's file, so they never stand for one.
|
|
52
|
+
* Build the rewriter for a project, for an agent reading a page by URL or,
|
|
53
|
+
* with `assistant`, for the assistant's snapshot.
|
|
34
54
|
*/
|
|
35
|
-
export declare const relativeLinkRewriter: (project: BlumeProject) => RelativeLinkRewriter;
|
|
55
|
+
export declare const relativeLinkRewriter: (project: BlumeProject, options?: RelativeLinkOptions) => RelativeLinkRewriter;
|
|
@@ -981,6 +981,12 @@ export interface OgPaletteConfig {
|
|
|
981
981
|
}
|
|
982
982
|
/** Per-page Open Graph image generation. */
|
|
983
983
|
export interface OgConfig {
|
|
984
|
+
/**
|
|
985
|
+
* Default social image for pages without their own `seo.image`, in place of
|
|
986
|
+
* the generated card (which then defaults off): one path or URL, or one per
|
|
987
|
+
* locale, like any localizable label.
|
|
988
|
+
*/
|
|
989
|
+
image?: string | Record<string, string>;
|
|
984
990
|
/**
|
|
985
991
|
* Card subtitle. Defaults to the site description; a string overrides it,
|
|
986
992
|
* `false` renders the card without one.
|
|
@@ -1097,6 +1103,31 @@ export interface SoftwareConfig {
|
|
|
1097
1103
|
}
|
|
1098
1104
|
/** Discoverability: OG images, feeds, sitemap, robots, and structured data. */
|
|
1099
1105
|
export interface SeoConfig {
|
|
1106
|
+
/**
|
|
1107
|
+
* Structured-data entities shared with a parent site (`example.com/docs`),
|
|
1108
|
+
* referenced by absolute `@id` instead of defined again.
|
|
1109
|
+
*/
|
|
1110
|
+
jsonLd?: {
|
|
1111
|
+
/** The WebSite's `@id`, which every page names as `isPartOf`. */
|
|
1112
|
+
websiteId?: string;
|
|
1113
|
+
/** The Organization's `@id`; `organization` still adds its details. */
|
|
1114
|
+
organizationId?: string;
|
|
1115
|
+
/** Credited on pages without their own `authors`. */
|
|
1116
|
+
author?: {
|
|
1117
|
+
"@id": string;
|
|
1118
|
+
};
|
|
1119
|
+
/** Every page's publisher, over the Organization. */
|
|
1120
|
+
publisher?: {
|
|
1121
|
+
"@id": string;
|
|
1122
|
+
};
|
|
1123
|
+
/** Emit the WebSite node. Defaults to true unless `websiteId` is set. */
|
|
1124
|
+
website?: boolean;
|
|
1125
|
+
};
|
|
1126
|
+
/**
|
|
1127
|
+
* Date pages without a front matter `date` by the git commit that added
|
|
1128
|
+
* their source file, following exact renames. Defaults to `false`.
|
|
1129
|
+
*/
|
|
1130
|
+
datePublished?: false | "git";
|
|
1100
1131
|
/**
|
|
1101
1132
|
* Meta tags written into every page's head, name to content: site
|
|
1102
1133
|
* verification tokens, `theme-color`, an app banner, and anything else
|
|
@@ -1136,7 +1167,10 @@ export interface SeoConfig {
|
|
|
1136
1167
|
/** RSS/Atom feeds. */
|
|
1137
1168
|
rss?: RssConfig;
|
|
1138
1169
|
/** Generate sitemap.xml (requires `deployment.site`). Defaults to `true`. */
|
|
1139
|
-
sitemap?: boolean
|
|
1170
|
+
sitemap?: boolean | {
|
|
1171
|
+
/** List each page's translations as hreflang links. Defaults to `false`. */
|
|
1172
|
+
alternates?: boolean;
|
|
1173
|
+
};
|
|
1140
1174
|
/**
|
|
1141
1175
|
* The documented product, added to the homepage's JSON-LD as a
|
|
1142
1176
|
* `SoftwareApplication` node. `true` takes every default (name and
|
|
@@ -104,6 +104,12 @@ export interface BlumeRoute {
|
|
|
104
104
|
/** True when this route renders fallback content for a missing translation. */
|
|
105
105
|
fallback: boolean;
|
|
106
106
|
hidden: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* The translations the page head links as hreflang alternates: the
|
|
109
|
+
* indexable ones, so a `noindex` or hidden translation is left out (see
|
|
110
|
+
* `hreflangAlternates`).
|
|
111
|
+
*/
|
|
112
|
+
hreflang: RouteAlternate[];
|
|
107
113
|
id: string;
|
|
108
114
|
/** Whether the page is part of the search index. */
|
|
109
115
|
indexable: boolean;
|
|
@@ -117,6 +123,12 @@ export interface BlumeRoute {
|
|
|
117
123
|
*/
|
|
118
124
|
monolingual: boolean;
|
|
119
125
|
path: string;
|
|
126
|
+
/**
|
|
127
|
+
* The git commit that added the page's source, as an ISO date, when
|
|
128
|
+
* `seo.datePublished` is `"git"` and front matter carries no date; else
|
|
129
|
+
* `null`.
|
|
130
|
+
*/
|
|
131
|
+
published: string | null;
|
|
120
132
|
title: string;
|
|
121
133
|
/** Resolved docs version (`""` for the current docs). */
|
|
122
134
|
version: string;
|
|
@@ -242,6 +254,7 @@ export interface BlumeDataConfig {
|
|
|
242
254
|
* kept out of this snapshot, which pages serialize into HTML.
|
|
243
255
|
*/
|
|
244
256
|
og: {
|
|
257
|
+
image?: string | Record<string, string>;
|
|
245
258
|
/**
|
|
246
259
|
* Site-wide card subtitle: `seo.og.description` (`false` omits it) over
|
|
247
260
|
* the site description. A page with its own description shows that
|
|
@@ -284,6 +297,7 @@ export interface BlumeDataConfig {
|
|
|
284
297
|
};
|
|
285
298
|
/** Deployment site URL, or `null` when none is configured/detected. */
|
|
286
299
|
site: string | null;
|
|
300
|
+
jsonLd: ResolvedConfig["seo"]["jsonLd"];
|
|
287
301
|
structuredData: boolean;
|
|
288
302
|
theme: ResolvedConfig["theme"];
|
|
289
303
|
title: string;
|
|
@@ -7,22 +7,31 @@ export interface ResolvedLastModified {
|
|
|
7
7
|
export declare const gitEnv: () => NodeJS.ProcessEnv;
|
|
8
8
|
/** Normalize the `lastModified` config (`false | "git" | "frontmatter"`) into `{ enabled, source }`. */
|
|
9
9
|
export declare const resolveLastModifiedConfig: (value: false | "git" | "frontmatter") => ResolvedLastModified;
|
|
10
|
+
/** Each file's git dates, keyed by path. */
|
|
11
|
+
export interface GitDates {
|
|
12
|
+
/** The committer ISO date of the newest commit that changed the file. */
|
|
13
|
+
modified: Map<string, string>;
|
|
14
|
+
/** The committer ISO date of the commit that added the file. */
|
|
15
|
+
published: Map<string, string>;
|
|
16
|
+
}
|
|
10
17
|
/**
|
|
11
|
-
* Parse `git log --format=%x00%cI --name-status -M100%` output into
|
|
12
|
-
* repo-root-relative path
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* ignored.
|
|
18
|
+
* Parse `git log --format=%x00%cI --name-status -M100%` output into each
|
|
19
|
+
* repo-root-relative path's dates. Each commit emits a NUL-prefixed date line
|
|
20
|
+
* followed by a status line per path it touched (`M\tpath`, `R100\told\tnew`);
|
|
21
|
+
* since git logs newest-first, the first date seen for a path is when it last
|
|
22
|
+
* changed, and the add (`A\tpath`) that ends its history is when it was
|
|
23
|
+
* published. Blank lines are ignored.
|
|
17
24
|
*
|
|
18
25
|
* A rename (`-M100%` reports only exact ones, where the content is unchanged)
|
|
19
26
|
* follows the file the way `git log --follow` does for one path: it dates
|
|
20
27
|
* nothing itself, and the older commits that name the old path date the file
|
|
21
28
|
* under its current name, so renaming `page.md` to `page.mdx` keeps the page's
|
|
22
|
-
*
|
|
23
|
-
* off the commits before it) takes the rename's date.
|
|
29
|
+
* dates. A file whose visible history starts at a rename (a shallow clone cut
|
|
30
|
+
* off the commits before it) takes the rename's date. Only exact renames are
|
|
31
|
+
* followed: `--follow`'s default 50% similarity would hand a new page the
|
|
32
|
+
* history of a similar one deleted in the same commit.
|
|
24
33
|
*/
|
|
25
|
-
export declare const parseGitLog: (output: string) =>
|
|
34
|
+
export declare const parseGitLog: (output: string) => GitDates;
|
|
26
35
|
/**
|
|
27
36
|
* `path` with every symlink resolved, the spelling git prints paths in: a
|
|
28
37
|
* project opened through a link (`/tmp/site` on macOS, where `/tmp` links to
|
|
@@ -41,17 +50,16 @@ export declare const realPath: (path: string) => string;
|
|
|
41
50
|
*/
|
|
42
51
|
export declare const gitRepositoryRoot: (root: string) => string | null;
|
|
43
52
|
/**
|
|
44
|
-
* Resolve each source file's
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* is unavailable or the project isn't a repo — the feature then simply shows
|
|
53
|
+
* Resolve each source file's git dates (see `parseGitLog`), keyed by absolute
|
|
54
|
+
* source path. Runs a single `git log` over the given content roots (each
|
|
55
|
+
* local source's own root, which may diverge from `content.root`), following
|
|
56
|
+
* renames within them (a file moved in from outside every root dates from the
|
|
57
|
+
* move), and maps repo-root-relative paths back to the given absolute paths
|
|
58
|
+
* (monorepo-safe via `rev-parse --show-toplevel`). Returns empty maps if git
|
|
59
|
+
* is unavailable or the project isn't a repo — the features then simply show
|
|
52
60
|
* no dates.
|
|
53
61
|
*/
|
|
54
|
-
export declare const
|
|
62
|
+
export declare const gitFileDates: (root: string, contentRoots: string[], sourcePaths: string[], repositoryRoot?: string | null) => GitDates;
|
|
55
63
|
/**
|
|
56
64
|
* Whether the repository containing `root` is a shallow clone. Returns false
|
|
57
65
|
* when git is unavailable or the project isn't a repo — those cases already
|
|
@@ -67,3 +75,10 @@ export declare const isShallowGitRepository: (root: string) => boolean;
|
|
|
67
75
|
* shallow.
|
|
68
76
|
*/
|
|
69
77
|
export declare const lastModifiedShallowWarning: (root: string, undatedCount: number) => Diagnostic[];
|
|
78
|
+
/**
|
|
79
|
+
* The warning for `seo.datePublished: "git"` in a shallow clone, where the
|
|
80
|
+
* oldest commit git can see is where the clone was cut, not where each page
|
|
81
|
+
* began. Git then dates no page rather than every page wrongly. Empty when
|
|
82
|
+
* every page has a front matter date.
|
|
83
|
+
*/
|
|
84
|
+
export declare const datePublishedShallowWarning: (undatedCount: number) => Diagnostic[];
|
|
@@ -33,6 +33,16 @@ export interface RelativeLinkBase {
|
|
|
33
33
|
* name (`./node.js` for `node.js.mdx`, `./v1.2`) is still a page link.
|
|
34
34
|
*/
|
|
35
35
|
export declare const resolveRelativeHref: (href: string, from: RelativeLinkBase, resolveFile?: (path: string) => string | undefined, hasRoute?: (route: string) => boolean) => string | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Where a relative page link in a raw HTML `<a href>` written on `route`
|
|
38
|
+
* lands, with the authored `?query#hash` kept, or `undefined` when `href`
|
|
39
|
+
* isn't a relative page link (see {@link resolveRelativeHref}). The Markdown
|
|
40
|
+
* pipeline leaves a raw element as written, so the browser resolves it
|
|
41
|
+
* against the page's slashless URL, as `blume validate` reads it: its parent
|
|
42
|
+
* directory, even on an index page, and a `.md` target is that path's
|
|
43
|
+
* Markdown copy rather than a file link.
|
|
44
|
+
*/
|
|
45
|
+
export declare const resolveRawRelativeHref: (href: string, route: string, hasRoute: (route: string) => boolean) => string | undefined;
|
|
36
46
|
/**
|
|
37
47
|
* Where a root-relative link to a content file (`/guide/new.md`, the way
|
|
38
48
|
* VitePress, Docsify, and TypeDoc write one) lands: the route of the source
|
|
@@ -96,6 +106,12 @@ export declare const buildFileRouteIndex: (pages: readonly PageRecord[], i18n: L
|
|
|
96
106
|
* tree's file at the same place.
|
|
97
107
|
*/
|
|
98
108
|
export declare const routeOfLinkedFile: (index: FileRouteIndex, from: FileLinkBase, path: string) => string | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* The route a file link written on a staged page lands on: the linked
|
|
111
|
+
* entry's, by its path under the staging dir (`entryId`), as the rendered
|
|
112
|
+
* link resolves it.
|
|
113
|
+
*/
|
|
114
|
+
export declare const routeOfLinkedEntry: (index: FileRouteIndex, entryId: string, path: string) => string | undefined;
|
|
99
115
|
/**
|
|
100
116
|
* Validate every link discovered in the content graph: internal page links and
|
|
101
117
|
* anchors against the route map, asset links against the public dir, and
|
|
@@ -4048,6 +4048,18 @@ export declare const blumeConfigSchema: z.ZodObject<{
|
|
|
4048
4048
|
}>>>>;
|
|
4049
4049
|
}, z.core.$strict>>>;
|
|
4050
4050
|
seo: z.ZodPrefault<z.ZodObject<{
|
|
4051
|
+
datePublished: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodLiteral<"git">]>>;
|
|
4052
|
+
jsonLd: z.ZodPrefault<z.ZodObject<{
|
|
4053
|
+
author: z.ZodOptional<z.ZodObject<{
|
|
4054
|
+
"@id": z.ZodURL;
|
|
4055
|
+
}, z.core.$strict>>;
|
|
4056
|
+
organizationId: z.ZodOptional<z.ZodURL>;
|
|
4057
|
+
publisher: z.ZodOptional<z.ZodObject<{
|
|
4058
|
+
"@id": z.ZodURL;
|
|
4059
|
+
}, z.core.$strict>>;
|
|
4060
|
+
website: z.ZodOptional<z.ZodBoolean>;
|
|
4061
|
+
websiteId: z.ZodOptional<z.ZodURL>;
|
|
4062
|
+
}, z.core.$strict>>;
|
|
4051
4063
|
metatags: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
4052
4064
|
og: z.ZodDefault<z.ZodObject<{
|
|
4053
4065
|
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
|
|
@@ -4071,6 +4083,7 @@ export declare const blumeConfigSchema: z.ZodObject<{
|
|
|
4071
4083
|
}>>;
|
|
4072
4084
|
weight: z.ZodOptional<z.ZodNumber>;
|
|
4073
4085
|
}, z.core.$strict>]>>>;
|
|
4086
|
+
image: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
4074
4087
|
logo: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
|
|
4075
4088
|
palette: z.ZodOptional<z.ZodObject<{
|
|
4076
4089
|
accent: z.ZodOptional<z.ZodString>;
|
|
@@ -4104,7 +4117,9 @@ export declare const blumeConfigSchema: z.ZodObject<{
|
|
|
4104
4117
|
limit: z.ZodDefault<z.ZodNumber>;
|
|
4105
4118
|
types: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
4106
4119
|
}, z.core.$strict>>;
|
|
4107
|
-
sitemap: z.ZodDefault<z.ZodBoolean
|
|
4120
|
+
sitemap: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
4121
|
+
alternates: z.ZodDefault<z.ZodBoolean>;
|
|
4122
|
+
}, z.core.$strict>]>>;
|
|
4108
4123
|
software: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
4109
4124
|
applicationCategory: z.ZodDefault<z.ZodString>;
|
|
4110
4125
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -245,6 +245,11 @@ export interface PageRecord {
|
|
|
245
245
|
unknownProps?: ElementUse[];
|
|
246
246
|
/** Resolved "last updated" ISO date, when the feature is enabled. */
|
|
247
247
|
lastModified?: string;
|
|
248
|
+
/**
|
|
249
|
+
* The git commit that added the source file, as an ISO date, when
|
|
250
|
+
* `seo.datePublished` is `"git"` and front matter carries no `date`.
|
|
251
|
+
*/
|
|
252
|
+
published?: string;
|
|
248
253
|
/** Absolute paths of files this page `<include>`s, transitively. Drives the
|
|
249
254
|
* dev-server invalidation edge from a partial to the pages that splice it. */
|
|
250
255
|
includes?: string[];
|
|
@@ -461,6 +466,11 @@ export interface RouteManifestEntry {
|
|
|
461
466
|
aiExclude?: boolean;
|
|
462
467
|
/** Resolved "last updated" ISO date, when the feature is enabled. */
|
|
463
468
|
lastModified?: string;
|
|
469
|
+
/**
|
|
470
|
+
* The git commit that added the source file, as an ISO date, when
|
|
471
|
+
* `seo.datePublished` is `"git"` and front matter carries no `date`.
|
|
472
|
+
*/
|
|
473
|
+
published?: string;
|
|
464
474
|
}
|
|
465
475
|
/** The generated runtime contract between core and the Astro project. */
|
|
466
476
|
export interface BlumeManifest {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BlumeProject } from "../core/project-graph.ts";
|
|
2
|
+
import type { RouteAlternate } from "../core/types.ts";
|
|
2
3
|
/** One emitted sitemap artifact: its dist-root filename and XML body. */
|
|
3
4
|
export interface SitemapFile {
|
|
4
5
|
name: string;
|
|
@@ -6,6 +7,14 @@ export interface SitemapFile {
|
|
|
6
7
|
}
|
|
7
8
|
/** The build log line for an emitted sitemap set: one file, or an index. */
|
|
8
9
|
export declare const describeSitemapFiles: (files: readonly SitemapFile[]) => string;
|
|
10
|
+
/**
|
|
11
|
+
* Each route's hreflang set, keyed by route: its indexable translations. The
|
|
12
|
+
* page head links it, and so does the sitemap under `seo.sitemap.alternates`,
|
|
13
|
+
* so the two never disagree, and neither points crawlers at a page they're
|
|
14
|
+
* told not to index. A page that can't be indexed joins no set — except an
|
|
15
|
+
* i18n fallback copy, which links the translations it stands in for.
|
|
16
|
+
*/
|
|
17
|
+
export declare const hreflangAlternates: (project: BlumeProject) => Map<string, RouteAlternate[]>;
|
|
9
18
|
/**
|
|
10
19
|
* Build the sitemap files from the route manifest plus the routes the manifest
|
|
11
20
|
* can't see: custom `.astro` pages (most importantly a custom landing `/`) and
|
|
@@ -79,7 +79,9 @@ interface BuildOptions {
|
|
|
79
79
|
* same serializers the `.md` mirror, llms-full.txt and MCP `get_page` use: a
|
|
80
80
|
* page whose body is a `<CardGroup>` of `<Card>`s is prose to a reader and bare
|
|
81
81
|
* JSX to anything reading the source, and section landing pages are exactly
|
|
82
|
-
* that shape.
|
|
82
|
+
* that shape. Its page links point at the pages they mean, as they do there
|
|
83
|
+
* too, as the routes the assistant's snapshot keys those pages by (see
|
|
84
|
+
* `relativeLinkRewriter`'s `assistant`): the model cites the links it reads.
|
|
83
85
|
*
|
|
84
86
|
* `audience` resolves `<Visibility>` blocks before extraction: `"web"`
|
|
85
87
|
* (default) keeps web-only content and drops agents-only blocks — the site
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Latin folding, shared by the search index and everything that finds a query
|
|
3
|
+
* in a page's text afterwards: the search dialog's highlights and excerpts,
|
|
4
|
+
* and the assistant's excerpts. The index matches Prüfung for `prufung`, so
|
|
5
|
+
* the rest must too, or a page found by folding shows its opening with
|
|
6
|
+
* nothing marked.
|
|
7
|
+
*/
|
|
8
|
+
/** `text` without its soft hyphens. */
|
|
9
|
+
export declare const stripSoftHyphens: (text: string) => string;
|
|
10
|
+
/**
|
|
11
|
+
* Fold lowercased text's Latin letters to the plain letters an unaccented
|
|
12
|
+
* query types: accents drop (café → cafe), letters NFD leaves whole are
|
|
13
|
+
* spelled out (Łódź → lodz, ışık and IŞIK → isik, Straße → strasse), and
|
|
14
|
+
* compatibility forms unpack (the fi ligature → fi, fullwidth API → api).
|
|
15
|
+
* Soft hyphens go too. Marks on any other script, and marks on no letter
|
|
16
|
+
* (the keycap in 1️⃣), stay.
|
|
17
|
+
*/
|
|
18
|
+
export declare const foldLatin: (lowered: string) => string;
|
|
19
|
+
/**
|
|
20
|
+
* {@link foldLatin} for the Latin letters of a lowercased term, whatever
|
|
21
|
+
* script the rest of it is in: a segmenter keeps caféनमस्ते together as one
|
|
22
|
+
* term. Only the Latin runs fold. Marks are spelling elsewhere (Thai vowels
|
|
23
|
+
* and tones; the breve that separates Cyrillic й from и), and NFD would split
|
|
24
|
+
* a Hangul syllable into its jamo.
|
|
25
|
+
*/
|
|
26
|
+
export declare const foldLatinTerm: (term: string) => string;
|
|
27
|
+
/**
|
|
28
|
+
* A regex source that finds `term` in unfolded text whatever accents, soft
|
|
29
|
+
* hyphens or spelled-out letters its Latin words carry there: `prufung`
|
|
30
|
+
* matches Prüfung, `strasse` matches Straße. Compile it with the `iu` flags.
|
|
31
|
+
* Characters outside Latin match as themselves.
|
|
32
|
+
*/
|
|
33
|
+
export declare const accentInsensitive: (term: string) => string;
|
|
@@ -34,10 +34,10 @@ export interface OramaDoc {
|
|
|
34
34
|
* Orama client loader (browser), the MCP server, and assistant grounding (Node),
|
|
35
35
|
* so ranking is identical wherever docs are queried. `locale` — the site's
|
|
36
36
|
* `i18n.defaultLocale` — swaps in a word-segmenting tokenizer for every
|
|
37
|
-
* non-Latin script, all of which
|
|
37
|
+
* non-Latin script, all of which {@link latinTokenizer} reduces to zero
|
|
38
38
|
* tokens. A non-Latin default's tokenizer serves every page: Latin words
|
|
39
39
|
* survive segmentation intact, so English pages on a segmented index stay
|
|
40
|
-
* searchable. A Latin default keeps
|
|
40
|
+
* searchable. A Latin default keeps {@link latinTokenizer} for its Latin-script
|
|
41
41
|
* pages, and each page in a non-Latin locale (the Japanese and Hindi
|
|
42
42
|
* translations of an English site) is indexed with its own locale's tokenizer.
|
|
43
43
|
*/
|
|
@@ -68,7 +68,7 @@ export interface OramaQueryFilters {
|
|
|
68
68
|
* On an index whose translations have tokenizers of their own, a query scoped
|
|
69
69
|
* to a locale is tokenized with that locale's tokenizer. An unscoped query
|
|
70
70
|
* searches each locale's pages with its own tokenizer, and the Latin-script
|
|
71
|
-
* pages with
|
|
72
|
-
* the one index, so their scores share its term statistics.
|
|
71
|
+
* pages with {@link latinTokenizer}, then merges the matches by score: every
|
|
72
|
+
* search runs over the one index, so their scores share its term statistics.
|
|
73
73
|
*/
|
|
74
74
|
export declare const queryOramaIndex: (db: AnyOrama, term: string, limit: number, filters?: OramaQueryFilters) => Promise<OramaDoc[]>;
|
|
@@ -53,8 +53,41 @@ export interface StructuredDataIdentity {
|
|
|
53
53
|
organization?: OrganizationIdentity;
|
|
54
54
|
software?: SoftwareIdentity;
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* `seo.jsonLd`: entities the docs share with a site they live inside
|
|
58
|
+
* (`example.com/docs`), referenced by `@id` instead of defined again.
|
|
59
|
+
*/
|
|
60
|
+
export interface JsonLdEntities {
|
|
61
|
+
/** Credited on pages without their own `authors`. */
|
|
62
|
+
author?: {
|
|
63
|
+
"@id": string;
|
|
64
|
+
};
|
|
65
|
+
/** Cited as every page's publisher in place of the Organization's id. */
|
|
66
|
+
publisher?: {
|
|
67
|
+
"@id": string;
|
|
68
|
+
};
|
|
69
|
+
/** The Organization's `@id`, defined here or elsewhere. */
|
|
70
|
+
organizationId?: string;
|
|
71
|
+
/** Emit the WebSite node. Defaults to true unless `websiteId` is set. */
|
|
72
|
+
website?: boolean;
|
|
73
|
+
/** The WebSite's `@id`, which every page names as `isPartOf`. */
|
|
74
|
+
websiteId?: string;
|
|
75
|
+
}
|
|
76
|
+
/** A front matter `authors` entry: a name, or a name with a profile URL. */
|
|
77
|
+
export type AuthorInput = string | {
|
|
78
|
+
name: string;
|
|
79
|
+
url?: string;
|
|
80
|
+
};
|
|
56
81
|
/** Inputs for a page's JSON-LD, all known at render time in RootLayout. */
|
|
57
82
|
export interface StructuredDataInput {
|
|
83
|
+
jsonLd?: JsonLdEntities;
|
|
84
|
+
/**
|
|
85
|
+
* The page's `og:image`, emitted as the page node's `image`. Absolute when
|
|
86
|
+
* `siteUrl` is set, otherwise root-relative like every other URL here.
|
|
87
|
+
*/
|
|
88
|
+
image?: string | null;
|
|
89
|
+
/** The page's own byline, which wins over `jsonLd.author`. */
|
|
90
|
+
authors?: AuthorInput | AuthorInput[];
|
|
58
91
|
siteName: string;
|
|
59
92
|
/** Absolute site origin, or null when `deployment.site` is unset. */
|
|
60
93
|
siteUrl: string | null;
|
|
@@ -149,7 +149,7 @@ search: orama(),
|
|
|
149
149
|
|
|
150
150
|
#### Non-Latin scripts
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
The standard tokenizer keeps only Latin letters and digits, so text in any other script — Japanese, Chinese, Korean and Thai, but equally Russian, Greek, Hebrew and Hindi — would otherwise produce no matches at all. Blume handles this for you: pages in a locale that resolves to a non-Latin script are indexed with a word-segmenting tokenizer (built on the browser- and Node-native `Intl.Segmenter`). Declaring your site's languages is all it takes:
|
|
153
153
|
|
|
154
154
|
```ts blume.config.ts lineNumbers
|
|
155
155
|
i18n: {
|
|
@@ -158,7 +158,7 @@ i18n: {
|
|
|
158
158
|
}
|
|
159
159
|
```
|
|
160
160
|
|
|
161
|
-
The same tokenizers serve the search dialog, the MCP server's `search_docs` tool, and assistant grounding. The script is what decides, not the language name — `az-Cyrl` is segmented while `sr-Latn` is not. With a non-Latin default, every page shares the default locale's tokenizer: Latin words survive segmentation intact, so pages in English stay searchable alongside the default language. With a Latin default, Latin-script pages keep the standard tokenizer and each translation in a non-Latin script gets its own locale's, so an English site's Japanese and Hindi pages are searchable from their own language and from a search across every language.
|
|
161
|
+
The same tokenizers serve the search dialog, the MCP server's `search_docs` tool, and assistant grounding. The script is what decides, not the language name — `az-Cyrl` is segmented while `sr-Latn` is not. With a non-Latin default, every page shares the default locale's tokenizer: Latin words survive segmentation intact, so pages in English stay searchable alongside the default language. With a Latin default, Latin-script pages keep the standard tokenizer and each translation in a non-Latin script gets its own locale's, so an English site's Japanese and Hindi pages are searchable from their own language and from a search across every language. The standard tokenizer strips accents and spells out letters that have none to strip (ø as o, ł as l, ß as ss), so `cafe` finds café and `lodz` finds Łódź, and the search dialog and the assistant's excerpts find the accented word in the page too. Where accents tell words apart (Swedish ändra and andra, Vietnamese tones), a query also matches words that differ from it only in those accents.
|
|
162
162
|
|
|
163
163
|
Japanese and Chinese go one step further. Segmenting alone indexes a compound term as its parts — 資金決済法 as 資金, 決済 and 法 — which lets a page mentioning each part somewhere outrank the page the term is actually about. Han, Hiragana and Katakana are therefore indexed as overlapping character pairs, and queries on those indexes prefer pages carrying a term's pairs together, loosening to any-pair matching when no page carries them all, so typing a whole sentence still returns its closest pages. Korean and Thai keep their segmented words.
|
|
164
164
|
|