blume 0.7.0 → 1.0.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/CHANGELOG.md +666 -0
- package/LICENSE +21 -0
- package/README.md +107 -0
- package/dist/cli/index.js +1852 -380
- package/dist/cli/index.js.map +98 -91
- package/dist/types/ai/component-markdown.d.ts +34 -0
- package/dist/types/components/content/youtube.d.ts +18 -0
- package/dist/types/core/base-path.d.ts +9 -0
- package/dist/types/core/config-input.d.ts +47 -2
- package/dist/types/core/config.d.ts +3 -2
- package/dist/types/core/data.d.ts +7 -0
- package/dist/types/core/i18n-ui.d.ts +526 -132
- package/dist/types/core/schema.d.ts +293 -146
- package/dist/types/index.d.ts +1 -0
- package/dist/types/openapi/references.d.ts +60 -0
- package/dist/types/seo/x-handle.d.ts +12 -0
- package/docs/01-quickstart.mdx +5 -2
- package/docs/02-deployment.mdx +8 -8
- package/docs/03-faq.mdx +46 -16
- package/docs/advanced/api-reference.mdx +1 -1
- package/docs/advanced/changelog.mdx +1 -1
- package/docs/advanced/custom-pages.mdx +1 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/configuration/ai.mdx +49 -10
- package/docs/configuration/customization.mdx +11 -0
- package/docs/configuration/export.mdx +1 -1
- package/docs/configuration/index.mdx +27 -3
- package/docs/configuration/seo.mdx +35 -5
- package/docs/content/components.mdx +2 -2
- package/docs/content/i18n.mdx +1 -1
- package/docs/content/navigation.mdx +3 -3
- package/docs/content/sources.mdx +1 -1
- package/docs/content/syntax.mdx +6 -4
- package/docs/index.mdx +2 -2
- package/docs/reference/cli.mdx +9 -7
- package/docs/reference/frontmatter.mdx +1 -1
- package/package.json +22 -4
- package/skills/blume/SKILL.md +5 -3
- package/skills/blume-update-docs/SKILL.md +3 -2
- package/src/ai/agent-readability.ts +9 -8
- package/src/ai/ask-context.ts +7 -2
- package/src/ai/ask-data.ts +3 -0
- package/src/ai/component-markdown.ts +461 -0
- package/src/ai/llms.ts +135 -26
- package/src/ai/markdown.ts +35 -6
- package/src/ai/mcp/data.ts +25 -4
- package/src/ai/mcp/discovery.ts +10 -3
- package/src/ai/mcp/server.ts +21 -7
- package/src/ai/mcp/tools.ts +1 -1
- package/src/ai/visibility.ts +74 -0
- package/src/astro/component-slots.ts +11 -1
- package/src/astro/generate.ts +77 -45
- package/src/astro/integration.ts +1 -1
- package/src/astro/markdown-negotiation.ts +1 -1
- package/src/astro/pages.ts +81 -19
- package/src/astro/templates.ts +150 -19
- package/src/blume-modules.d.ts +8 -0
- package/src/cli/commands/build.ts +120 -23
- package/src/cli/commands/check.ts +1 -1
- package/src/cli/commands/dev.ts +26 -5
- package/src/cli/commands/eject.ts +47 -19
- package/src/cli/commands/init.ts +120 -180
- package/src/cli/commands/preview.ts +4 -1
- package/src/cli/commands/validate.ts +43 -2
- package/src/cli/dev-lock.ts +8 -4
- package/src/cli/eject-scripts.ts +72 -0
- package/src/cli/env.ts +15 -5
- package/src/cli/init/questions.ts +158 -0
- package/src/cli/init/scaffold.ts +380 -0
- package/src/cli/internal-error.ts +9 -4
- package/src/cli/prepare.ts +3 -2
- package/src/components/Icon.astro +2 -1
- package/src/components/content/AccordionItem.astro +23 -4
- package/src/components/content/Badge.astro +3 -1
- package/src/components/content/Card.astro +4 -2
- package/src/components/content/Step.astro +10 -1
- package/src/components/content/Tabs.astro +15 -3
- package/src/components/content/Tile.astro +2 -1
- package/src/components/content/Tooltip.astro +3 -1
- package/src/components/content/Update.astro +9 -2
- package/src/components/content/auto-type-table.ts +7 -1
- package/src/components/content/base-href.ts +33 -0
- package/src/components/content/changelog-element.ts +9 -2
- package/src/components/content/mermaid-element.ts +7 -2
- package/src/components/islands/AskAI.astro +5 -2
- package/src/components/islands/ask-ai.tsx +86 -11
- package/src/components/islands/hooks.ts +28 -8
- package/src/components/layout/Banner.astro +10 -2
- package/src/components/layout/Breadcrumbs.astro +11 -2
- package/src/components/layout/Header.astro +13 -4
- package/src/components/layout/Logo.astro +11 -3
- package/src/components/layout/NavTree.astro +19 -5
- package/src/components/layout/PageActions.astro +25 -10
- package/src/components/layout/PageLayout.astro +85 -9
- package/src/components/layout/Pagination.astro +10 -4
- package/src/components/layout/ReferenceLayout.astro +20 -2
- package/src/components/layout/RootLayout.astro +142 -12
- package/src/components/layout/Search.astro +117 -27
- package/src/components/layout/search/algolia.ts +11 -2
- package/src/components/layout/search/endpoint.ts +11 -5
- package/src/components/layout/search/orama-cloud.ts +8 -2
- package/src/components/layout/search/types.ts +5 -1
- package/src/components/layout/search/typesense.ts +4 -1
- package/src/components/layout/toc-element.ts +1 -1
- package/src/components/openapi/ApiTagOperations.astro +2 -1
- package/src/components/openapi/Operation.astro +47 -40
- package/src/components/openapi/RequestPanel.astro +1 -1
- package/src/components/openapi/helpers.ts +71 -3
- package/src/components/openapi/panel.ts +1 -1
- package/src/core/base-path.ts +24 -0
- package/src/core/builtin-tags.ts +2 -0
- package/src/core/config-input.ts +48 -2
- package/src/core/config.ts +3 -2
- package/src/core/data.ts +4 -0
- package/src/core/frontmatter.ts +7 -0
- package/src/core/graph.ts +15 -5
- package/src/core/i18n-ui.ts +54 -0
- package/src/core/i18n.ts +16 -8
- package/src/core/last-modified.ts +13 -6
- package/src/core/links.ts +32 -8
- package/src/core/navigation.ts +29 -4
- package/src/core/package-json.ts +17 -2
- package/src/core/project-graph.ts +15 -6
- package/src/core/schema.ts +71 -2
- package/src/core/sources/assets.ts +6 -1
- package/src/core/sources/filesystem.ts +4 -0
- package/src/core/sources/mdx-remote.ts +23 -14
- package/src/core/sources/normalize.ts +152 -50
- package/src/core/sources/notion.ts +8 -8
- package/src/core/ui-packs/ar.ts +8 -0
- package/src/core/ui-packs/bg.ts +8 -0
- package/src/core/ui-packs/bn.ts +8 -0
- package/src/core/ui-packs/ca.ts +8 -0
- package/src/core/ui-packs/cs.ts +8 -0
- package/src/core/ui-packs/da.ts +8 -0
- package/src/core/ui-packs/de.ts +8 -0
- package/src/core/ui-packs/el.ts +8 -0
- package/src/core/ui-packs/es.ts +8 -0
- package/src/core/ui-packs/fa.ts +8 -0
- package/src/core/ui-packs/fi.ts +8 -0
- package/src/core/ui-packs/fr.ts +9 -1
- package/src/core/ui-packs/he.ts +8 -0
- package/src/core/ui-packs/hi.ts +8 -0
- package/src/core/ui-packs/hr.ts +8 -0
- package/src/core/ui-packs/hu.ts +8 -0
- package/src/core/ui-packs/id.ts +8 -0
- package/src/core/ui-packs/it.ts +8 -0
- package/src/core/ui-packs/ja.ts +8 -0
- package/src/core/ui-packs/ko.ts +8 -0
- package/src/core/ui-packs/nl.ts +8 -0
- package/src/core/ui-packs/no.ts +8 -0
- package/src/core/ui-packs/pl.ts +8 -0
- package/src/core/ui-packs/pt-br.ts +8 -0
- package/src/core/ui-packs/pt.ts +8 -0
- package/src/core/ui-packs/ro.ts +8 -0
- package/src/core/ui-packs/ru.ts +8 -0
- package/src/core/ui-packs/sk.ts +8 -0
- package/src/core/ui-packs/sr.ts +8 -0
- package/src/core/ui-packs/sv.ts +8 -0
- package/src/core/ui-packs/th.ts +8 -0
- package/src/core/ui-packs/tr.ts +8 -0
- package/src/core/ui-packs/uk.ts +8 -0
- package/src/core/ui-packs/vi.ts +8 -0
- package/src/core/ui-packs/zh-tw.ts +8 -0
- package/src/core/ui-packs/zh.ts +8 -0
- package/src/deploy/adapter-output.ts +18 -8
- package/src/deploy/redirects.ts +7 -2
- package/src/deploy/sitemap.ts +53 -11
- package/src/index.ts +5 -0
- package/src/markdown/base-links.ts +10 -8
- package/src/markdown/index.ts +15 -3
- package/src/markdown/inline-code.ts +7 -2
- package/src/markdown/package-commands.ts +10 -4
- package/src/og/card.ts +4 -2
- package/src/og/dimensions.ts +12 -0
- package/src/openapi/model.ts +12 -4
- package/src/openapi/parse.ts +21 -0
- package/src/openapi/references.ts +38 -8
- package/src/openapi/render-mdx.ts +62 -1
- package/src/openapi/source.ts +59 -10
- package/src/registry/eject.ts +184 -12
- package/src/registry/registry.ts +0 -3
- package/src/search/documents.ts +34 -2
- package/src/seo/jsonld.ts +20 -13
- package/src/seo/x-handle.ts +18 -0
package/dist/cli/index.js
CHANGED
|
@@ -48,7 +48,6 @@ import { dirname as dirname3, join as join4 } from "pathe";
|
|
|
48
48
|
// src/registry/registry.ts
|
|
49
49
|
import { join as join3 } from "pathe";
|
|
50
50
|
var packageSrc = join3(packageRoot(), "src");
|
|
51
|
-
var itemsRoot = join3(packageRoot(), "src", "registry", "items");
|
|
52
51
|
var layoutComponent = (config) => {
|
|
53
52
|
const target = `components/blume/${config.file}`;
|
|
54
53
|
return {
|
|
@@ -663,14 +662,17 @@ var buildAgentReadability = (project) => {
|
|
|
663
662
|
}
|
|
664
663
|
const site = config.deployment.site ?? null;
|
|
665
664
|
const deployBase = normalizeBasePath(config.deployment.base);
|
|
666
|
-
const abs = (path) =>
|
|
665
|
+
const abs = (path) => {
|
|
666
|
+
const based = withBasePath(deployBase, path);
|
|
667
|
+
return site ? `${site.replace(/\/+$/u, "")}${based}` : based;
|
|
668
|
+
};
|
|
667
669
|
const artifacts = {
|
|
668
670
|
markdown: {
|
|
669
671
|
contentNegotiation: "text/markdown",
|
|
670
672
|
pattern: abs("/{route}.md")
|
|
671
673
|
}
|
|
672
674
|
};
|
|
673
|
-
if (config.ai.llmsTxt) {
|
|
675
|
+
if (config.ai.llmsTxt.enabled) {
|
|
674
676
|
artifacts.llmsFullTxt = abs("/llms-full.txt");
|
|
675
677
|
artifacts.llmsTxt = abs("/llms.txt");
|
|
676
678
|
}
|
|
@@ -723,6 +725,7 @@ var withYamlEngine = (options) => ({
|
|
|
723
725
|
}
|
|
724
726
|
});
|
|
725
727
|
var matter = Object.assign((input, options) => baseMatter(input, withYamlEngine(options)), baseMatter, {
|
|
728
|
+
read: (filepath, options) => baseMatter.read(filepath, withYamlEngine(options)),
|
|
726
729
|
stringify: (file, data, options) => baseMatter.stringify(file, data, withYamlEngine(options))
|
|
727
730
|
});
|
|
728
731
|
var frontmatter_default = matter;
|
|
@@ -744,37 +747,376 @@ var readEntryText = async (ctx, page) => {
|
|
|
744
747
|
return "";
|
|
745
748
|
};
|
|
746
749
|
|
|
750
|
+
// src/ai/component-markdown.ts
|
|
751
|
+
import { mdxToMdast } from "satteri";
|
|
752
|
+
|
|
753
|
+
// src/components/content/youtube.ts
|
|
754
|
+
var BARE_ID = /^[\w-]{11}$/u;
|
|
755
|
+
var URL_ID = /(?:youtu\.be\/|\/embed\/|\/shorts\/|\/live\/|[?&]v=)(?<id>[\w-]{11})/u;
|
|
756
|
+
var parseYouTubeId = (input) => {
|
|
757
|
+
const value = input.trim();
|
|
758
|
+
if (!value) {
|
|
759
|
+
return null;
|
|
760
|
+
}
|
|
761
|
+
if (BARE_ID.test(value)) {
|
|
762
|
+
return value;
|
|
763
|
+
}
|
|
764
|
+
return URL_ID.exec(value)?.groups?.id ?? null;
|
|
765
|
+
};
|
|
766
|
+
|
|
767
|
+
// src/ai/component-markdown.ts
|
|
768
|
+
var evaluateExpression = (raw) => {
|
|
769
|
+
try {
|
|
770
|
+
const value = new Function(`"use strict"; return (${raw});`)();
|
|
771
|
+
return { ok: true, value };
|
|
772
|
+
} catch {
|
|
773
|
+
return { ok: false, value: undefined };
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
var readProps = (node) => {
|
|
777
|
+
const props = {};
|
|
778
|
+
let lossy = false;
|
|
779
|
+
for (const attribute of node.attributes ?? []) {
|
|
780
|
+
if (attribute.type !== "mdxJsxAttribute" || !attribute.name) {
|
|
781
|
+
lossy = true;
|
|
782
|
+
continue;
|
|
783
|
+
}
|
|
784
|
+
if (attribute.value === null || attribute.value === undefined) {
|
|
785
|
+
props[attribute.name] = true;
|
|
786
|
+
} else if (typeof attribute.value === "string") {
|
|
787
|
+
props[attribute.name] = attribute.value;
|
|
788
|
+
} else {
|
|
789
|
+
const result = evaluateExpression(attribute.value.value);
|
|
790
|
+
if (result.ok) {
|
|
791
|
+
props[attribute.name] = result.value;
|
|
792
|
+
} else {
|
|
793
|
+
lossy = true;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
return { lossy, props };
|
|
798
|
+
};
|
|
799
|
+
var hasOffsets = (node) => typeof node.position?.start?.offset === "number" && typeof node.position?.end?.offset === "number";
|
|
800
|
+
var applySplices = (text, splices) => {
|
|
801
|
+
let result = text;
|
|
802
|
+
for (const splice of [...splices].toSorted((a, b) => b.start - a.start)) {
|
|
803
|
+
const lineStart = result.lastIndexOf(`
|
|
804
|
+
`, splice.start - 1) + 1;
|
|
805
|
+
const prefix = result.slice(lineStart, splice.start);
|
|
806
|
+
const indent = /^[\t ]+$/u.test(prefix) ? prefix : "";
|
|
807
|
+
const replacement = indent ? splice.text.split(`
|
|
808
|
+
`).map((line, index) => index === 0 || line === "" ? line : `${indent}${line}`).join(`
|
|
809
|
+
`) : splice.text;
|
|
810
|
+
result = result.slice(0, splice.start) + replacement + result.slice(splice.end);
|
|
811
|
+
}
|
|
812
|
+
return result;
|
|
813
|
+
};
|
|
814
|
+
var dedent = (text) => {
|
|
815
|
+
const lines = text.split(`
|
|
816
|
+
`);
|
|
817
|
+
const rest = lines.slice(1).filter((line) => line.trim() !== "");
|
|
818
|
+
if (rest.length === 0) {
|
|
819
|
+
return text;
|
|
820
|
+
}
|
|
821
|
+
const indent = Math.min(...rest.map((line) => line.length - line.trimStart().length));
|
|
822
|
+
if (indent === 0) {
|
|
823
|
+
return text;
|
|
824
|
+
}
|
|
825
|
+
return [
|
|
826
|
+
lines[0],
|
|
827
|
+
...lines.slice(1).map((line) => line.trim() === "" ? "" : line.slice(indent))
|
|
828
|
+
].join(`
|
|
829
|
+
`);
|
|
830
|
+
};
|
|
831
|
+
var isJsxElement = (node) => node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement";
|
|
832
|
+
var cellText = (value) => String(value ?? "").replaceAll(/\s*\n\s*/gu, " ").replaceAll("|", "\\|").trim();
|
|
833
|
+
var cellCode = (value) => {
|
|
834
|
+
const text = cellText(value);
|
|
835
|
+
return text && !text.includes("`") ? `\`${text}\`` : text;
|
|
836
|
+
};
|
|
837
|
+
var typeTable = ({ children, props }) => {
|
|
838
|
+
const { type } = props;
|
|
839
|
+
if (type === null || typeof type !== "object") {
|
|
840
|
+
return null;
|
|
841
|
+
}
|
|
842
|
+
const entries = Object.entries(type);
|
|
843
|
+
const rows = entries.map(([name, info]) => {
|
|
844
|
+
const prop = cellCode(`${name}${info.required ? "" : "?"}`);
|
|
845
|
+
const typeCell = info.typeDescriptionLink ? `[${cellCode(info.type)}](${cellText(info.typeDescriptionLink)})` : cellCode(info.type);
|
|
846
|
+
const defaultCell = info.default === undefined ? "-" : cellCode(info.default);
|
|
847
|
+
const description = cellText([info.description, info.typeDescription].filter((part) => typeof part === "string" && part !== "").join(" "));
|
|
848
|
+
return `| ${prop} | ${typeCell} | ${defaultCell} | ${description} |`;
|
|
849
|
+
});
|
|
850
|
+
const table = rows.length > 0 ? [
|
|
851
|
+
"| Prop | Type | Default | Description |",
|
|
852
|
+
"| --- | --- | --- | --- |",
|
|
853
|
+
...rows
|
|
854
|
+
].join(`
|
|
855
|
+
`) : "";
|
|
856
|
+
return [table, children].filter(Boolean).join(`
|
|
857
|
+
|
|
858
|
+
`);
|
|
859
|
+
};
|
|
860
|
+
var callout = ({ children, props }) => {
|
|
861
|
+
const type = typeof props.type === "string" ? props.type : "info";
|
|
862
|
+
const label = typeof props.title === "string" && props.title !== "" ? props.title : type.charAt(0).toUpperCase() + type.slice(1);
|
|
863
|
+
if (!children) {
|
|
864
|
+
return `> **${label}**`;
|
|
865
|
+
}
|
|
866
|
+
const body = children.split(`
|
|
867
|
+
`).map((line) => line.trim() === "" ? ">" : `> ${line}`).join(`
|
|
868
|
+
`);
|
|
869
|
+
return `> **${label}**
|
|
870
|
+
>
|
|
871
|
+
${body}`;
|
|
872
|
+
};
|
|
873
|
+
var listItem = (index, content) => {
|
|
874
|
+
const marker = `${index}. `;
|
|
875
|
+
return content.split(`
|
|
876
|
+
`).map((line, lineIndex) => {
|
|
877
|
+
if (lineIndex === 0) {
|
|
878
|
+
return `${marker}${line}`;
|
|
879
|
+
}
|
|
880
|
+
return line === "" ? "" : ` ${line}`;
|
|
881
|
+
}).join(`
|
|
882
|
+
`);
|
|
883
|
+
};
|
|
884
|
+
var steps = ({ childComponents, children }) => {
|
|
885
|
+
const items = childComponents("Step");
|
|
886
|
+
if (items.length === 0) {
|
|
887
|
+
return children;
|
|
888
|
+
}
|
|
889
|
+
return items.map((step, index) => {
|
|
890
|
+
const title = typeof step.props.title === "string" && step.props.title !== "" ? `**${step.props.title}**` : "";
|
|
891
|
+
const content = [title, step.children].filter(Boolean).join(`
|
|
892
|
+
|
|
893
|
+
`);
|
|
894
|
+
return listItem(index + 1, content);
|
|
895
|
+
}).join(`
|
|
896
|
+
|
|
897
|
+
`);
|
|
898
|
+
};
|
|
899
|
+
var tabs = ({ childComponents, children }) => {
|
|
900
|
+
const items = childComponents("Tab");
|
|
901
|
+
if (items.length === 0) {
|
|
902
|
+
return children;
|
|
903
|
+
}
|
|
904
|
+
return items.map((tab, index) => {
|
|
905
|
+
const title = typeof tab.props.title === "string" && tab.props.title !== "" ? tab.props.title : `Tab ${index + 1}`;
|
|
906
|
+
return tab.children ? `**${title}**
|
|
907
|
+
|
|
908
|
+
${tab.children}` : `**${title}**`;
|
|
909
|
+
}).join(`
|
|
910
|
+
|
|
911
|
+
`);
|
|
912
|
+
};
|
|
913
|
+
var youtube = ({ props }) => {
|
|
914
|
+
let input = "";
|
|
915
|
+
if (typeof props.id === "string") {
|
|
916
|
+
input = props.id;
|
|
917
|
+
} else if (typeof props.url === "string") {
|
|
918
|
+
input = props.url;
|
|
919
|
+
}
|
|
920
|
+
const videoId = parseYouTubeId(input);
|
|
921
|
+
if (!videoId) {
|
|
922
|
+
return null;
|
|
923
|
+
}
|
|
924
|
+
const start = typeof props.start === "number" && props.start > 0 ? `&t=${Math.floor(props.start)}s` : "";
|
|
925
|
+
const title = typeof props.title === "string" && props.title !== "" ? props.title : "Watch on YouTube";
|
|
926
|
+
return `[${title}](https://www.youtube.com/watch?v=${videoId}${start})`;
|
|
927
|
+
};
|
|
928
|
+
var SERIALIZERS = {
|
|
929
|
+
Callout: callout,
|
|
930
|
+
Steps: steps,
|
|
931
|
+
Tabs: tabs,
|
|
932
|
+
TypeTable: typeTable,
|
|
933
|
+
YouTube: youtube
|
|
934
|
+
};
|
|
935
|
+
var escapeRegExp2 = (value) => value.replaceAll(/[$()*+.?[\\\]^{|}]/gu, String.raw`\$&`);
|
|
936
|
+
var componentHint = (registry2) => new RegExp(`<(?:${Object.keys(registry2).map(escapeRegExp2).join("|")})[\\s/>]`, "u");
|
|
937
|
+
var BUILT_IN_HINT = componentHint(SERIALIZERS);
|
|
938
|
+
var renderChildren = (walk, node) => {
|
|
939
|
+
const children = (node.children ?? []).filter(hasOffsets);
|
|
940
|
+
const [first] = children;
|
|
941
|
+
if (!first) {
|
|
942
|
+
return "";
|
|
943
|
+
}
|
|
944
|
+
const start = first.position.start.offset;
|
|
945
|
+
const end = children.at(-1)?.position.end.offset ?? start;
|
|
946
|
+
const splices = [];
|
|
947
|
+
collectSplices(walk, children, splices);
|
|
948
|
+
const spliced = applySplices(walk.source.slice(start, end), splices.map((splice) => ({
|
|
949
|
+
...splice,
|
|
950
|
+
end: splice.end - start,
|
|
951
|
+
start: splice.start - start
|
|
952
|
+
})));
|
|
953
|
+
return dedent(spliced).trim();
|
|
954
|
+
};
|
|
955
|
+
var serializeElement = (serializer, walk, node) => serializer({
|
|
956
|
+
...readProps(node),
|
|
957
|
+
childComponents: (name) => (node.children ?? []).filter((child) => isJsxElement(child) && child.name === name).map((child) => ({
|
|
958
|
+
...readProps(child),
|
|
959
|
+
children: renderChildren(walk, child)
|
|
960
|
+
})),
|
|
961
|
+
children: renderChildren(walk, node)
|
|
962
|
+
});
|
|
963
|
+
var collectSplices = (walk, nodes, out) => {
|
|
964
|
+
for (const node of nodes) {
|
|
965
|
+
const serializer = node.type === "mdxJsxFlowElement" && node.name ? walk.registry[node.name] : undefined;
|
|
966
|
+
if (serializer && hasOffsets(node)) {
|
|
967
|
+
const text = serializeElement(serializer, walk, node);
|
|
968
|
+
if (text !== null) {
|
|
969
|
+
out.push({
|
|
970
|
+
end: node.position.end.offset,
|
|
971
|
+
start: node.position.start.offset,
|
|
972
|
+
text
|
|
973
|
+
});
|
|
974
|
+
continue;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
collectSplices(walk, node.children ?? [], out);
|
|
978
|
+
}
|
|
979
|
+
};
|
|
980
|
+
var downlevelComponents = (source, components) => {
|
|
981
|
+
const custom = components && Object.keys(components).length > 0;
|
|
982
|
+
const registry2 = custom ? { ...SERIALIZERS, ...components } : SERIALIZERS;
|
|
983
|
+
const hint = custom ? componentHint(registry2) : BUILT_IN_HINT;
|
|
984
|
+
if (!hint.test(source)) {
|
|
985
|
+
return source;
|
|
986
|
+
}
|
|
987
|
+
let tree;
|
|
988
|
+
try {
|
|
989
|
+
tree = mdxToMdast(source);
|
|
990
|
+
} catch {
|
|
991
|
+
return source;
|
|
992
|
+
}
|
|
993
|
+
const splices = [];
|
|
994
|
+
collectSplices({ registry: registry2, source }, tree.children ?? [], splices);
|
|
995
|
+
return splices.length > 0 ? applySplices(source, splices) : source;
|
|
996
|
+
};
|
|
997
|
+
|
|
998
|
+
// src/ai/visibility.ts
|
|
999
|
+
var CODE_FENCE_BLOCK = /^(?<fence>`{3,}|~{3,})[^\n]*\n[\s\S]*?^\k<fence>[^\n]*(?=\n|$)/gmu;
|
|
1000
|
+
var FENCE_TOKEN = /\u0000blume-fence-(?<index>\d+)\u0000/gu;
|
|
1001
|
+
var visibilityBlock = (audience) => new RegExp(`<Visibility\\s+for\\s*=\\s*(?:"${audience}"|'${audience}')\\s*>(?<inner>[\\s\\S]*?)</Visibility\\s*>`, "gu");
|
|
1002
|
+
var BLOCKS = {
|
|
1003
|
+
agents: visibilityBlock("agents"),
|
|
1004
|
+
web: visibilityBlock("web")
|
|
1005
|
+
};
|
|
1006
|
+
var applyAudienceVisibility = (markdown, audience) => {
|
|
1007
|
+
const fences = [];
|
|
1008
|
+
const masked = markdown.replace(CODE_FENCE_BLOCK, (block) => {
|
|
1009
|
+
fences.push(block);
|
|
1010
|
+
return `\x00blume-fence-${fences.length - 1}\x00`;
|
|
1011
|
+
});
|
|
1012
|
+
let touched = false;
|
|
1013
|
+
const filtered = masked.replaceAll(BLOCKS[audience === "agents" ? "web" : "agents"], () => {
|
|
1014
|
+
touched = true;
|
|
1015
|
+
return "";
|
|
1016
|
+
}).replaceAll(BLOCKS[audience], (_match, inner) => {
|
|
1017
|
+
touched = true;
|
|
1018
|
+
return inner;
|
|
1019
|
+
});
|
|
1020
|
+
const tidied = touched ? filtered.replaceAll(/\n{3,}/gu, `
|
|
1021
|
+
|
|
1022
|
+
`) : filtered;
|
|
1023
|
+
return tidied.replaceAll(FENCE_TOKEN, (token, index) => fences[Number(index)] ?? token);
|
|
1024
|
+
};
|
|
1025
|
+
var applyAgentVisibility = (markdown) => applyAudienceVisibility(markdown, "agents");
|
|
1026
|
+
|
|
747
1027
|
// src/ai/llms.ts
|
|
748
1028
|
var pageUrl = (route, site, base = "") => {
|
|
749
|
-
|
|
750
|
-
|
|
1029
|
+
const path = withBasePath(base, route);
|
|
1030
|
+
return encodeURI(site ? `${site.replace(/\/$/u, "")}${path}` : path);
|
|
1031
|
+
};
|
|
1032
|
+
var eligiblePages = (project) => project.graph.pages.filter((page) => !(page.meta.draft || page.meta.sidebar.hidden || page.meta.seo.noindex) && (project.config.ai.llmsTxt.openapi || page.source.name !== "openapi"));
|
|
1033
|
+
var indexedNavigations = (project) => {
|
|
1034
|
+
const { i18n } = project.config;
|
|
1035
|
+
if (i18n) {
|
|
1036
|
+
return i18n.locales.flatMap(({ code, label }) => {
|
|
1037
|
+
const nav = project.graph.navigationByLocale[code];
|
|
1038
|
+
if (!nav) {
|
|
1039
|
+
return [];
|
|
1040
|
+
}
|
|
1041
|
+
return [{ label: code === i18n.defaultLocale ? undefined : label, nav }];
|
|
1042
|
+
});
|
|
751
1043
|
}
|
|
752
|
-
return
|
|
1044
|
+
return [{ nav: project.graph.navigation }];
|
|
753
1045
|
};
|
|
754
|
-
var orderedPages = (project) => [...project.graph.pages].filter((page) => !page.meta.draft).sort((a, b) => a.route.localeCompare(b.route));
|
|
755
1046
|
var buildIndex = (project) => {
|
|
756
1047
|
const { config } = project;
|
|
757
1048
|
const { site } = config.deployment;
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
const url = pageUrl(page.route, site, normalizeBasePath(config.deployment.base));
|
|
1049
|
+
const base = normalizeBasePath(config.deployment.base);
|
|
1050
|
+
const eligible = eligiblePages(project);
|
|
1051
|
+
const byRoute = new Map(eligible.map((page) => [page.route, page]));
|
|
1052
|
+
const seen = new Set;
|
|
1053
|
+
const line = (page) => {
|
|
1054
|
+
seen.add(page.route);
|
|
765
1055
|
const summary = page.description ? `: ${page.description}` : "";
|
|
766
|
-
|
|
1056
|
+
return `- [${page.title}](${pageUrl(page.route, site, base)})${summary}`;
|
|
1057
|
+
};
|
|
1058
|
+
const renderLevel = (nodes, depth) => {
|
|
1059
|
+
const list = [];
|
|
1060
|
+
const groupBlocks = [];
|
|
1061
|
+
for (const node of nodes) {
|
|
1062
|
+
if (node.kind === "page") {
|
|
1063
|
+
const page = byRoute.get(node.route);
|
|
1064
|
+
if (page && !seen.has(page.route)) {
|
|
1065
|
+
list.push(line(page));
|
|
1066
|
+
}
|
|
1067
|
+
continue;
|
|
1068
|
+
}
|
|
1069
|
+
const rootPage = node.route ? byRoute.get(node.route) : undefined;
|
|
1070
|
+
const blocks2 = renderLevel(node.children, depth + 1);
|
|
1071
|
+
if (rootPage && !seen.has(rootPage.route)) {
|
|
1072
|
+
blocks2.unshift(line(rootPage));
|
|
1073
|
+
}
|
|
1074
|
+
if (blocks2.length > 0) {
|
|
1075
|
+
groupBlocks.push(`${"#".repeat(Math.min(depth, 6))} ${node.label}`, ...blocks2);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
return list.length > 0 ? [list.join(`
|
|
1079
|
+
`), ...groupBlocks] : groupBlocks;
|
|
1080
|
+
};
|
|
1081
|
+
const renderNav = (nav, depth) => {
|
|
1082
|
+
const loose = nav.sidebar.filter((node) => node.kind === "page");
|
|
1083
|
+
const groups = nav.sidebar.filter((node) => node.kind === "group");
|
|
1084
|
+
const looseBlocks = renderLevel(loose, depth + 1);
|
|
1085
|
+
return [
|
|
1086
|
+
...looseBlocks.length > 0 ? [`${"#".repeat(depth)} Docs`, ...looseBlocks] : [],
|
|
1087
|
+
...renderLevel(groups, depth)
|
|
1088
|
+
];
|
|
1089
|
+
};
|
|
1090
|
+
const blocks = [];
|
|
1091
|
+
for (const { label, nav } of indexedNavigations(project)) {
|
|
1092
|
+
if (label) {
|
|
1093
|
+
const localized = renderNav(nav, 3);
|
|
1094
|
+
if (localized.length > 0) {
|
|
1095
|
+
blocks.push(`## ${label}`, ...localized);
|
|
1096
|
+
}
|
|
1097
|
+
continue;
|
|
1098
|
+
}
|
|
1099
|
+
blocks.push(...renderNav(nav, 2));
|
|
767
1100
|
}
|
|
768
|
-
|
|
1101
|
+
const leftover = eligible.filter((page) => !seen.has(page.route)).toSorted((a, b) => a.route.localeCompare(b.route));
|
|
1102
|
+
if (leftover.length > 0) {
|
|
1103
|
+
blocks.push(blocks.length > 0 ? "## Other" : "## Docs", leftover.map(line).join(`
|
|
1104
|
+
`));
|
|
1105
|
+
}
|
|
1106
|
+
const header = config.description ? `# ${config.title}
|
|
1107
|
+
|
|
1108
|
+
> ${config.description}` : `# ${config.title}`;
|
|
1109
|
+
return `${[header, ...blocks].join(`
|
|
1110
|
+
|
|
769
1111
|
`)}
|
|
770
1112
|
`;
|
|
771
1113
|
};
|
|
772
1114
|
var buildFull = async (project) => {
|
|
773
1115
|
const { config } = project;
|
|
774
|
-
const pages =
|
|
1116
|
+
const pages = eligiblePages(project).toSorted((a, b) => a.route.localeCompare(b.route));
|
|
775
1117
|
const sections = await Promise.all(pages.map(async (page) => {
|
|
776
1118
|
const raw = await readEntryText(project, page);
|
|
777
|
-
const body = frontmatter_default(raw).content.trim();
|
|
1119
|
+
const body = downlevelComponents(applyAgentVisibility(frontmatter_default(raw).content), config.ai.markdownComponents).trim();
|
|
778
1120
|
const url = pageUrl(page.route, config.deployment.site, normalizeBasePath(config.deployment.base));
|
|
779
1121
|
return [`# ${page.title}`, `Source: ${url}`, "", body].join(`
|
|
780
1122
|
`);
|
|
@@ -897,7 +1239,7 @@ import { existsSync as existsSync4 } from "node:fs";
|
|
|
897
1239
|
import { cp, mkdir as mkdir2, rm } from "node:fs/promises";
|
|
898
1240
|
import { dirname as dirname4, join as join6 } from "pathe";
|
|
899
1241
|
var ADAPTER_OUTPUT_PATHS = {
|
|
900
|
-
netlify: ".netlify",
|
|
1242
|
+
netlify: ".netlify/v1",
|
|
901
1243
|
vercel: ".vercel/output"
|
|
902
1244
|
};
|
|
903
1245
|
var deployStaticDir = (config, context) => {
|
|
@@ -905,7 +1247,11 @@ var deployStaticDir = (config, context) => {
|
|
|
905
1247
|
if (output === "server" && adapter === "vercel") {
|
|
906
1248
|
return join6(context.root, ".vercel", "output", "static");
|
|
907
1249
|
}
|
|
908
|
-
|
|
1250
|
+
const dist = context.distDir ?? join6(context.root, "dist");
|
|
1251
|
+
if (output === "server" && adapter === "node") {
|
|
1252
|
+
return join6(dist, "client");
|
|
1253
|
+
}
|
|
1254
|
+
return dist;
|
|
909
1255
|
};
|
|
910
1256
|
var surfaceAdapterOutput = async (config, context) => {
|
|
911
1257
|
const { adapter, output } = config.deployment;
|
|
@@ -940,8 +1286,8 @@ var buildNetlifyRedirects = (redirects) => `${redirects.map((redirect) => `${red
|
|
|
940
1286
|
var buildVercelConfig = (redirects) => `${JSON.stringify({
|
|
941
1287
|
redirects: redirects.map((redirect) => ({
|
|
942
1288
|
destination: redirect.to,
|
|
943
|
-
|
|
944
|
-
|
|
1289
|
+
source: redirect.from,
|
|
1290
|
+
statusCode: redirect.status
|
|
945
1291
|
}))
|
|
946
1292
|
}, null, 2)}
|
|
947
1293
|
`;
|
|
@@ -986,7 +1332,71 @@ var buildRobots = (project) => {
|
|
|
986
1332
|
`;
|
|
987
1333
|
};
|
|
988
1334
|
|
|
1335
|
+
// src/astro/pages.ts
|
|
1336
|
+
import { extname, relative as relative4 } from "pathe";
|
|
1337
|
+
import { glob, globSync } from "tinyglobby";
|
|
1338
|
+
var PAGE_GLOB = ["**/*.astro"];
|
|
1339
|
+
var toPageRoutes = (pagesRoot, files) => {
|
|
1340
|
+
files.sort();
|
|
1341
|
+
return files.map((file) => {
|
|
1342
|
+
const rel = relative4(pagesRoot, file);
|
|
1343
|
+
const withoutExt = rel.slice(0, rel.length - extname(rel).length);
|
|
1344
|
+
const parts = withoutExt.split("/");
|
|
1345
|
+
if (parts.at(-1) === "index") {
|
|
1346
|
+
parts.pop();
|
|
1347
|
+
}
|
|
1348
|
+
const pattern = parts.length === 0 ? "/" : `/${parts.join("/")}`;
|
|
1349
|
+
return { entrypoint: file, pattern };
|
|
1350
|
+
});
|
|
1351
|
+
};
|
|
1352
|
+
var discoverPages = async (pagesRoot) => toPageRoutes(pagesRoot, await glob(PAGE_GLOB, { absolute: true, cwd: pagesRoot, onlyFiles: true }));
|
|
1353
|
+
var discoverPagesSync = (pagesRoot) => toPageRoutes(pagesRoot, globSync(PAGE_GLOB, { absolute: true, cwd: pagesRoot, onlyFiles: true }));
|
|
1354
|
+
var routeIsTaken = (pages, contentPages, route) => pages.some((page) => page.pattern === route) || contentPages.some((page) => page.route === route);
|
|
1355
|
+
var PRIVATE_SEGMENT = /^[._]/u;
|
|
1356
|
+
var staticSegments = (pattern) => {
|
|
1357
|
+
const segments = pattern.split("/").filter(Boolean);
|
|
1358
|
+
return segments.some((part) => PRIVATE_SEGMENT.test(part) || part.includes("[")) ? null : segments;
|
|
1359
|
+
};
|
|
1360
|
+
var customStaticRoutes = (pages) => {
|
|
1361
|
+
const routes = new Set;
|
|
1362
|
+
for (const { pattern } of pages) {
|
|
1363
|
+
const segments = staticSegments(pattern);
|
|
1364
|
+
if (segments !== null) {
|
|
1365
|
+
routes.add(segments.length === 0 ? "/" : `/${segments.join("/")}`);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
return [...routes];
|
|
1369
|
+
};
|
|
1370
|
+
var hasGeneratedChangelog = (project, userPages) => {
|
|
1371
|
+
const hasChangelog = project.graph.pages.some((page) => page.contentType === "changelog" && !(page.meta.draft || page.meta.sidebar.hidden));
|
|
1372
|
+
const hasChangelogSource = (project.config.content.sources ?? []).some((source) => source.type === "github-releases");
|
|
1373
|
+
return (hasChangelog || hasChangelogSource) && !routeIsTaken(userPages, project.graph.pages, "/changelog");
|
|
1374
|
+
};
|
|
1375
|
+
var humanizeSegment = (segment) => segment.split(/[-_]/u).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1376
|
+
var customOgRoutes = (pages, siteTitle) => {
|
|
1377
|
+
const seen = new Set;
|
|
1378
|
+
const routes = [];
|
|
1379
|
+
const collectRoute = (pattern) => {
|
|
1380
|
+
const segments = staticSegments(pattern);
|
|
1381
|
+
if (segments === null) {
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
const slug = segments.length === 0 ? "index" : segments.join("/");
|
|
1385
|
+
if (seen.has(slug)) {
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
seen.add(slug);
|
|
1389
|
+
const last = segments.at(-1);
|
|
1390
|
+
routes.push({ slug, title: last ? humanizeSegment(last) : siteTitle });
|
|
1391
|
+
};
|
|
1392
|
+
for (const { pattern } of pages) {
|
|
1393
|
+
collectRoute(pattern);
|
|
1394
|
+
}
|
|
1395
|
+
return routes;
|
|
1396
|
+
};
|
|
1397
|
+
|
|
989
1398
|
// src/deploy/sitemap.ts
|
|
1399
|
+
var ERROR_ROUTES = new Set(["/404", "/500"]);
|
|
990
1400
|
var lastmodTag = (value) => {
|
|
991
1401
|
if (!value) {
|
|
992
1402
|
return "";
|
|
@@ -1001,13 +1411,29 @@ var buildSitemap = (project) => {
|
|
|
1001
1411
|
}
|
|
1002
1412
|
const base = site.replace(/\/$/u, "");
|
|
1003
1413
|
const deployBase = normalizeBasePath(project.config.deployment.base);
|
|
1414
|
+
const seen = new Set;
|
|
1004
1415
|
const urls = [];
|
|
1416
|
+
const pushUrl = (route, lastModified) => {
|
|
1417
|
+
const loc = escapeXml(encodeURI(`${base}${route}`));
|
|
1418
|
+
if (seen.has(loc)) {
|
|
1419
|
+
return;
|
|
1420
|
+
}
|
|
1421
|
+
seen.add(loc);
|
|
1422
|
+
urls.push(` <url><loc>${loc}</loc>${lastmodTag(lastModified)}</url>`);
|
|
1423
|
+
};
|
|
1005
1424
|
for (const page of project.graph.pages) {
|
|
1006
|
-
if (page.meta.draft || page.meta.sidebar.hidden || page.meta.seo.noindex) {
|
|
1425
|
+
if (page.meta.draft || page.meta.sidebar.hidden || page.meta.seo.noindex || ERROR_ROUTES.has(page.route)) {
|
|
1007
1426
|
continue;
|
|
1008
1427
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1428
|
+
pushUrl(withBasePath(deployBase, page.route), page.lastModified);
|
|
1429
|
+
}
|
|
1430
|
+
const userPages = project.context.pagesRoot ? discoverPagesSync(project.context.pagesRoot) : [];
|
|
1431
|
+
const extraRoutes = customStaticRoutes(userPages).filter((route) => !ERROR_ROUTES.has(route));
|
|
1432
|
+
if (hasGeneratedChangelog(project, userPages)) {
|
|
1433
|
+
extraRoutes.push("/changelog");
|
|
1434
|
+
}
|
|
1435
|
+
for (const route of extraRoutes) {
|
|
1436
|
+
pushUrl(withBasePath(deployBase, route));
|
|
1011
1437
|
}
|
|
1012
1438
|
urls.sort();
|
|
1013
1439
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -1055,6 +1481,11 @@ var ar = {
|
|
|
1055
1481
|
send: "إرسال",
|
|
1056
1482
|
title: "اسأل الذكاء الاصطناعي"
|
|
1057
1483
|
},
|
|
1484
|
+
banner: { dismiss: "إغلاق الإعلان" },
|
|
1485
|
+
changelog: {
|
|
1486
|
+
description: "تحديثات المنتج وملاحظات الإصدارات.",
|
|
1487
|
+
title: "سجل التغييرات"
|
|
1488
|
+
},
|
|
1058
1489
|
feedback: {
|
|
1059
1490
|
no: "لا",
|
|
1060
1491
|
question: "هل كانت هذه الصفحة مفيدة؟",
|
|
@@ -1062,13 +1493,16 @@ var ar = {
|
|
|
1062
1493
|
yes: "نعم"
|
|
1063
1494
|
},
|
|
1064
1495
|
languageSwitcher: { label: "اللغة", untranslated: "غير مترجم" },
|
|
1496
|
+
nav: { breadcrumb: "مسار التنقل" },
|
|
1065
1497
|
page: {
|
|
1066
1498
|
lastUpdated: "آخر تحديث في",
|
|
1067
1499
|
next: "التالي",
|
|
1500
|
+
pagination: "ترقيم الصفحات",
|
|
1068
1501
|
previous: "السابق",
|
|
1069
1502
|
skipToContent: "الانتقال إلى المحتوى"
|
|
1070
1503
|
},
|
|
1071
1504
|
search: {
|
|
1505
|
+
all: "الكل",
|
|
1072
1506
|
button: "بحث",
|
|
1073
1507
|
devOnly: "البحث متاح في إصدار الإنتاج.",
|
|
1074
1508
|
label: "البحث في الوثائق",
|
|
@@ -1101,6 +1535,11 @@ var bg = {
|
|
|
1101
1535
|
send: "Изпрати",
|
|
1102
1536
|
title: "Попитай ИИ"
|
|
1103
1537
|
},
|
|
1538
|
+
banner: { dismiss: "Затваряне на съобщението" },
|
|
1539
|
+
changelog: {
|
|
1540
|
+
description: "Актуализации на продукта и бележки към изданията.",
|
|
1541
|
+
title: "Дневник на промените"
|
|
1542
|
+
},
|
|
1104
1543
|
feedback: {
|
|
1105
1544
|
no: "Не",
|
|
1106
1545
|
question: "Беше ли полезна тази страница?",
|
|
@@ -1108,13 +1547,16 @@ var bg = {
|
|
|
1108
1547
|
yes: "Да"
|
|
1109
1548
|
},
|
|
1110
1549
|
languageSwitcher: { label: "Език", untranslated: "Непреведено" },
|
|
1550
|
+
nav: { breadcrumb: "Навигационна пътека" },
|
|
1111
1551
|
page: {
|
|
1112
1552
|
lastUpdated: "Последна актуализация",
|
|
1113
1553
|
next: "Напред",
|
|
1554
|
+
pagination: "Пагинация",
|
|
1114
1555
|
previous: "Назад",
|
|
1115
1556
|
skipToContent: "Към съдържанието"
|
|
1116
1557
|
},
|
|
1117
1558
|
search: {
|
|
1559
|
+
all: "Всички",
|
|
1118
1560
|
button: "Търсене",
|
|
1119
1561
|
devOnly: "Търсенето е достъпно в производствената компилация.",
|
|
1120
1562
|
label: "Търсене в документацията",
|
|
@@ -1147,6 +1589,11 @@ var bn = {
|
|
|
1147
1589
|
send: "পাঠান",
|
|
1148
1590
|
title: "AI-কে জিজ্ঞাসা করুন"
|
|
1149
1591
|
},
|
|
1592
|
+
banner: { dismiss: "ঘোষণা বন্ধ করুন" },
|
|
1593
|
+
changelog: {
|
|
1594
|
+
description: "পণ্য আপডেট এবং রিলিজ নোট।",
|
|
1595
|
+
title: "পরিবর্তন লগ"
|
|
1596
|
+
},
|
|
1150
1597
|
feedback: {
|
|
1151
1598
|
no: "না",
|
|
1152
1599
|
question: "এই পৃষ্ঠাটি কি সহায়ক ছিল?",
|
|
@@ -1154,13 +1601,16 @@ var bn = {
|
|
|
1154
1601
|
yes: "হ্যাঁ"
|
|
1155
1602
|
},
|
|
1156
1603
|
languageSwitcher: { label: "ভাষা", untranslated: "অনূদিত নয়" },
|
|
1604
|
+
nav: { breadcrumb: "ব্রেডক্রাম্ব" },
|
|
1157
1605
|
page: {
|
|
1158
1606
|
lastUpdated: "সর্বশেষ আপডেট",
|
|
1159
1607
|
next: "পরবর্তী",
|
|
1608
|
+
pagination: "পেজিনেশন",
|
|
1160
1609
|
previous: "পূর্ববর্তী",
|
|
1161
1610
|
skipToContent: "বিষয়বস্তুতে যান"
|
|
1162
1611
|
},
|
|
1163
1612
|
search: {
|
|
1613
|
+
all: "সব",
|
|
1164
1614
|
button: "অনুসন্ধান",
|
|
1165
1615
|
devOnly: "অনুসন্ধান প্রোডাকশন বিল্ডে উপলব্ধ।",
|
|
1166
1616
|
label: "ডকুমেন্টেশন অনুসন্ধান করুন",
|
|
@@ -1193,6 +1643,11 @@ var ca = {
|
|
|
1193
1643
|
send: "Envia",
|
|
1194
1644
|
title: "Pregunta a la IA"
|
|
1195
1645
|
},
|
|
1646
|
+
banner: { dismiss: "Tanca l'anunci" },
|
|
1647
|
+
changelog: {
|
|
1648
|
+
description: "Actualitzacions del producte i notes de la versió.",
|
|
1649
|
+
title: "Registre de canvis"
|
|
1650
|
+
},
|
|
1196
1651
|
feedback: {
|
|
1197
1652
|
no: "No",
|
|
1198
1653
|
question: "Aquesta pàgina t'ha estat útil?",
|
|
@@ -1200,13 +1655,16 @@ var ca = {
|
|
|
1200
1655
|
yes: "Sí"
|
|
1201
1656
|
},
|
|
1202
1657
|
languageSwitcher: { label: "Idioma", untranslated: "Sense traduir" },
|
|
1658
|
+
nav: { breadcrumb: "Ruta de navegació" },
|
|
1203
1659
|
page: {
|
|
1204
1660
|
lastUpdated: "Última actualització el",
|
|
1205
1661
|
next: "Següent",
|
|
1662
|
+
pagination: "Paginació",
|
|
1206
1663
|
previous: "Anterior",
|
|
1207
1664
|
skipToContent: "Vés al contingut"
|
|
1208
1665
|
},
|
|
1209
1666
|
search: {
|
|
1667
|
+
all: "Tots",
|
|
1210
1668
|
button: "Cerca",
|
|
1211
1669
|
devOnly: "La cerca està disponible a la compilació de producció.",
|
|
1212
1670
|
label: "Cerca a la documentació",
|
|
@@ -1239,6 +1697,11 @@ var cs = {
|
|
|
1239
1697
|
send: "Odeslat",
|
|
1240
1698
|
title: "Zeptat se AI"
|
|
1241
1699
|
},
|
|
1700
|
+
banner: { dismiss: "Zavřít oznámení" },
|
|
1701
|
+
changelog: {
|
|
1702
|
+
description: "Novinky produktu a poznámky k vydání.",
|
|
1703
|
+
title: "Seznam změn"
|
|
1704
|
+
},
|
|
1242
1705
|
feedback: {
|
|
1243
1706
|
no: "Ne",
|
|
1244
1707
|
question: "Byla tato stránka užitečná?",
|
|
@@ -1246,13 +1709,16 @@ var cs = {
|
|
|
1246
1709
|
yes: "Ano"
|
|
1247
1710
|
},
|
|
1248
1711
|
languageSwitcher: { label: "Jazyk", untranslated: "Nepřeloženo" },
|
|
1712
|
+
nav: { breadcrumb: "Drobečková navigace" },
|
|
1249
1713
|
page: {
|
|
1250
1714
|
lastUpdated: "Naposledy aktualizováno",
|
|
1251
1715
|
next: "Další",
|
|
1716
|
+
pagination: "Stránkování",
|
|
1252
1717
|
previous: "Předchozí",
|
|
1253
1718
|
skipToContent: "Přejít k obsahu"
|
|
1254
1719
|
},
|
|
1255
1720
|
search: {
|
|
1721
|
+
all: "Vše",
|
|
1256
1722
|
button: "Hledat",
|
|
1257
1723
|
devOnly: "Vyhledávání je dostupné v produkčním buildu.",
|
|
1258
1724
|
label: "Prohledat dokumentaci",
|
|
@@ -1285,6 +1751,11 @@ var da = {
|
|
|
1285
1751
|
send: "Send",
|
|
1286
1752
|
title: "Spørg AI"
|
|
1287
1753
|
},
|
|
1754
|
+
banner: { dismiss: "Luk meddelelsen" },
|
|
1755
|
+
changelog: {
|
|
1756
|
+
description: "Produktopdateringer og udgivelsesnoter.",
|
|
1757
|
+
title: "Ændringslog"
|
|
1758
|
+
},
|
|
1288
1759
|
feedback: {
|
|
1289
1760
|
no: "Nej",
|
|
1290
1761
|
question: "Var denne side nyttig?",
|
|
@@ -1292,13 +1763,16 @@ var da = {
|
|
|
1292
1763
|
yes: "Ja"
|
|
1293
1764
|
},
|
|
1294
1765
|
languageSwitcher: { label: "Sprog", untranslated: "Ikke oversat" },
|
|
1766
|
+
nav: { breadcrumb: "Brødkrummesti" },
|
|
1295
1767
|
page: {
|
|
1296
1768
|
lastUpdated: "Senest opdateret den",
|
|
1297
1769
|
next: "Næste",
|
|
1770
|
+
pagination: "Paginering",
|
|
1298
1771
|
previous: "Forrige",
|
|
1299
1772
|
skipToContent: "Spring til indhold"
|
|
1300
1773
|
},
|
|
1301
1774
|
search: {
|
|
1775
|
+
all: "Alle",
|
|
1302
1776
|
button: "Søg",
|
|
1303
1777
|
devOnly: "Søgning er tilgængelig i produktionsbygningen.",
|
|
1304
1778
|
label: "Søg i dokumentationen",
|
|
@@ -1331,6 +1805,11 @@ var de = {
|
|
|
1331
1805
|
send: "Senden",
|
|
1332
1806
|
title: "KI fragen"
|
|
1333
1807
|
},
|
|
1808
|
+
banner: { dismiss: "Ankündigung schließen" },
|
|
1809
|
+
changelog: {
|
|
1810
|
+
description: "Produkt-Updates und Versionshinweise.",
|
|
1811
|
+
title: "Änderungsprotokoll"
|
|
1812
|
+
},
|
|
1334
1813
|
feedback: {
|
|
1335
1814
|
no: "Nein",
|
|
1336
1815
|
question: "War diese Seite hilfreich?",
|
|
@@ -1338,13 +1817,16 @@ var de = {
|
|
|
1338
1817
|
yes: "Ja"
|
|
1339
1818
|
},
|
|
1340
1819
|
languageSwitcher: { label: "Sprache", untranslated: "Nicht übersetzt" },
|
|
1820
|
+
nav: { breadcrumb: "Brotkrümelnavigation" },
|
|
1341
1821
|
page: {
|
|
1342
1822
|
lastUpdated: "Zuletzt aktualisiert am",
|
|
1343
1823
|
next: "Weiter",
|
|
1824
|
+
pagination: "Seitennummerierung",
|
|
1344
1825
|
previous: "Zurück",
|
|
1345
1826
|
skipToContent: "Zum Inhalt springen"
|
|
1346
1827
|
},
|
|
1347
1828
|
search: {
|
|
1829
|
+
all: "Alle",
|
|
1348
1830
|
button: "Suchen",
|
|
1349
1831
|
devOnly: "Die Suche ist im Produktions-Build verfügbar.",
|
|
1350
1832
|
label: "Dokumentation durchsuchen",
|
|
@@ -1377,6 +1859,11 @@ var el = {
|
|
|
1377
1859
|
send: "Αποστολή",
|
|
1378
1860
|
title: "Ρωτήστε την AI"
|
|
1379
1861
|
},
|
|
1862
|
+
banner: { dismiss: "Κλείσιμο ανακοίνωσης" },
|
|
1863
|
+
changelog: {
|
|
1864
|
+
description: "Ενημερώσεις προϊόντος και σημειώσεις έκδοσης.",
|
|
1865
|
+
title: "Ιστορικό αλλαγών"
|
|
1866
|
+
},
|
|
1380
1867
|
feedback: {
|
|
1381
1868
|
no: "Όχι",
|
|
1382
1869
|
question: "Σας φάνηκε χρήσιμη αυτή η σελίδα;",
|
|
@@ -1384,13 +1871,16 @@ var el = {
|
|
|
1384
1871
|
yes: "Ναι"
|
|
1385
1872
|
},
|
|
1386
1873
|
languageSwitcher: { label: "Γλώσσα", untranslated: "Δεν έχει μεταφραστεί" },
|
|
1874
|
+
nav: { breadcrumb: "Διαδρομή πλοήγησης" },
|
|
1387
1875
|
page: {
|
|
1388
1876
|
lastUpdated: "Τελευταία ενημέρωση",
|
|
1389
1877
|
next: "Επόμενο",
|
|
1878
|
+
pagination: "Σελιδοποίηση",
|
|
1390
1879
|
previous: "Προηγούμενο",
|
|
1391
1880
|
skipToContent: "Μετάβαση στο περιεχόμενο"
|
|
1392
1881
|
},
|
|
1393
1882
|
search: {
|
|
1883
|
+
all: "Όλα",
|
|
1394
1884
|
button: "Αναζήτηση",
|
|
1395
1885
|
devOnly: "Η αναζήτηση είναι διαθέσιμη στην έκδοση παραγωγής.",
|
|
1396
1886
|
label: "Αναζήτηση στην τεκμηρίωση",
|
|
@@ -1423,6 +1913,11 @@ var es = {
|
|
|
1423
1913
|
send: "Enviar",
|
|
1424
1914
|
title: "Preguntar a la IA"
|
|
1425
1915
|
},
|
|
1916
|
+
banner: { dismiss: "Cerrar el anuncio" },
|
|
1917
|
+
changelog: {
|
|
1918
|
+
description: "Novedades del producto y notas de la versión.",
|
|
1919
|
+
title: "Registro de cambios"
|
|
1920
|
+
},
|
|
1426
1921
|
feedback: {
|
|
1427
1922
|
no: "No",
|
|
1428
1923
|
question: "¿Te ha resultado útil esta página?",
|
|
@@ -1430,13 +1925,16 @@ var es = {
|
|
|
1430
1925
|
yes: "Sí"
|
|
1431
1926
|
},
|
|
1432
1927
|
languageSwitcher: { label: "Idioma", untranslated: "Sin traducir" },
|
|
1928
|
+
nav: { breadcrumb: "Ruta de navegación" },
|
|
1433
1929
|
page: {
|
|
1434
1930
|
lastUpdated: "Última actualización el",
|
|
1435
1931
|
next: "Siguiente",
|
|
1932
|
+
pagination: "Paginación",
|
|
1436
1933
|
previous: "Anterior",
|
|
1437
1934
|
skipToContent: "Saltar al contenido"
|
|
1438
1935
|
},
|
|
1439
1936
|
search: {
|
|
1937
|
+
all: "Todos",
|
|
1440
1938
|
button: "Buscar",
|
|
1441
1939
|
devOnly: "La búsqueda está disponible en la compilación de producción.",
|
|
1442
1940
|
label: "Buscar en la documentación",
|
|
@@ -1469,6 +1967,11 @@ var fa = {
|
|
|
1469
1967
|
send: "ارسال",
|
|
1470
1968
|
title: "از هوش مصنوعی بپرسید"
|
|
1471
1969
|
},
|
|
1970
|
+
banner: { dismiss: "بستن اطلاعیه" },
|
|
1971
|
+
changelog: {
|
|
1972
|
+
description: "بهروزرسانیهای محصول و یادداشتهای انتشار.",
|
|
1973
|
+
title: "گزارش تغییرات"
|
|
1974
|
+
},
|
|
1472
1975
|
feedback: {
|
|
1473
1976
|
no: "خیر",
|
|
1474
1977
|
question: "آیا این صفحه مفید بود؟",
|
|
@@ -1476,13 +1979,16 @@ var fa = {
|
|
|
1476
1979
|
yes: "بله"
|
|
1477
1980
|
},
|
|
1478
1981
|
languageSwitcher: { label: "زبان", untranslated: "ترجمهنشده" },
|
|
1982
|
+
nav: { breadcrumb: "مسیر ناوبری" },
|
|
1479
1983
|
page: {
|
|
1480
1984
|
lastUpdated: "آخرین بهروزرسانی",
|
|
1481
1985
|
next: "بعدی",
|
|
1986
|
+
pagination: "صفحهبندی",
|
|
1482
1987
|
previous: "قبلی",
|
|
1483
1988
|
skipToContent: "پرش به محتوا"
|
|
1484
1989
|
},
|
|
1485
1990
|
search: {
|
|
1991
|
+
all: "همه",
|
|
1486
1992
|
button: "جستجو",
|
|
1487
1993
|
devOnly: "جستجو در نسخه تولید در دسترس است.",
|
|
1488
1994
|
label: "جستجو در مستندات",
|
|
@@ -1515,6 +2021,11 @@ var fi = {
|
|
|
1515
2021
|
send: "Lähetä",
|
|
1516
2022
|
title: "Kysy tekoälyltä"
|
|
1517
2023
|
},
|
|
2024
|
+
banner: { dismiss: "Sulje ilmoitus" },
|
|
2025
|
+
changelog: {
|
|
2026
|
+
description: "Tuotepäivitykset ja julkaisutiedot.",
|
|
2027
|
+
title: "Muutosloki"
|
|
2028
|
+
},
|
|
1518
2029
|
feedback: {
|
|
1519
2030
|
no: "Ei",
|
|
1520
2031
|
question: "Oliko tästä sivusta apua?",
|
|
@@ -1522,13 +2033,16 @@ var fi = {
|
|
|
1522
2033
|
yes: "Kyllä"
|
|
1523
2034
|
},
|
|
1524
2035
|
languageSwitcher: { label: "Kieli", untranslated: "Ei käännetty" },
|
|
2036
|
+
nav: { breadcrumb: "Murupolku" },
|
|
1525
2037
|
page: {
|
|
1526
2038
|
lastUpdated: "Viimeksi päivitetty",
|
|
1527
2039
|
next: "Seuraava",
|
|
2040
|
+
pagination: "Sivutus",
|
|
1528
2041
|
previous: "Edellinen",
|
|
1529
2042
|
skipToContent: "Siirry sisältöön"
|
|
1530
2043
|
},
|
|
1531
2044
|
search: {
|
|
2045
|
+
all: "Kaikki",
|
|
1532
2046
|
button: "Hae",
|
|
1533
2047
|
devOnly: "Haku on käytettävissä tuotantokäännöksessä.",
|
|
1534
2048
|
label: "Hae dokumentaatiosta",
|
|
@@ -1543,7 +2057,7 @@ var fr = {
|
|
|
1543
2057
|
actions: {
|
|
1544
2058
|
addToCursor: "Ajouter à Cursor",
|
|
1545
2059
|
addToVscode: "Ajouter à VS Code",
|
|
1546
|
-
askAI: "Demander à l'IA",
|
|
2060
|
+
askAI: "Demander à l'IA à propos de cette page",
|
|
1547
2061
|
connectMcp: "Se connecter à MCP",
|
|
1548
2062
|
copied: "Copié !",
|
|
1549
2063
|
copyClaudeCode: "Copier la commande Claude Code",
|
|
@@ -1561,6 +2075,11 @@ var fr = {
|
|
|
1561
2075
|
send: "Envoyer",
|
|
1562
2076
|
title: "Demander à l'IA"
|
|
1563
2077
|
},
|
|
2078
|
+
banner: { dismiss: "Fermer l'annonce" },
|
|
2079
|
+
changelog: {
|
|
2080
|
+
description: "Nouveautés du produit et notes de version.",
|
|
2081
|
+
title: "Journal des modifications"
|
|
2082
|
+
},
|
|
1564
2083
|
feedback: {
|
|
1565
2084
|
no: "Non",
|
|
1566
2085
|
question: "Cette page vous a-t-elle été utile ?",
|
|
@@ -1568,13 +2087,16 @@ var fr = {
|
|
|
1568
2087
|
yes: "Oui"
|
|
1569
2088
|
},
|
|
1570
2089
|
languageSwitcher: { label: "Langue", untranslated: "Non traduit" },
|
|
2090
|
+
nav: { breadcrumb: "Fil d'Ariane" },
|
|
1571
2091
|
page: {
|
|
1572
2092
|
lastUpdated: "Dernière mise à jour le",
|
|
1573
2093
|
next: "Suivant",
|
|
2094
|
+
pagination: "Pagination",
|
|
1574
2095
|
previous: "Précédent",
|
|
1575
2096
|
skipToContent: "Aller au contenu"
|
|
1576
2097
|
},
|
|
1577
2098
|
search: {
|
|
2099
|
+
all: "Tous",
|
|
1578
2100
|
button: "Rechercher",
|
|
1579
2101
|
devOnly: "La recherche est disponible dans la version de production.",
|
|
1580
2102
|
label: "Rechercher dans la doc",
|
|
@@ -1607,6 +2129,11 @@ var he = {
|
|
|
1607
2129
|
send: "שלח",
|
|
1608
2130
|
title: "שאל את ה-AI"
|
|
1609
2131
|
},
|
|
2132
|
+
banner: { dismiss: "סגירת ההודעה" },
|
|
2133
|
+
changelog: {
|
|
2134
|
+
description: "עדכוני מוצר והערות גרסה.",
|
|
2135
|
+
title: "יומן שינויים"
|
|
2136
|
+
},
|
|
1610
2137
|
feedback: {
|
|
1611
2138
|
no: "לא",
|
|
1612
2139
|
question: "האם העמוד הזה היה מועיל?",
|
|
@@ -1614,13 +2141,16 @@ var he = {
|
|
|
1614
2141
|
yes: "כן"
|
|
1615
2142
|
},
|
|
1616
2143
|
languageSwitcher: { label: "שפה", untranslated: "לא מתורגם" },
|
|
2144
|
+
nav: { breadcrumb: "פירורי לחם" },
|
|
1617
2145
|
page: {
|
|
1618
2146
|
lastUpdated: "עודכן לאחרונה",
|
|
1619
2147
|
next: "הבא",
|
|
2148
|
+
pagination: "עימוד",
|
|
1620
2149
|
previous: "הקודם",
|
|
1621
2150
|
skipToContent: "דלג לתוכן"
|
|
1622
2151
|
},
|
|
1623
2152
|
search: {
|
|
2153
|
+
all: "הכל",
|
|
1624
2154
|
button: "חיפוש",
|
|
1625
2155
|
devOnly: "החיפוש זמין בבנייה לייצור.",
|
|
1626
2156
|
label: "חפש בתיעוד",
|
|
@@ -1653,6 +2183,11 @@ var hi = {
|
|
|
1653
2183
|
send: "भेजें",
|
|
1654
2184
|
title: "AI से पूछें"
|
|
1655
2185
|
},
|
|
2186
|
+
banner: { dismiss: "घोषणा बंद करें" },
|
|
2187
|
+
changelog: {
|
|
2188
|
+
description: "उत्पाद अपडेट और रिलीज़ नोट्स।",
|
|
2189
|
+
title: "परिवर्तन लॉग"
|
|
2190
|
+
},
|
|
1656
2191
|
feedback: {
|
|
1657
2192
|
no: "नहीं",
|
|
1658
2193
|
question: "क्या यह पेज सहायक था?",
|
|
@@ -1660,13 +2195,16 @@ var hi = {
|
|
|
1660
2195
|
yes: "हाँ"
|
|
1661
2196
|
},
|
|
1662
2197
|
languageSwitcher: { label: "भाषा", untranslated: "अनुवादित नहीं" },
|
|
2198
|
+
nav: { breadcrumb: "ब्रेडक्रम" },
|
|
1663
2199
|
page: {
|
|
1664
2200
|
lastUpdated: "अंतिम अपडेट",
|
|
1665
2201
|
next: "अगला",
|
|
2202
|
+
pagination: "पृष्ठांकन",
|
|
1666
2203
|
previous: "पिछला",
|
|
1667
2204
|
skipToContent: "सामग्री पर जाएँ"
|
|
1668
2205
|
},
|
|
1669
2206
|
search: {
|
|
2207
|
+
all: "सभी",
|
|
1670
2208
|
button: "खोजें",
|
|
1671
2209
|
devOnly: "खोज प्रोडक्शन बिल्ड में उपलब्ध है।",
|
|
1672
2210
|
label: "दस्तावेज़ खोजें",
|
|
@@ -1699,6 +2237,11 @@ var hr = {
|
|
|
1699
2237
|
send: "Pošalji",
|
|
1700
2238
|
title: "Pitaj AI"
|
|
1701
2239
|
},
|
|
2240
|
+
banner: { dismiss: "Zatvori obavijest" },
|
|
2241
|
+
changelog: {
|
|
2242
|
+
description: "Ažuriranja proizvoda i napomene o izdanjima.",
|
|
2243
|
+
title: "Popis promjena"
|
|
2244
|
+
},
|
|
1702
2245
|
feedback: {
|
|
1703
2246
|
no: "Ne",
|
|
1704
2247
|
question: "Je li vam ova stranica bila korisna?",
|
|
@@ -1706,13 +2249,16 @@ var hr = {
|
|
|
1706
2249
|
yes: "Da"
|
|
1707
2250
|
},
|
|
1708
2251
|
languageSwitcher: { label: "Jezik", untranslated: "Nije prevedeno" },
|
|
2252
|
+
nav: { breadcrumb: "Navigacijski put" },
|
|
1709
2253
|
page: {
|
|
1710
2254
|
lastUpdated: "Posljednje ažuriranje",
|
|
1711
2255
|
next: "Sljedeće",
|
|
2256
|
+
pagination: "Straničenje",
|
|
1712
2257
|
previous: "Prethodno",
|
|
1713
2258
|
skipToContent: "Prijeđi na sadržaj"
|
|
1714
2259
|
},
|
|
1715
2260
|
search: {
|
|
2261
|
+
all: "Sve",
|
|
1716
2262
|
button: "Pretraži",
|
|
1717
2263
|
devOnly: "Pretraživanje je dostupno u produkcijskoj verziji.",
|
|
1718
2264
|
label: "Pretraži dokumentaciju",
|
|
@@ -1745,6 +2291,11 @@ var hu = {
|
|
|
1745
2291
|
send: "Küldés",
|
|
1746
2292
|
title: "Kérdezd az AI-t"
|
|
1747
2293
|
},
|
|
2294
|
+
banner: { dismiss: "Közlemény bezárása" },
|
|
2295
|
+
changelog: {
|
|
2296
|
+
description: "Termékfrissítések és kiadási megjegyzések.",
|
|
2297
|
+
title: "Változásnapló"
|
|
2298
|
+
},
|
|
1748
2299
|
feedback: {
|
|
1749
2300
|
no: "Nem",
|
|
1750
2301
|
question: "Hasznos volt ez az oldal?",
|
|
@@ -1752,13 +2303,16 @@ var hu = {
|
|
|
1752
2303
|
yes: "Igen"
|
|
1753
2304
|
},
|
|
1754
2305
|
languageSwitcher: { label: "Nyelv", untranslated: "Nincs lefordítva" },
|
|
2306
|
+
nav: { breadcrumb: "Morzsamenü" },
|
|
1755
2307
|
page: {
|
|
1756
2308
|
lastUpdated: "Utoljára frissítve",
|
|
1757
2309
|
next: "Következő",
|
|
2310
|
+
pagination: "Lapozás",
|
|
1758
2311
|
previous: "Előző",
|
|
1759
2312
|
skipToContent: "Ugrás a tartalomra"
|
|
1760
2313
|
},
|
|
1761
2314
|
search: {
|
|
2315
|
+
all: "Összes",
|
|
1762
2316
|
button: "Keresés",
|
|
1763
2317
|
devOnly: "A keresés az éles buildben érhető el.",
|
|
1764
2318
|
label: "Keresés a dokumentációban",
|
|
@@ -1791,6 +2345,11 @@ var id = {
|
|
|
1791
2345
|
send: "Kirim",
|
|
1792
2346
|
title: "Tanya AI"
|
|
1793
2347
|
},
|
|
2348
|
+
banner: { dismiss: "Tutup pengumuman" },
|
|
2349
|
+
changelog: {
|
|
2350
|
+
description: "Pembaruan produk dan catatan rilis.",
|
|
2351
|
+
title: "Log perubahan"
|
|
2352
|
+
},
|
|
1794
2353
|
feedback: {
|
|
1795
2354
|
no: "Tidak",
|
|
1796
2355
|
question: "Apakah halaman ini membantu?",
|
|
@@ -1798,13 +2357,16 @@ var id = {
|
|
|
1798
2357
|
yes: "Ya"
|
|
1799
2358
|
},
|
|
1800
2359
|
languageSwitcher: { label: "Bahasa", untranslated: "Belum diterjemahkan" },
|
|
2360
|
+
nav: { breadcrumb: "Remah roti" },
|
|
1801
2361
|
page: {
|
|
1802
2362
|
lastUpdated: "Terakhir diperbarui",
|
|
1803
2363
|
next: "Berikutnya",
|
|
2364
|
+
pagination: "Penomoran halaman",
|
|
1804
2365
|
previous: "Sebelumnya",
|
|
1805
2366
|
skipToContent: "Lewati ke konten"
|
|
1806
2367
|
},
|
|
1807
2368
|
search: {
|
|
2369
|
+
all: "Semua",
|
|
1808
2370
|
button: "Cari",
|
|
1809
2371
|
devOnly: "Pencarian tersedia di build produksi.",
|
|
1810
2372
|
label: "Cari dokumentasi",
|
|
@@ -1837,6 +2399,11 @@ var it = {
|
|
|
1837
2399
|
send: "Invia",
|
|
1838
2400
|
title: "Chiedi all'IA"
|
|
1839
2401
|
},
|
|
2402
|
+
banner: { dismiss: "Chiudi l'annuncio" },
|
|
2403
|
+
changelog: {
|
|
2404
|
+
description: "Aggiornamenti del prodotto e note di rilascio.",
|
|
2405
|
+
title: "Registro delle modifiche"
|
|
2406
|
+
},
|
|
1840
2407
|
feedback: {
|
|
1841
2408
|
no: "No",
|
|
1842
2409
|
question: "Questa pagina ti è stata utile?",
|
|
@@ -1844,13 +2411,16 @@ var it = {
|
|
|
1844
2411
|
yes: "Sì"
|
|
1845
2412
|
},
|
|
1846
2413
|
languageSwitcher: { label: "Lingua", untranslated: "Non tradotto" },
|
|
2414
|
+
nav: { breadcrumb: "Percorso di navigazione" },
|
|
1847
2415
|
page: {
|
|
1848
2416
|
lastUpdated: "Ultimo aggiornamento il",
|
|
1849
2417
|
next: "Successivo",
|
|
2418
|
+
pagination: "Paginazione",
|
|
1850
2419
|
previous: "Precedente",
|
|
1851
2420
|
skipToContent: "Vai al contenuto"
|
|
1852
2421
|
},
|
|
1853
2422
|
search: {
|
|
2423
|
+
all: "Tutti",
|
|
1854
2424
|
button: "Cerca",
|
|
1855
2425
|
devOnly: "La ricerca è disponibile nella build di produzione.",
|
|
1856
2426
|
label: "Cerca nella documentazione",
|
|
@@ -1883,6 +2453,11 @@ var ja = {
|
|
|
1883
2453
|
send: "送信",
|
|
1884
2454
|
title: "AI に質問"
|
|
1885
2455
|
},
|
|
2456
|
+
banner: { dismiss: "お知らせを閉じる" },
|
|
2457
|
+
changelog: {
|
|
2458
|
+
description: "製品のアップデートとリリースノート。",
|
|
2459
|
+
title: "変更履歴"
|
|
2460
|
+
},
|
|
1886
2461
|
feedback: {
|
|
1887
2462
|
no: "いいえ",
|
|
1888
2463
|
question: "このページは役に立ちましたか?",
|
|
@@ -1890,13 +2465,16 @@ var ja = {
|
|
|
1890
2465
|
yes: "はい"
|
|
1891
2466
|
},
|
|
1892
2467
|
languageSwitcher: { label: "言語", untranslated: "未翻訳" },
|
|
2468
|
+
nav: { breadcrumb: "パンくずリスト" },
|
|
1893
2469
|
page: {
|
|
1894
2470
|
lastUpdated: "最終更新",
|
|
1895
2471
|
next: "次へ",
|
|
2472
|
+
pagination: "ページネーション",
|
|
1896
2473
|
previous: "前へ",
|
|
1897
2474
|
skipToContent: "コンテンツにスキップ"
|
|
1898
2475
|
},
|
|
1899
2476
|
search: {
|
|
2477
|
+
all: "すべて",
|
|
1900
2478
|
button: "検索",
|
|
1901
2479
|
devOnly: "検索は本番ビルドで利用できます。",
|
|
1902
2480
|
label: "ドキュメントを検索",
|
|
@@ -1929,6 +2507,11 @@ var ko = {
|
|
|
1929
2507
|
send: "보내기",
|
|
1930
2508
|
title: "AI에게 질문"
|
|
1931
2509
|
},
|
|
2510
|
+
banner: { dismiss: "공지 닫기" },
|
|
2511
|
+
changelog: {
|
|
2512
|
+
description: "제품 업데이트 및 릴리스 노트.",
|
|
2513
|
+
title: "변경 로그"
|
|
2514
|
+
},
|
|
1932
2515
|
feedback: {
|
|
1933
2516
|
no: "아니요",
|
|
1934
2517
|
question: "이 페이지가 도움이 되었나요?",
|
|
@@ -1936,13 +2519,16 @@ var ko = {
|
|
|
1936
2519
|
yes: "예"
|
|
1937
2520
|
},
|
|
1938
2521
|
languageSwitcher: { label: "언어", untranslated: "번역되지 않음" },
|
|
2522
|
+
nav: { breadcrumb: "탐색 경로" },
|
|
1939
2523
|
page: {
|
|
1940
2524
|
lastUpdated: "마지막 업데이트",
|
|
1941
2525
|
next: "다음",
|
|
2526
|
+
pagination: "페이지네이션",
|
|
1942
2527
|
previous: "이전",
|
|
1943
2528
|
skipToContent: "본문으로 건너뛰기"
|
|
1944
2529
|
},
|
|
1945
2530
|
search: {
|
|
2531
|
+
all: "전체",
|
|
1946
2532
|
button: "검색",
|
|
1947
2533
|
devOnly: "검색은 프로덕션 빌드에서 사용할 수 있습니다.",
|
|
1948
2534
|
label: "문서 검색",
|
|
@@ -1975,6 +2561,11 @@ var nl = {
|
|
|
1975
2561
|
send: "Verzenden",
|
|
1976
2562
|
title: "AI vragen"
|
|
1977
2563
|
},
|
|
2564
|
+
banner: { dismiss: "Aankondiging sluiten" },
|
|
2565
|
+
changelog: {
|
|
2566
|
+
description: "Productupdates en releaseopmerkingen.",
|
|
2567
|
+
title: "Wijzigingslogboek"
|
|
2568
|
+
},
|
|
1978
2569
|
feedback: {
|
|
1979
2570
|
no: "Nee",
|
|
1980
2571
|
question: "Was deze pagina nuttig?",
|
|
@@ -1982,13 +2573,16 @@ var nl = {
|
|
|
1982
2573
|
yes: "Ja"
|
|
1983
2574
|
},
|
|
1984
2575
|
languageSwitcher: { label: "Taal", untranslated: "Niet vertaald" },
|
|
2576
|
+
nav: { breadcrumb: "Kruimelpad" },
|
|
1985
2577
|
page: {
|
|
1986
2578
|
lastUpdated: "Laatst bijgewerkt op",
|
|
1987
2579
|
next: "Volgende",
|
|
2580
|
+
pagination: "Paginering",
|
|
1988
2581
|
previous: "Vorige",
|
|
1989
2582
|
skipToContent: "Naar inhoud springen"
|
|
1990
2583
|
},
|
|
1991
2584
|
search: {
|
|
2585
|
+
all: "Alle",
|
|
1992
2586
|
button: "Zoeken",
|
|
1993
2587
|
devOnly: "Zoeken is beschikbaar in de productiebuild.",
|
|
1994
2588
|
label: "Documentatie doorzoeken",
|
|
@@ -2021,6 +2615,11 @@ var no = {
|
|
|
2021
2615
|
send: "Send",
|
|
2022
2616
|
title: "Spør AI"
|
|
2023
2617
|
},
|
|
2618
|
+
banner: { dismiss: "Lukk kunngjøringen" },
|
|
2619
|
+
changelog: {
|
|
2620
|
+
description: "Produktoppdateringer og utgivelsesnotater.",
|
|
2621
|
+
title: "Endringslogg"
|
|
2622
|
+
},
|
|
2024
2623
|
feedback: {
|
|
2025
2624
|
no: "Nei",
|
|
2026
2625
|
question: "Var denne siden nyttig?",
|
|
@@ -2028,13 +2627,16 @@ var no = {
|
|
|
2028
2627
|
yes: "Ja"
|
|
2029
2628
|
},
|
|
2030
2629
|
languageSwitcher: { label: "Språk", untranslated: "Ikke oversatt" },
|
|
2630
|
+
nav: { breadcrumb: "Brødsmulesti" },
|
|
2031
2631
|
page: {
|
|
2032
2632
|
lastUpdated: "Sist oppdatert",
|
|
2033
2633
|
next: "Neste",
|
|
2634
|
+
pagination: "Paginering",
|
|
2034
2635
|
previous: "Forrige",
|
|
2035
2636
|
skipToContent: "Hopp til innhold"
|
|
2036
2637
|
},
|
|
2037
2638
|
search: {
|
|
2639
|
+
all: "Alle",
|
|
2038
2640
|
button: "Søk",
|
|
2039
2641
|
devOnly: "Søk er tilgjengelig i produksjonsbygget.",
|
|
2040
2642
|
label: "Søk i dokumentasjonen",
|
|
@@ -2067,6 +2669,11 @@ var pl = {
|
|
|
2067
2669
|
send: "Wyślij",
|
|
2068
2670
|
title: "Zapytaj AI"
|
|
2069
2671
|
},
|
|
2672
|
+
banner: { dismiss: "Zamknij ogłoszenie" },
|
|
2673
|
+
changelog: {
|
|
2674
|
+
description: "Aktualizacje produktu i informacje o wydaniach.",
|
|
2675
|
+
title: "Dziennik zmian"
|
|
2676
|
+
},
|
|
2070
2677
|
feedback: {
|
|
2071
2678
|
no: "Nie",
|
|
2072
2679
|
question: "Czy ta strona była pomocna?",
|
|
@@ -2074,13 +2681,16 @@ var pl = {
|
|
|
2074
2681
|
yes: "Tak"
|
|
2075
2682
|
},
|
|
2076
2683
|
languageSwitcher: { label: "Język", untranslated: "Nieprzetłumaczone" },
|
|
2684
|
+
nav: { breadcrumb: "Ścieżka nawigacyjna" },
|
|
2077
2685
|
page: {
|
|
2078
2686
|
lastUpdated: "Ostatnia aktualizacja",
|
|
2079
2687
|
next: "Następny",
|
|
2688
|
+
pagination: "Paginacja",
|
|
2080
2689
|
previous: "Poprzedni",
|
|
2081
2690
|
skipToContent: "Przejdź do treści"
|
|
2082
2691
|
},
|
|
2083
2692
|
search: {
|
|
2693
|
+
all: "Wszystkie",
|
|
2084
2694
|
button: "Szukaj",
|
|
2085
2695
|
devOnly: "Wyszukiwanie jest dostępne w kompilacji produkcyjnej.",
|
|
2086
2696
|
label: "Przeszukaj dokumentację",
|
|
@@ -2113,6 +2723,11 @@ var ptBR = {
|
|
|
2113
2723
|
send: "Enviar",
|
|
2114
2724
|
title: "Perguntar à IA"
|
|
2115
2725
|
},
|
|
2726
|
+
banner: { dismiss: "Fechar o anúncio" },
|
|
2727
|
+
changelog: {
|
|
2728
|
+
description: "Atualizações do produto e notas de lançamento.",
|
|
2729
|
+
title: "Registro de alterações"
|
|
2730
|
+
},
|
|
2116
2731
|
feedback: {
|
|
2117
2732
|
no: "Não",
|
|
2118
2733
|
question: "Esta página foi útil?",
|
|
@@ -2120,13 +2735,16 @@ var ptBR = {
|
|
|
2120
2735
|
yes: "Sim"
|
|
2121
2736
|
},
|
|
2122
2737
|
languageSwitcher: { label: "Idioma", untranslated: "Não traduzido" },
|
|
2738
|
+
nav: { breadcrumb: "Trilha de navegação" },
|
|
2123
2739
|
page: {
|
|
2124
2740
|
lastUpdated: "Última atualização em",
|
|
2125
2741
|
next: "Próximo",
|
|
2742
|
+
pagination: "Paginação",
|
|
2126
2743
|
previous: "Anterior",
|
|
2127
2744
|
skipToContent: "Pular para o conteúdo"
|
|
2128
2745
|
},
|
|
2129
2746
|
search: {
|
|
2747
|
+
all: "Todos",
|
|
2130
2748
|
button: "Pesquisar",
|
|
2131
2749
|
devOnly: "A busca está disponível na build de produção.",
|
|
2132
2750
|
label: "Pesquisar na documentação",
|
|
@@ -2159,6 +2777,11 @@ var pt = {
|
|
|
2159
2777
|
send: "Enviar",
|
|
2160
2778
|
title: "Perguntar à IA"
|
|
2161
2779
|
},
|
|
2780
|
+
banner: { dismiss: "Fechar o anúncio" },
|
|
2781
|
+
changelog: {
|
|
2782
|
+
description: "Atualizações do produto e notas de lançamento.",
|
|
2783
|
+
title: "Registo de alterações"
|
|
2784
|
+
},
|
|
2162
2785
|
feedback: {
|
|
2163
2786
|
no: "Não",
|
|
2164
2787
|
question: "Esta página foi útil?",
|
|
@@ -2166,13 +2789,16 @@ var pt = {
|
|
|
2166
2789
|
yes: "Sim"
|
|
2167
2790
|
},
|
|
2168
2791
|
languageSwitcher: { label: "Idioma", untranslated: "Não traduzido" },
|
|
2792
|
+
nav: { breadcrumb: "Caminho de navegação" },
|
|
2169
2793
|
page: {
|
|
2170
2794
|
lastUpdated: "Última atualização a",
|
|
2171
2795
|
next: "Seguinte",
|
|
2796
|
+
pagination: "Paginação",
|
|
2172
2797
|
previous: "Anterior",
|
|
2173
2798
|
skipToContent: "Saltar para o conteúdo"
|
|
2174
2799
|
},
|
|
2175
2800
|
search: {
|
|
2801
|
+
all: "Todos",
|
|
2176
2802
|
button: "Pesquisar",
|
|
2177
2803
|
devOnly: "A pesquisa está disponível na compilação de produção.",
|
|
2178
2804
|
label: "Pesquisar na documentação",
|
|
@@ -2205,6 +2831,11 @@ var ro = {
|
|
|
2205
2831
|
send: "Trimite",
|
|
2206
2832
|
title: "Întreabă AI"
|
|
2207
2833
|
},
|
|
2834
|
+
banner: { dismiss: "Închide anunțul" },
|
|
2835
|
+
changelog: {
|
|
2836
|
+
description: "Actualizări ale produsului și note de lansare.",
|
|
2837
|
+
title: "Jurnal de modificări"
|
|
2838
|
+
},
|
|
2208
2839
|
feedback: {
|
|
2209
2840
|
no: "Nu",
|
|
2210
2841
|
question: "Ți-a fost utilă această pagină?",
|
|
@@ -2212,13 +2843,16 @@ var ro = {
|
|
|
2212
2843
|
yes: "Da"
|
|
2213
2844
|
},
|
|
2214
2845
|
languageSwitcher: { label: "Limbă", untranslated: "Netradus" },
|
|
2846
|
+
nav: { breadcrumb: "Cale de navigare" },
|
|
2215
2847
|
page: {
|
|
2216
2848
|
lastUpdated: "Ultima actualizare",
|
|
2217
2849
|
next: "Următorul",
|
|
2850
|
+
pagination: "Paginare",
|
|
2218
2851
|
previous: "Anteriorul",
|
|
2219
2852
|
skipToContent: "Sari la conținut"
|
|
2220
2853
|
},
|
|
2221
2854
|
search: {
|
|
2855
|
+
all: "Toate",
|
|
2222
2856
|
button: "Caută",
|
|
2223
2857
|
devOnly: "Căutarea este disponibilă în versiunea de producție.",
|
|
2224
2858
|
label: "Caută în documentație",
|
|
@@ -2251,6 +2885,11 @@ var ru = {
|
|
|
2251
2885
|
send: "Отправить",
|
|
2252
2886
|
title: "Спросить ИИ"
|
|
2253
2887
|
},
|
|
2888
|
+
banner: { dismiss: "Закрыть объявление" },
|
|
2889
|
+
changelog: {
|
|
2890
|
+
description: "Обновления продукта и примечания к выпускам.",
|
|
2891
|
+
title: "Журнал изменений"
|
|
2892
|
+
},
|
|
2254
2893
|
feedback: {
|
|
2255
2894
|
no: "Нет",
|
|
2256
2895
|
question: "Эта страница была полезной?",
|
|
@@ -2258,13 +2897,16 @@ var ru = {
|
|
|
2258
2897
|
yes: "Да"
|
|
2259
2898
|
},
|
|
2260
2899
|
languageSwitcher: { label: "Язык", untranslated: "Не переведено" },
|
|
2900
|
+
nav: { breadcrumb: "Навигационная цепочка" },
|
|
2261
2901
|
page: {
|
|
2262
2902
|
lastUpdated: "Последнее обновление",
|
|
2263
2903
|
next: "Далее",
|
|
2904
|
+
pagination: "Пагинация",
|
|
2264
2905
|
previous: "Назад",
|
|
2265
2906
|
skipToContent: "Перейти к содержимому"
|
|
2266
2907
|
},
|
|
2267
2908
|
search: {
|
|
2909
|
+
all: "Все",
|
|
2268
2910
|
button: "Поиск",
|
|
2269
2911
|
devOnly: "Поиск доступен в production-сборке.",
|
|
2270
2912
|
label: "Поиск по документации",
|
|
@@ -2297,6 +2939,11 @@ var sk = {
|
|
|
2297
2939
|
send: "Odoslať",
|
|
2298
2940
|
title: "Opýtať sa AI"
|
|
2299
2941
|
},
|
|
2942
|
+
banner: { dismiss: "Zavrieť oznámenie" },
|
|
2943
|
+
changelog: {
|
|
2944
|
+
description: "Novinky produktu a poznámky k vydaniu.",
|
|
2945
|
+
title: "Zoznam zmien"
|
|
2946
|
+
},
|
|
2300
2947
|
feedback: {
|
|
2301
2948
|
no: "Nie",
|
|
2302
2949
|
question: "Bola táto stránka užitočná?",
|
|
@@ -2304,13 +2951,16 @@ var sk = {
|
|
|
2304
2951
|
yes: "Áno"
|
|
2305
2952
|
},
|
|
2306
2953
|
languageSwitcher: { label: "Jazyk", untranslated: "Nepreložené" },
|
|
2954
|
+
nav: { breadcrumb: "Omrvinková navigácia" },
|
|
2307
2955
|
page: {
|
|
2308
2956
|
lastUpdated: "Naposledy aktualizované",
|
|
2309
2957
|
next: "Ďalej",
|
|
2958
|
+
pagination: "Stránkovanie",
|
|
2310
2959
|
previous: "Predchádzajúce",
|
|
2311
2960
|
skipToContent: "Prejsť na obsah"
|
|
2312
2961
|
},
|
|
2313
2962
|
search: {
|
|
2963
|
+
all: "Všetko",
|
|
2314
2964
|
button: "Hľadať",
|
|
2315
2965
|
devOnly: "Vyhľadávanie je dostupné v produkčnom builde.",
|
|
2316
2966
|
label: "Prehľadať dokumentáciu",
|
|
@@ -2343,6 +2993,11 @@ var sr = {
|
|
|
2343
2993
|
send: "Пошаљи",
|
|
2344
2994
|
title: "Питајте AI"
|
|
2345
2995
|
},
|
|
2996
|
+
banner: { dismiss: "Затвори обавештење" },
|
|
2997
|
+
changelog: {
|
|
2998
|
+
description: "Ажурирања производа и белешке о издањима.",
|
|
2999
|
+
title: "Дневник измена"
|
|
3000
|
+
},
|
|
2346
3001
|
feedback: {
|
|
2347
3002
|
no: "Не",
|
|
2348
3003
|
question: "Да ли вам је ова страница помогла?",
|
|
@@ -2350,13 +3005,16 @@ var sr = {
|
|
|
2350
3005
|
yes: "Да"
|
|
2351
3006
|
},
|
|
2352
3007
|
languageSwitcher: { label: "Језик", untranslated: "Није преведено" },
|
|
3008
|
+
nav: { breadcrumb: "Путања навигације" },
|
|
2353
3009
|
page: {
|
|
2354
3010
|
lastUpdated: "Последње ажурирање",
|
|
2355
3011
|
next: "Следеће",
|
|
3012
|
+
pagination: "Пагинација",
|
|
2356
3013
|
previous: "Претходно",
|
|
2357
3014
|
skipToContent: "Пређи на садржај"
|
|
2358
3015
|
},
|
|
2359
3016
|
search: {
|
|
3017
|
+
all: "Све",
|
|
2360
3018
|
button: "Претражи",
|
|
2361
3019
|
devOnly: "Претрага је доступна у продукцијској верзији.",
|
|
2362
3020
|
label: "Претражи документацију",
|
|
@@ -2389,6 +3047,11 @@ var sv = {
|
|
|
2389
3047
|
send: "Skicka",
|
|
2390
3048
|
title: "Fråga AI"
|
|
2391
3049
|
},
|
|
3050
|
+
banner: { dismiss: "Stäng meddelandet" },
|
|
3051
|
+
changelog: {
|
|
3052
|
+
description: "Produktuppdateringar och versionsinformation.",
|
|
3053
|
+
title: "Ändringslogg"
|
|
3054
|
+
},
|
|
2392
3055
|
feedback: {
|
|
2393
3056
|
no: "Nej",
|
|
2394
3057
|
question: "Var den här sidan till hjälp?",
|
|
@@ -2396,13 +3059,16 @@ var sv = {
|
|
|
2396
3059
|
yes: "Ja"
|
|
2397
3060
|
},
|
|
2398
3061
|
languageSwitcher: { label: "Språk", untranslated: "Inte översatt" },
|
|
3062
|
+
nav: { breadcrumb: "Brödsmulor" },
|
|
2399
3063
|
page: {
|
|
2400
3064
|
lastUpdated: "Senast uppdaterad",
|
|
2401
3065
|
next: "Nästa",
|
|
3066
|
+
pagination: "Paginering",
|
|
2402
3067
|
previous: "Föregående",
|
|
2403
3068
|
skipToContent: "Hoppa till innehåll"
|
|
2404
3069
|
},
|
|
2405
3070
|
search: {
|
|
3071
|
+
all: "Alla",
|
|
2406
3072
|
button: "Sök",
|
|
2407
3073
|
devOnly: "Sökning är tillgänglig i produktionsbygget.",
|
|
2408
3074
|
label: "Sök i dokumentationen",
|
|
@@ -2435,6 +3101,11 @@ var th = {
|
|
|
2435
3101
|
send: "ส่ง",
|
|
2436
3102
|
title: "ถาม AI"
|
|
2437
3103
|
},
|
|
3104
|
+
banner: { dismiss: "ปิดประกาศ" },
|
|
3105
|
+
changelog: {
|
|
3106
|
+
description: "อัปเดตผลิตภัณฑ์และบันทึกประจำรุ่น",
|
|
3107
|
+
title: "บันทึกการเปลี่ยนแปลง"
|
|
3108
|
+
},
|
|
2438
3109
|
feedback: {
|
|
2439
3110
|
no: "ไม่",
|
|
2440
3111
|
question: "หน้านี้มีประโยชน์หรือไม่?",
|
|
@@ -2442,13 +3113,16 @@ var th = {
|
|
|
2442
3113
|
yes: "ใช่"
|
|
2443
3114
|
},
|
|
2444
3115
|
languageSwitcher: { label: "ภาษา", untranslated: "ยังไม่ได้แปล" },
|
|
3116
|
+
nav: { breadcrumb: "เส้นทางนำทาง" },
|
|
2445
3117
|
page: {
|
|
2446
3118
|
lastUpdated: "อัปเดตล่าสุดเมื่อ",
|
|
2447
3119
|
next: "ถัดไป",
|
|
3120
|
+
pagination: "การแบ่งหน้า",
|
|
2448
3121
|
previous: "ก่อนหน้า",
|
|
2449
3122
|
skipToContent: "ข้ามไปยังเนื้อหา"
|
|
2450
3123
|
},
|
|
2451
3124
|
search: {
|
|
3125
|
+
all: "ทั้งหมด",
|
|
2452
3126
|
button: "ค้นหา",
|
|
2453
3127
|
devOnly: "การค้นหาพร้อมใช้งานในบิลด์โปรดักชัน",
|
|
2454
3128
|
label: "ค้นหาเอกสาร",
|
|
@@ -2481,6 +3155,11 @@ var tr = {
|
|
|
2481
3155
|
send: "Gönder",
|
|
2482
3156
|
title: "Yapay zekâya sor"
|
|
2483
3157
|
},
|
|
3158
|
+
banner: { dismiss: "Duyuruyu kapat" },
|
|
3159
|
+
changelog: {
|
|
3160
|
+
description: "Ürün güncellemeleri ve sürüm notları.",
|
|
3161
|
+
title: "Değişiklik günlüğü"
|
|
3162
|
+
},
|
|
2484
3163
|
feedback: {
|
|
2485
3164
|
no: "Hayır",
|
|
2486
3165
|
question: "Bu sayfa yardımcı oldu mu?",
|
|
@@ -2488,13 +3167,16 @@ var tr = {
|
|
|
2488
3167
|
yes: "Evet"
|
|
2489
3168
|
},
|
|
2490
3169
|
languageSwitcher: { label: "Dil", untranslated: "Çevrilmemiş" },
|
|
3170
|
+
nav: { breadcrumb: "Gezinme yolu" },
|
|
2491
3171
|
page: {
|
|
2492
3172
|
lastUpdated: "Son güncelleme",
|
|
2493
3173
|
next: "Sonraki",
|
|
3174
|
+
pagination: "Sayfalama",
|
|
2494
3175
|
previous: "Önceki",
|
|
2495
3176
|
skipToContent: "İçeriğe geç"
|
|
2496
3177
|
},
|
|
2497
3178
|
search: {
|
|
3179
|
+
all: "Tümü",
|
|
2498
3180
|
button: "Ara",
|
|
2499
3181
|
devOnly: "Arama, üretim derlemesinde kullanılabilir.",
|
|
2500
3182
|
label: "Belgelerde ara",
|
|
@@ -2527,6 +3209,11 @@ var uk = {
|
|
|
2527
3209
|
send: "Надіслати",
|
|
2528
3210
|
title: "Запитати ШІ"
|
|
2529
3211
|
},
|
|
3212
|
+
banner: { dismiss: "Закрити оголошення" },
|
|
3213
|
+
changelog: {
|
|
3214
|
+
description: "Оновлення продукту та примітки до випусків.",
|
|
3215
|
+
title: "Журнал змін"
|
|
3216
|
+
},
|
|
2530
3217
|
feedback: {
|
|
2531
3218
|
no: "Ні",
|
|
2532
3219
|
question: "Чи була ця сторінка корисною?",
|
|
@@ -2534,13 +3221,16 @@ var uk = {
|
|
|
2534
3221
|
yes: "Так"
|
|
2535
3222
|
},
|
|
2536
3223
|
languageSwitcher: { label: "Мова", untranslated: "Не перекладено" },
|
|
3224
|
+
nav: { breadcrumb: "Навігаційний ланцюжок" },
|
|
2537
3225
|
page: {
|
|
2538
3226
|
lastUpdated: "Останнє оновлення",
|
|
2539
3227
|
next: "Далі",
|
|
3228
|
+
pagination: "Пагінація",
|
|
2540
3229
|
previous: "Назад",
|
|
2541
3230
|
skipToContent: "Перейти до вмісту"
|
|
2542
3231
|
},
|
|
2543
3232
|
search: {
|
|
3233
|
+
all: "Усі",
|
|
2544
3234
|
button: "Пошук",
|
|
2545
3235
|
devOnly: "Пошук доступний у production-збірці.",
|
|
2546
3236
|
label: "Пошук у документації",
|
|
@@ -2573,6 +3263,11 @@ var vi = {
|
|
|
2573
3263
|
send: "Gửi",
|
|
2574
3264
|
title: "Hỏi AI"
|
|
2575
3265
|
},
|
|
3266
|
+
banner: { dismiss: "Đóng thông báo" },
|
|
3267
|
+
changelog: {
|
|
3268
|
+
description: "Cập nhật sản phẩm và ghi chú phát hành.",
|
|
3269
|
+
title: "Nhật ký thay đổi"
|
|
3270
|
+
},
|
|
2576
3271
|
feedback: {
|
|
2577
3272
|
no: "Không",
|
|
2578
3273
|
question: "Trang này có hữu ích không?",
|
|
@@ -2580,13 +3275,16 @@ var vi = {
|
|
|
2580
3275
|
yes: "Có"
|
|
2581
3276
|
},
|
|
2582
3277
|
languageSwitcher: { label: "Ngôn ngữ", untranslated: "Chưa dịch" },
|
|
3278
|
+
nav: { breadcrumb: "Đường dẫn điều hướng" },
|
|
2583
3279
|
page: {
|
|
2584
3280
|
lastUpdated: "Cập nhật lần cuối",
|
|
2585
3281
|
next: "Tiếp theo",
|
|
3282
|
+
pagination: "Phân trang",
|
|
2586
3283
|
previous: "Trước",
|
|
2587
3284
|
skipToContent: "Chuyển đến nội dung"
|
|
2588
3285
|
},
|
|
2589
3286
|
search: {
|
|
3287
|
+
all: "Tất cả",
|
|
2590
3288
|
button: "Tìm kiếm",
|
|
2591
3289
|
devOnly: "Tìm kiếm có sẵn trong bản dựng production.",
|
|
2592
3290
|
label: "Tìm kiếm tài liệu",
|
|
@@ -2619,6 +3317,11 @@ var zhTW = {
|
|
|
2619
3317
|
send: "傳送",
|
|
2620
3318
|
title: "向 AI 提問"
|
|
2621
3319
|
},
|
|
3320
|
+
banner: { dismiss: "關閉公告" },
|
|
3321
|
+
changelog: {
|
|
3322
|
+
description: "產品更新與版本說明。",
|
|
3323
|
+
title: "更新日誌"
|
|
3324
|
+
},
|
|
2622
3325
|
feedback: {
|
|
2623
3326
|
no: "沒有幫助",
|
|
2624
3327
|
question: "這個頁面有幫助嗎?",
|
|
@@ -2626,13 +3329,16 @@ var zhTW = {
|
|
|
2626
3329
|
yes: "有幫助"
|
|
2627
3330
|
},
|
|
2628
3331
|
languageSwitcher: { label: "語言", untranslated: "未翻譯" },
|
|
3332
|
+
nav: { breadcrumb: "麵包屑導覽" },
|
|
2629
3333
|
page: {
|
|
2630
3334
|
lastUpdated: "最後更新於",
|
|
2631
3335
|
next: "下一頁",
|
|
3336
|
+
pagination: "分頁",
|
|
2632
3337
|
previous: "上一頁",
|
|
2633
3338
|
skipToContent: "跳至內容"
|
|
2634
3339
|
},
|
|
2635
3340
|
search: {
|
|
3341
|
+
all: "全部",
|
|
2636
3342
|
button: "搜尋",
|
|
2637
3343
|
devOnly: "搜尋在正式版組建中可用。",
|
|
2638
3344
|
label: "搜尋文件",
|
|
@@ -2665,6 +3371,11 @@ var zh = {
|
|
|
2665
3371
|
send: "发送",
|
|
2666
3372
|
title: "向 AI 提问"
|
|
2667
3373
|
},
|
|
3374
|
+
banner: { dismiss: "关闭公告" },
|
|
3375
|
+
changelog: {
|
|
3376
|
+
description: "产品更新与版本说明。",
|
|
3377
|
+
title: "更新日志"
|
|
3378
|
+
},
|
|
2668
3379
|
feedback: {
|
|
2669
3380
|
no: "没有帮助",
|
|
2670
3381
|
question: "这个页面有帮助吗?",
|
|
@@ -2672,13 +3383,16 @@ var zh = {
|
|
|
2672
3383
|
yes: "有帮助"
|
|
2673
3384
|
},
|
|
2674
3385
|
languageSwitcher: { label: "语言", untranslated: "未翻译" },
|
|
3386
|
+
nav: { breadcrumb: "面包屑导航" },
|
|
2675
3387
|
page: {
|
|
2676
3388
|
lastUpdated: "最后更新于",
|
|
2677
3389
|
next: "下一页",
|
|
3390
|
+
pagination: "分页",
|
|
2678
3391
|
previous: "上一页",
|
|
2679
3392
|
skipToContent: "跳到内容"
|
|
2680
3393
|
},
|
|
2681
3394
|
search: {
|
|
3395
|
+
all: "全部",
|
|
2682
3396
|
button: "搜索",
|
|
2683
3397
|
devOnly: "搜索在生产构建中可用。",
|
|
2684
3398
|
label: "搜索文档",
|
|
@@ -2745,10 +3459,10 @@ var localizeRoute = (logicalRoute, code, i18n) => {
|
|
|
2745
3459
|
return logicalRoute === "/" ? prefix : `${prefix}${logicalRoute}`;
|
|
2746
3460
|
};
|
|
2747
3461
|
var detectLocale = (parts, i18n) => {
|
|
2748
|
-
const
|
|
2749
|
-
const
|
|
2750
|
-
if (
|
|
2751
|
-
return { locale:
|
|
3462
|
+
const first = parts[0]?.toLowerCase();
|
|
3463
|
+
const matched = i18n.locales.find((locale) => locale.code !== i18n.defaultLocale && locale.code.toLowerCase() === first);
|
|
3464
|
+
if (matched) {
|
|
3465
|
+
return { locale: matched.code, rest: parts.slice(1) };
|
|
2752
3466
|
}
|
|
2753
3467
|
return { locale: i18n.defaultLocale, rest: parts };
|
|
2754
3468
|
};
|
|
@@ -2763,11 +3477,11 @@ var localePlacement = (rel, ext, i18n) => {
|
|
|
2763
3477
|
if (i18n.parser === "dot") {
|
|
2764
3478
|
const lastDot = base.lastIndexOf(".");
|
|
2765
3479
|
if (lastDot > base.lastIndexOf("/")) {
|
|
2766
|
-
const suffix = base.slice(lastDot + 1);
|
|
2767
|
-
const matched = i18n.locales.
|
|
3480
|
+
const suffix = base.slice(lastDot + 1).toLowerCase();
|
|
3481
|
+
const matched = i18n.locales.find((locale2) => locale2.code.toLowerCase() === suffix);
|
|
2768
3482
|
if (matched) {
|
|
2769
3483
|
return {
|
|
2770
|
-
locales: [
|
|
3484
|
+
locales: [matched.code],
|
|
2771
3485
|
navPath: `${base.slice(0, lastDot)}${ext}`
|
|
2772
3486
|
};
|
|
2773
3487
|
}
|
|
@@ -2903,9 +3617,16 @@ var toPlainText = (markdown) => {
|
|
|
2903
3617
|
};
|
|
2904
3618
|
var buildCrumbIndex = (sidebar) => {
|
|
2905
3619
|
const index = new Map;
|
|
3620
|
+
const groupRoutes = new Map;
|
|
2906
3621
|
const walk = (nodes, trail) => {
|
|
2907
3622
|
for (const node of nodes) {
|
|
2908
3623
|
if (node.kind === "group") {
|
|
3624
|
+
if (node.route && !groupRoutes.has(node.route)) {
|
|
3625
|
+
groupRoutes.set(node.route, {
|
|
3626
|
+
breadcrumb: [...trail, node.label],
|
|
3627
|
+
section: node.label
|
|
3628
|
+
});
|
|
3629
|
+
}
|
|
2909
3630
|
walk(node.children, [...trail, node.label]);
|
|
2910
3631
|
} else if (node.route) {
|
|
2911
3632
|
index.set(node.route, {
|
|
@@ -2916,6 +3637,11 @@ var buildCrumbIndex = (sidebar) => {
|
|
|
2916
3637
|
}
|
|
2917
3638
|
};
|
|
2918
3639
|
walk(sidebar, []);
|
|
3640
|
+
for (const [route, crumbs] of groupRoutes) {
|
|
3641
|
+
if (!index.has(route)) {
|
|
3642
|
+
index.set(route, crumbs);
|
|
3643
|
+
}
|
|
3644
|
+
}
|
|
2919
3645
|
return index;
|
|
2920
3646
|
};
|
|
2921
3647
|
var buildSearchDocuments = async (project, options) => {
|
|
@@ -2939,7 +3665,8 @@ var buildSearchDocuments = async (project, options) => {
|
|
|
2939
3665
|
const page = pageById.get(route.id);
|
|
2940
3666
|
const raw = page ? await readEntryText(project, page) : "";
|
|
2941
3667
|
const source = raw ? frontmatter_default(raw).content : "";
|
|
2942
|
-
const
|
|
3668
|
+
const visible = applyAudienceVisibility(source, options?.audience ?? "web");
|
|
3669
|
+
const body = options?.content === "markdown" ? visible.trim() : toPlainText(visible);
|
|
2943
3670
|
const tags = page?.meta?.search?.tags;
|
|
2944
3671
|
const crumb = crumbs.get(route.path);
|
|
2945
3672
|
return {
|
|
@@ -3235,10 +3962,11 @@ var updateDevLockPort = (outDir, port) => {
|
|
|
3235
3962
|
}
|
|
3236
3963
|
};
|
|
3237
3964
|
var describeDevLock = (lock) => lock.port === undefined ? "" : ` at http://localhost:${lock.port}`;
|
|
3238
|
-
var refuseIfDevRunning = (root, action,
|
|
3239
|
-
const lock = readDevLock(resolveRuntimeDir(root, runtimeDir));
|
|
3965
|
+
var refuseIfDevRunning = (root, action, options = {}) => {
|
|
3966
|
+
const lock = readDevLock(resolveRuntimeDir(root, options.runtimeDir));
|
|
3240
3967
|
if (lock) {
|
|
3241
|
-
|
|
3968
|
+
const remedies = options.isolatedHint ? "Reuse that server, stop it first, or re-run with --isolated to build/verify against .blume-verify without touching it." : "Reuse that server or stop it first.";
|
|
3969
|
+
logger.error(`A \`blume dev\` server is running${describeDevLock(lock)}; ${action} would corrupt its .blume runtime. ${remedies}`);
|
|
3242
3970
|
process.exit(1);
|
|
3243
3971
|
}
|
|
3244
3972
|
};
|
|
@@ -3262,6 +3990,7 @@ import { glob as glob5 } from "tinyglobby";
|
|
|
3262
3990
|
// src/ai/ask-data.ts
|
|
3263
3991
|
var buildAskData = async (project) => {
|
|
3264
3992
|
const documents = await buildSearchDocuments(project, {
|
|
3993
|
+
audience: "agents",
|
|
3265
3994
|
content: "markdown",
|
|
3266
3995
|
includeWhenDisabled: true
|
|
3267
3996
|
});
|
|
@@ -3332,6 +4061,7 @@ var askBackendRuntimeDep = (ask) => {
|
|
|
3332
4061
|
|
|
3333
4062
|
// src/ai/markdown.ts
|
|
3334
4063
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
4064
|
+
var agentMarkdown = (entry) => entry.md ?? entry.mdx;
|
|
3335
4065
|
var buildRawMarkdown = async (project) => {
|
|
3336
4066
|
const pageById = new Map(project.graph.pages.map((page) => [page.id, page]));
|
|
3337
4067
|
const readRoute = async (route) => {
|
|
@@ -3341,17 +4071,29 @@ var buildRawMarkdown = async (project) => {
|
|
|
3341
4071
|
}
|
|
3342
4072
|
return route.sourcePath ? await readFile4(route.sourcePath, "utf-8") : "";
|
|
3343
4073
|
};
|
|
3344
|
-
const entries = await Promise.all(project.manifest.routes.map(async (route) =>
|
|
4074
|
+
const entries = await Promise.all(project.manifest.routes.map(async (route) => {
|
|
4075
|
+
const source = applyAgentVisibility(await readRoute(route));
|
|
4076
|
+
const md = downlevelComponents(source, project.config.ai.markdownComponents);
|
|
4077
|
+
const entry = md === source ? { mdx: source } : { md, mdx: source };
|
|
4078
|
+
return [route.path, entry];
|
|
4079
|
+
}));
|
|
3345
4080
|
return Object.fromEntries(entries);
|
|
3346
4081
|
};
|
|
3347
4082
|
|
|
3348
4083
|
// src/ai/mcp/data.ts
|
|
3349
4084
|
var buildMcpData = async (project) => {
|
|
3350
4085
|
const { config, graph, manifest } = project;
|
|
3351
|
-
const [documents,
|
|
3352
|
-
buildSearchDocuments(project, {
|
|
4086
|
+
const [documents, rawMarkdown] = await Promise.all([
|
|
4087
|
+
buildSearchDocuments(project, {
|
|
4088
|
+
audience: "agents",
|
|
4089
|
+
includeWhenDisabled: true
|
|
4090
|
+
}),
|
|
3353
4091
|
buildRawMarkdown(project)
|
|
3354
4092
|
]);
|
|
4093
|
+
const pages = Object.fromEntries(Object.entries(rawMarkdown).map(([route, entry]) => [
|
|
4094
|
+
route,
|
|
4095
|
+
agentMarkdown(entry)
|
|
4096
|
+
]));
|
|
3355
4097
|
const descriptionById = new Map(graph.pages.map((page) => [page.id, page.description]));
|
|
3356
4098
|
const routes = [];
|
|
3357
4099
|
for (const route of manifest.routes) {
|
|
@@ -3368,6 +4110,7 @@ var buildMcpData = async (project) => {
|
|
|
3368
4110
|
});
|
|
3369
4111
|
}
|
|
3370
4112
|
return {
|
|
4113
|
+
base: normalizeBasePath(config.deployment.base),
|
|
3371
4114
|
documents: documents.map((doc) => ({
|
|
3372
4115
|
content: doc.content,
|
|
3373
4116
|
description: doc.description,
|
|
@@ -3395,7 +4138,7 @@ var MCP_TOOLS = [
|
|
|
3395
4138
|
},
|
|
3396
4139
|
{
|
|
3397
4140
|
annotations: READ_ONLY,
|
|
3398
|
-
description: "Fetch a single documentation page as
|
|
4141
|
+
description: "Fetch a single documentation page as agent-optimized Markdown (frontmatter included, components downleveled to plain Markdown). Pass a route from `search_docs` or `list_pages`, e.g. `/guides/install`.",
|
|
3399
4142
|
name: "get_page",
|
|
3400
4143
|
title: "Get page Markdown"
|
|
3401
4144
|
},
|
|
@@ -3414,7 +4157,10 @@ var MCP_TOOLS = [
|
|
|
3414
4157
|
];
|
|
3415
4158
|
|
|
3416
4159
|
// src/ai/mcp/discovery.ts
|
|
3417
|
-
var serverUrl = (input) =>
|
|
4160
|
+
var serverUrl = (input) => {
|
|
4161
|
+
const path = withBasePath(input.base, input.route);
|
|
4162
|
+
return input.site ? `${input.site.replace(/\/+$/u, "")}${path}` : path;
|
|
4163
|
+
};
|
|
3418
4164
|
var buildMcpDiscovery = (input) => ({
|
|
3419
4165
|
servers: [
|
|
3420
4166
|
{
|
|
@@ -3504,7 +4250,7 @@ var validateUsedComponents = (pages, extraTags, registryNames) => {
|
|
|
3504
4250
|
|
|
3505
4251
|
// src/core/component-overrides.ts
|
|
3506
4252
|
import { existsSync as existsSync7 } from "node:fs";
|
|
3507
|
-
import { dirname as dirname5, extname, isAbsolute as isAbsolute2, resolve as resolve3 } from "pathe";
|
|
4253
|
+
import { dirname as dirname5, extname as extname2, isAbsolute as isAbsolute2, resolve as resolve3 } from "pathe";
|
|
3508
4254
|
import ts from "typescript";
|
|
3509
4255
|
var GROUPS = ["mdx", "layout", "islands"];
|
|
3510
4256
|
var GROUP_SET = new Set(GROUPS);
|
|
@@ -3603,17 +4349,17 @@ var probeExtension = (base) => {
|
|
|
3603
4349
|
return null;
|
|
3604
4350
|
};
|
|
3605
4351
|
var toImport = (specifier, imported, dir) => {
|
|
3606
|
-
const
|
|
4352
|
+
const relative5 = specifier.startsWith(".") || isAbsolute2(specifier);
|
|
3607
4353
|
let path = specifier;
|
|
3608
|
-
let extension =
|
|
3609
|
-
if (
|
|
4354
|
+
let extension = extname2(specifier).slice(1).toLowerCase();
|
|
4355
|
+
if (relative5) {
|
|
3610
4356
|
const absolute = isAbsolute2(specifier) ? specifier : resolve3(dir, specifier);
|
|
3611
4357
|
if (extension) {
|
|
3612
4358
|
path = absolute;
|
|
3613
4359
|
} else {
|
|
3614
4360
|
const probed = probeExtension(absolute);
|
|
3615
4361
|
path = probed ?? absolute;
|
|
3616
|
-
extension = probed ?
|
|
4362
|
+
extension = probed ? extname2(probed).slice(1).toLowerCase() : "";
|
|
3617
4363
|
}
|
|
3618
4364
|
}
|
|
3619
4365
|
return {
|
|
@@ -3779,14 +4525,20 @@ var uiStringsObject = z.object({
|
|
|
3779
4525
|
connectMcp: z.string().default("Connect to MCP"),
|
|
3780
4526
|
copied: z.string().default("Copied!"),
|
|
3781
4527
|
copyClaudeCode: z.string().default("Copy Claude Code command"),
|
|
4528
|
+
copyCode: z.string().default("Copy code"),
|
|
3782
4529
|
copyCodex: z.string().default("Copy Codex command"),
|
|
3783
4530
|
copyMarkdown: z.string().default("Copy as Markdown"),
|
|
3784
4531
|
copyServerUrl: z.string().default("Copy server URL"),
|
|
3785
4532
|
edit: z.string().default("Edit on GitHub"),
|
|
4533
|
+
export: z.string().default("Export"),
|
|
4534
|
+
exportEpub: z.string().default("Export to EPUB"),
|
|
4535
|
+
exportPdf: z.string().default("Export to PDF"),
|
|
4536
|
+
generating: z.string().default("Generating…"),
|
|
3786
4537
|
openInChat: z.string().default("Open in chat"),
|
|
3787
4538
|
scrollToTop: z.string().default("Scroll to top")
|
|
3788
4539
|
}).default({}),
|
|
3789
4540
|
ask: z.object({
|
|
4541
|
+
ai: z.string().default("AI"),
|
|
3790
4542
|
clear: z.string().default("Clear conversation"),
|
|
3791
4543
|
close: z.string().default("Close"),
|
|
3792
4544
|
copy: z.string().default("Copy conversation"),
|
|
@@ -3796,7 +4548,19 @@ var uiStringsObject = z.object({
|
|
|
3796
4548
|
placeholder: z.string().default("Ask a question…"),
|
|
3797
4549
|
send: z.string().default("Send"),
|
|
3798
4550
|
tip: z.string().default("Tip: You can open and close chat with"),
|
|
3799
|
-
title: z.string().default("Ask AI")
|
|
4551
|
+
title: z.string().default("Ask AI"),
|
|
4552
|
+
you: z.string().default("You")
|
|
4553
|
+
}).default({}),
|
|
4554
|
+
banner: z.object({
|
|
4555
|
+
dismiss: z.string().default("Dismiss announcement")
|
|
4556
|
+
}).default({}),
|
|
4557
|
+
changelog: z.object({
|
|
4558
|
+
description: z.string().default("Product updates, new features, and fixes from every release."),
|
|
4559
|
+
showReleases: z.string().default("Show {version} releases"),
|
|
4560
|
+
title: z.string().default("Changelog")
|
|
4561
|
+
}).default({}),
|
|
4562
|
+
content: z.object({
|
|
4563
|
+
diagramError: z.string().default("Could not render this diagram.")
|
|
3800
4564
|
}).default({}),
|
|
3801
4565
|
feedback: z.object({
|
|
3802
4566
|
no: z.string().default("No"),
|
|
@@ -3808,6 +4572,19 @@ var uiStringsObject = z.object({
|
|
|
3808
4572
|
label: z.string().default("Language"),
|
|
3809
4573
|
untranslated: z.string().default("Not translated")
|
|
3810
4574
|
}).default({}),
|
|
4575
|
+
nav: z.object({
|
|
4576
|
+
back: z.string().default("Back"),
|
|
4577
|
+
breadcrumb: z.string().default("Breadcrumb"),
|
|
4578
|
+
closeNavigation: z.string().default("Close navigation"),
|
|
4579
|
+
deprecated: z.string().default("deprecated"),
|
|
4580
|
+
featured: z.string().default("Featured"),
|
|
4581
|
+
githubRepository: z.string().default("GitHub repository"),
|
|
4582
|
+
navigation: z.string().default("Navigation"),
|
|
4583
|
+
primary: z.string().default("Primary"),
|
|
4584
|
+
sections: z.string().default("Sections"),
|
|
4585
|
+
toggleNavigation: z.string().default("Toggle navigation"),
|
|
4586
|
+
toggleTheme: z.string().default("Toggle color theme")
|
|
4587
|
+
}).default({}),
|
|
3811
4588
|
notFound: z.object({
|
|
3812
4589
|
description: z.string().default("We couldn't find the page you're looking for."),
|
|
3813
4590
|
home: z.string().default("Back to home"),
|
|
@@ -3816,16 +4593,26 @@ var uiStringsObject = z.object({
|
|
|
3816
4593
|
page: z.object({
|
|
3817
4594
|
lastUpdated: z.string().default("Last updated on"),
|
|
3818
4595
|
next: z.string().default("Next"),
|
|
4596
|
+
pagination: z.string().default("Pagination"),
|
|
3819
4597
|
previous: z.string().default("Previous"),
|
|
3820
4598
|
skipToContent: z.string().default("Skip to content")
|
|
3821
4599
|
}).default({}),
|
|
3822
4600
|
search: z.object({
|
|
4601
|
+
all: z.string().default("All"),
|
|
3823
4602
|
allLanguages: z.string().default("All languages"),
|
|
4603
|
+
askAi: z.string().default("Ask AI"),
|
|
4604
|
+
askAiHint: z.string().default("Get an instant answer from AI"),
|
|
3824
4605
|
button: z.string().default("Search"),
|
|
3825
4606
|
devOnly: z.string().default("Search is available in the production build."),
|
|
4607
|
+
error: z.string().default("Something went wrong. Please try again."),
|
|
3826
4608
|
label: z.string().default("Search docs"),
|
|
4609
|
+
navigate: z.string().default("navigate"),
|
|
3827
4610
|
noResults: z.string().default("No results found."),
|
|
3828
|
-
|
|
4611
|
+
open: z.string().default("open"),
|
|
4612
|
+
placeholder: z.string().default("Search documentation…"),
|
|
4613
|
+
popular: z.string().default("Popular"),
|
|
4614
|
+
preview: z.string().default("preview"),
|
|
4615
|
+
results: z.string().default("Results")
|
|
3829
4616
|
}).default({}),
|
|
3830
4617
|
toc: z.object({
|
|
3831
4618
|
title: z.string().default("On this page")
|
|
@@ -4060,7 +4847,7 @@ var sourcesOf = (block) => {
|
|
|
4060
4847
|
}
|
|
4061
4848
|
return sources;
|
|
4062
4849
|
};
|
|
4063
|
-
var referencesFor = (kind, block, defaultLabel, renderer, display) => {
|
|
4850
|
+
var referencesFor = (kind, block, defaultLabel, renderer, display, basePath) => {
|
|
4064
4851
|
if (!block.enabled) {
|
|
4065
4852
|
return [];
|
|
4066
4853
|
}
|
|
@@ -4078,6 +4865,7 @@ var referencesFor = (kind, block, defaultLabel, renderer, display) => {
|
|
|
4078
4865
|
route = normalizeRoute(`${base}/${suffix || index + 1}`);
|
|
4079
4866
|
}
|
|
4080
4867
|
return {
|
|
4868
|
+
basePath,
|
|
4081
4869
|
display,
|
|
4082
4870
|
kind,
|
|
4083
4871
|
label,
|
|
@@ -4094,8 +4882,8 @@ var resolveReferences = (config) => [
|
|
|
4094
4882
|
...referencesFor("openapi", config.openapi, "API Reference", config.openapi.renderer, {
|
|
4095
4883
|
codeSamples: config.openapi.codeSamples,
|
|
4096
4884
|
expandSchemas: config.openapi.expandSchemas
|
|
4097
|
-
}),
|
|
4098
|
-
...referencesFor("asyncapi", config.asyncapi, "Events", "scalar", NO_DISPLAY)
|
|
4885
|
+
}, config.basePath),
|
|
4886
|
+
...referencesFor("asyncapi", config.asyncapi, "Events", "scalar", NO_DISPLAY, config.basePath)
|
|
4099
4887
|
];
|
|
4100
4888
|
var referenceTabs = (config) => resolveReferences(config).map((ref) => ({
|
|
4101
4889
|
label: ref.label,
|
|
@@ -4105,10 +4893,11 @@ var blumeReferenceOf = (ref, seen, usedSlugs) => {
|
|
|
4105
4893
|
if (ref.kind !== "openapi" || ref.renderer !== "blume") {
|
|
4106
4894
|
return null;
|
|
4107
4895
|
}
|
|
4108
|
-
|
|
4896
|
+
const kept = seen.get(ref.route);
|
|
4897
|
+
if (kept) {
|
|
4898
|
+
(kept.collisions ??= []).push(`Two API reference sources resolve to ${ref.route}; keeping the first.`);
|
|
4109
4899
|
return null;
|
|
4110
4900
|
}
|
|
4111
|
-
seen.add(ref.route);
|
|
4112
4901
|
let { slug } = ref;
|
|
4113
4902
|
let n = 2;
|
|
4114
4903
|
while (usedSlugs.has(slug)) {
|
|
@@ -4116,10 +4905,12 @@ var blumeReferenceOf = (ref, seen, usedSlugs) => {
|
|
|
4116
4905
|
n += 1;
|
|
4117
4906
|
}
|
|
4118
4907
|
usedSlugs.add(slug);
|
|
4119
|
-
|
|
4908
|
+
const accepted = slug === ref.slug ? ref : { ...ref, slug };
|
|
4909
|
+
seen.set(ref.route, accepted);
|
|
4910
|
+
return accepted;
|
|
4120
4911
|
};
|
|
4121
4912
|
var blumeReferences = (config) => {
|
|
4122
|
-
const seen = new
|
|
4913
|
+
const seen = new Map;
|
|
4123
4914
|
const usedSlugs = new Set;
|
|
4124
4915
|
const result = [];
|
|
4125
4916
|
for (const ref of resolveReferences(config)) {
|
|
@@ -4243,9 +5034,14 @@ var extractOperations = (document, baseRoute) => {
|
|
|
4243
5034
|
const tagsSeen = new Set;
|
|
4244
5035
|
const tagMeta = new Map((document.tags ?? []).map((tag) => [tag.name, tag.description ?? ""]));
|
|
4245
5036
|
const seen = new Set;
|
|
5037
|
+
const warnings = [];
|
|
4246
5038
|
for (const [path, rawItem] of Object.entries(document.paths ?? {})) {
|
|
4247
5039
|
const item = rawItem;
|
|
4248
|
-
if (!item
|
|
5040
|
+
if (!item) {
|
|
5041
|
+
continue;
|
|
5042
|
+
}
|
|
5043
|
+
if ("$ref" in item) {
|
|
5044
|
+
warnings.push(`Path "${path}" is a $ref to a shared path item; referenced path items are not resolved, so its operations are missing from the reference. Inline the path item under "paths" to render it.`);
|
|
4249
5045
|
continue;
|
|
4250
5046
|
}
|
|
4251
5047
|
for (const method of HTTP_METHODS) {
|
|
@@ -4283,7 +5079,7 @@ var extractOperations = (document, baseRoute) => {
|
|
|
4283
5079
|
name,
|
|
4284
5080
|
slug: slugify2(name) || "operations"
|
|
4285
5081
|
}));
|
|
4286
|
-
return { operations, tags };
|
|
5082
|
+
return { operations, tags, warnings };
|
|
4287
5083
|
};
|
|
4288
5084
|
|
|
4289
5085
|
// src/openapi/parse.ts
|
|
@@ -4307,6 +5103,13 @@ var PROXY_ENV_VARS = [
|
|
|
4307
5103
|
"ALL_PROXY",
|
|
4308
5104
|
"all_proxy"
|
|
4309
5105
|
];
|
|
5106
|
+
|
|
5107
|
+
class InvalidSpecError extends Error {
|
|
5108
|
+
constructor(message) {
|
|
5109
|
+
super(message);
|
|
5110
|
+
this.name = "InvalidSpecError";
|
|
5111
|
+
}
|
|
5112
|
+
}
|
|
4310
5113
|
var proxyInstalled = false;
|
|
4311
5114
|
var ensureProxyDispatcher = async () => {
|
|
4312
5115
|
if (proxyInstalled || !PROXY_ENV_VARS.some((name) => process.env[name])) {
|
|
@@ -4417,6 +5220,9 @@ var parseSpec = async (spec, root, options = {}) => {
|
|
|
4417
5220
|
const { text, warnings } = await readSpecText(spec, root, options);
|
|
4418
5221
|
const normalized = normalize2(text);
|
|
4419
5222
|
const { specification } = upgrade(normalized);
|
|
5223
|
+
if (specification === null || typeof specification !== "object") {
|
|
5224
|
+
throw new InvalidSpecError(`${spec} is not a valid OpenAPI document (expected a YAML or JSON object).`);
|
|
5225
|
+
}
|
|
4420
5226
|
return { document: specification, warnings };
|
|
4421
5227
|
};
|
|
4422
5228
|
|
|
@@ -4442,6 +5248,31 @@ var mdxSafe = (text) => {
|
|
|
4442
5248
|
}
|
|
4443
5249
|
return out + escapeProse(text.slice(cursor));
|
|
4444
5250
|
};
|
|
5251
|
+
var META_DESCRIPTION_MAX = 160;
|
|
5252
|
+
var PARAGRAPH_BREAK = /\n\s*\n/u;
|
|
5253
|
+
var MARKDOWN_LINK = /\[(?<text>[^\]]*)\]\([^)]*\)/gu;
|
|
5254
|
+
var MARKDOWN_MARKS = /[*_`#>]/gu;
|
|
5255
|
+
var WHITESPACE2 = /\s+/gu;
|
|
5256
|
+
var TRAILING_WORD = /\s+\S*$/u;
|
|
5257
|
+
var plainProse = (markdown) => (markdown.trim().split(PARAGRAPH_BREAK).at(0) ?? "").replace(MARKDOWN_LINK, "$<text>").replace(MARKDOWN_MARKS, "").replace(WHITESPACE2, " ").trim();
|
|
5258
|
+
var clip = (text, max) => {
|
|
5259
|
+
if (max <= 0) {
|
|
5260
|
+
return "";
|
|
5261
|
+
}
|
|
5262
|
+
if (text.length <= max) {
|
|
5263
|
+
return text;
|
|
5264
|
+
}
|
|
5265
|
+
const head = text.slice(0, max - 1);
|
|
5266
|
+
const onWordBoundary = head.replace(TRAILING_WORD, "");
|
|
5267
|
+
return `${onWordBoundary.length >= max / 2 ? onWordBoundary : head}…`;
|
|
5268
|
+
};
|
|
5269
|
+
var apiName = (spec) => spec.title || spec.label;
|
|
5270
|
+
var operationDescription = (spec, operation) => {
|
|
5271
|
+
const endpoint = `${operation.method.toUpperCase()} ${operation.path}`;
|
|
5272
|
+
const suffix = `Reference for the ${endpoint} endpoint in the ${apiName(spec)} API.`;
|
|
5273
|
+
const prose = clip(plainProse(operation.description || operation.summary), META_DESCRIPTION_MAX - suffix.length - 1);
|
|
5274
|
+
return clip([prose, suffix].filter(Boolean).join(" "), META_DESCRIPTION_MAX);
|
|
5275
|
+
};
|
|
4445
5276
|
var withDescription = (description, component) => description.trim() ? `${mdxSafe(description.trim())}
|
|
4446
5277
|
|
|
4447
5278
|
${component}` : component;
|
|
@@ -4454,6 +5285,7 @@ var operationMdx = (spec, operation) => {
|
|
|
4454
5285
|
data: {
|
|
4455
5286
|
...operation.deprecated ? { deprecated: true } : {},
|
|
4456
5287
|
search: { tags: [operation.tag, method] },
|
|
5288
|
+
seo: { description: operationDescription(spec, operation) },
|
|
4457
5289
|
sidebar: { badge: method, label: operation.summary || operation.path },
|
|
4458
5290
|
title,
|
|
4459
5291
|
type: "openapi-operation"
|
|
@@ -4502,8 +5334,11 @@ var overviewMdx = (spec) => {
|
|
|
4502
5334
|
|
|
4503
5335
|
`),
|
|
4504
5336
|
data: {
|
|
5337
|
+
seo: {
|
|
5338
|
+
description: clip(plainProse(spec.description), META_DESCRIPTION_MAX) || `${apiName(spec)} API reference.`
|
|
5339
|
+
},
|
|
4505
5340
|
sidebar: { label: "Overview" },
|
|
4506
|
-
title: spec
|
|
5341
|
+
title: apiName(spec)
|
|
4507
5342
|
}
|
|
4508
5343
|
};
|
|
4509
5344
|
};
|
|
@@ -4533,7 +5368,11 @@ var openApiSource = (references, ctx) => {
|
|
|
4533
5368
|
const loadReference = async (reference) => {
|
|
4534
5369
|
try {
|
|
4535
5370
|
const { document, warnings } = await parseSpec(reference.spec, ctx.projectRoot, { cacheDir: ctx.cacheDir, refresh: ctx.refresh });
|
|
4536
|
-
const {
|
|
5371
|
+
const {
|
|
5372
|
+
operations,
|
|
5373
|
+
tags,
|
|
5374
|
+
warnings: extractWarnings
|
|
5375
|
+
} = extractOperations(document, reference.route);
|
|
4537
5376
|
const info = document.info ?? { title: reference.label, version: "" };
|
|
4538
5377
|
const spec = {
|
|
4539
5378
|
codeSamples: reference.display.codeSamples,
|
|
@@ -4541,7 +5380,13 @@ var openApiSource = (references, ctx) => {
|
|
|
4541
5380
|
document,
|
|
4542
5381
|
expandSchemas: reference.display.expandSchemas,
|
|
4543
5382
|
label: reference.label,
|
|
4544
|
-
operations: Object.fromEntries(operations.map((operation) => [
|
|
5383
|
+
operations: Object.fromEntries(operations.map((operation) => [
|
|
5384
|
+
operation.key,
|
|
5385
|
+
{
|
|
5386
|
+
...operation,
|
|
5387
|
+
route: withBasePath(reference.basePath, operation.route)
|
|
5388
|
+
}
|
|
5389
|
+
])),
|
|
4545
5390
|
route: reference.route,
|
|
4546
5391
|
slug: reference.slug,
|
|
4547
5392
|
tags,
|
|
@@ -4549,11 +5394,26 @@ var openApiSource = (references, ctx) => {
|
|
|
4549
5394
|
version: info.version ?? ""
|
|
4550
5395
|
};
|
|
4551
5396
|
return {
|
|
4552
|
-
diagnostics:
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
5397
|
+
diagnostics: [
|
|
5398
|
+
...warnings.map((message) => ({
|
|
5399
|
+
code: "BLUME_OPENAPI_STALE",
|
|
5400
|
+
message,
|
|
5401
|
+
severity: "warning"
|
|
5402
|
+
})),
|
|
5403
|
+
...extractWarnings.map((message) => ({
|
|
5404
|
+
code: "BLUME_OPENAPI_REF_PATH_ITEM",
|
|
5405
|
+
message: `In OpenAPI spec "${reference.spec}": ${message}`,
|
|
5406
|
+
severity: "warning"
|
|
5407
|
+
})),
|
|
5408
|
+
...operations.length === 0 ? [
|
|
5409
|
+
{
|
|
5410
|
+
code: "BLUME_OPENAPI_EMPTY",
|
|
5411
|
+
message: `OpenAPI spec "${reference.spec}" for ${reference.route} declares no operations; its API reference is empty.`,
|
|
5412
|
+
severity: "warning",
|
|
5413
|
+
suggestion: "Check the spec points at an OpenAPI document with operations under `paths`."
|
|
5414
|
+
}
|
|
5415
|
+
] : []
|
|
5416
|
+
],
|
|
4557
5417
|
entries: specEntries(spec, operations),
|
|
4558
5418
|
slug: reference.slug,
|
|
4559
5419
|
spec
|
|
@@ -4563,14 +5423,18 @@ var openApiSource = (references, ctx) => {
|
|
|
4563
5423
|
code: "BLUME_OPENAPI_UNAVAILABLE",
|
|
4564
5424
|
message: `Could not load OpenAPI spec "${reference.spec}" for ${reference.route} (${error.message}); its reference pages were skipped.`,
|
|
4565
5425
|
severity: ctx.mode === "build" ? "error" : "warning",
|
|
4566
|
-
suggestion: "Check the spec URL/path is reachable from the build environment; behind a proxy, set HTTP(S)_PROXY."
|
|
5426
|
+
suggestion: error instanceof InvalidSpecError ? "Point the spec at an OpenAPI document (a YAML or JSON file with an object at the top level)." : "Check the spec URL/path is reachable from the build environment; behind a proxy, set HTTP(S)_PROXY."
|
|
4567
5427
|
};
|
|
4568
5428
|
}
|
|
4569
5429
|
};
|
|
4570
5430
|
const load2 = async () => {
|
|
4571
5431
|
const results = await Promise.all(references.map(loadReference));
|
|
4572
5432
|
const entries = [];
|
|
4573
|
-
const diagnostics = []
|
|
5433
|
+
const diagnostics = references.flatMap((reference) => (reference.collisions ?? []).map((message) => ({
|
|
5434
|
+
code: "BLUME_OPENAPI_ROUTE_COLLISION",
|
|
5435
|
+
message,
|
|
5436
|
+
severity: "warning"
|
|
5437
|
+
})));
|
|
4574
5438
|
const data = {};
|
|
4575
5439
|
for (const result of results) {
|
|
4576
5440
|
if ("severity" in result) {
|
|
@@ -4596,8 +5460,8 @@ var openApiSource = (references, ctx) => {
|
|
|
4596
5460
|
// src/core/sources/filesystem.ts
|
|
4597
5461
|
import { existsSync as existsSync8, watch as fsWatch } from "node:fs";
|
|
4598
5462
|
import { readFile as readFile7 } from "node:fs/promises";
|
|
4599
|
-
import { extname as
|
|
4600
|
-
import { glob } from "tinyglobby";
|
|
5463
|
+
import { extname as extname3, isAbsolute as isAbsolute4, join as join12, relative as relative5, resolve as resolve4 } from "pathe";
|
|
5464
|
+
import { glob as glob2 } from "tinyglobby";
|
|
4601
5465
|
|
|
4602
5466
|
// src/core/sources/watch.ts
|
|
4603
5467
|
var BLUME_IGNORE_DIRS = [
|
|
@@ -4627,7 +5491,7 @@ var ignoringWatchListener = (onChange, ignoreDirs = BLUME_WATCH_IGNORE_DIRS) =>
|
|
|
4627
5491
|
var filesystemSource = (options) => {
|
|
4628
5492
|
const contentRoot = isAbsolute4(options.root) ? options.root : join12(resolve4(options.projectRoot), options.root);
|
|
4629
5493
|
const load2 = async () => {
|
|
4630
|
-
const files = await
|
|
5494
|
+
const files = await glob2(options.include, {
|
|
4631
5495
|
absolute: true,
|
|
4632
5496
|
cwd: contentRoot,
|
|
4633
5497
|
ignore: [...options.exclude, ...baselineScanIgnore()],
|
|
@@ -4636,13 +5500,14 @@ var filesystemSource = (options) => {
|
|
|
4636
5500
|
files.sort();
|
|
4637
5501
|
const entries = await Promise.all(files.map(async (file) => {
|
|
4638
5502
|
const source = await readFile7(file, "utf-8");
|
|
4639
|
-
const ext =
|
|
5503
|
+
const ext = extname3(file).toLowerCase();
|
|
4640
5504
|
const format = ext === ".mdx" ? "mdx" : "md";
|
|
4641
5505
|
const parsed = frontmatter_default(source);
|
|
4642
5506
|
return {
|
|
4643
5507
|
body: { format, text: parsed.content },
|
|
4644
5508
|
data: parsed.data,
|
|
4645
|
-
|
|
5509
|
+
raw: source,
|
|
5510
|
+
ref: relative5(contentRoot, file),
|
|
4646
5511
|
sourcePath: file
|
|
4647
5512
|
};
|
|
4648
5513
|
}));
|
|
@@ -4878,14 +5743,9 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
4878
5743
|
const doFetch = options.fetchImpl ?? globalThis.fetch;
|
|
4879
5744
|
const cache = snapshotCache(ctx.cacheDir);
|
|
4880
5745
|
let snapshot = new Map;
|
|
4881
|
-
const
|
|
4882
|
-
if (options.github) {
|
|
4883
|
-
return
|
|
4884
|
-
}
|
|
4885
|
-
if (options.files && options.url) {
|
|
4886
|
-
const base = options.url.replace(/\/$/u, "");
|
|
4887
|
-
const refs = options.files.flatMap((ref) => matchesInclude(ref, options.include) ? [{ editUrl: `${base}/${ref}`, fetchUrl: `${base}/${ref}`, ref }] : []);
|
|
4888
|
-
return { refs, truncated: false };
|
|
5746
|
+
const assertConfigured = () => {
|
|
5747
|
+
if (options.github || options.files && options.url) {
|
|
5748
|
+
return;
|
|
4889
5749
|
}
|
|
4890
5750
|
throw new BlumeError({
|
|
4891
5751
|
code: "BLUME_SOURCE_MISCONFIGURED",
|
|
@@ -4893,6 +5753,14 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
4893
5753
|
severity: "error"
|
|
4894
5754
|
});
|
|
4895
5755
|
};
|
|
5756
|
+
const enumerate = async () => {
|
|
5757
|
+
if (options.github) {
|
|
5758
|
+
return await enumerateGithub(options.github, options.include, doFetch);
|
|
5759
|
+
}
|
|
5760
|
+
const base = (options.url ?? "").replace(/\/$/u, "");
|
|
5761
|
+
const refs = (options.files ?? []).flatMap((ref) => matchesInclude(ref, options.include) ? [{ editUrl: `${base}/${ref}`, fetchUrl: `${base}/${ref}`, ref }] : []);
|
|
5762
|
+
return { refs, truncated: false };
|
|
5763
|
+
};
|
|
4896
5764
|
const fetchEntry = async (item) => {
|
|
4897
5765
|
const res = await doFetch(item.fetchUrl, {
|
|
4898
5766
|
headers: githubHeaders2(item.fetchUrl)
|
|
@@ -4913,6 +5781,7 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
4913
5781
|
};
|
|
4914
5782
|
};
|
|
4915
5783
|
const load2 = async (refresh = ctx.refresh ?? true) => {
|
|
5784
|
+
assertConfigured();
|
|
4916
5785
|
const skipped = [];
|
|
4917
5786
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
4918
5787
|
const { refs, truncated } = await enumerate();
|
|
@@ -4973,22 +5842,22 @@ import { join as join14 } from "pathe";
|
|
|
4973
5842
|
|
|
4974
5843
|
// src/core/sources/assets.ts
|
|
4975
5844
|
import { mkdir as mkdir5, writeFile as writeFile5 } from "node:fs/promises";
|
|
4976
|
-
import { extname as
|
|
5845
|
+
import { extname as extname4, join as join13 } from "pathe";
|
|
4977
5846
|
var MD_IMAGE = /!\[(?<alt>[^\]]*)\]\((?<url>[^)\s]+)\)/gu;
|
|
4978
5847
|
var REMOTE = /^https?:\/\//u;
|
|
4979
5848
|
var SAFE_EXT = /^\.[a-z0-9]+$/iu;
|
|
4980
|
-
var
|
|
4981
|
-
var
|
|
5849
|
+
var CODE_FENCE_BLOCK2 = /^(?<fence>`{3,}|~{3,})[^\n]*\n[\s\S]*?^\k<fence>[^\n]*(?=\n|$)/gmu;
|
|
5850
|
+
var FENCE_TOKEN2 = /\u0000blume-fence-(?<index>\d+)\u0000/gu;
|
|
4982
5851
|
var extFor = (url) => {
|
|
4983
5852
|
const clean = url.split("?")[0] ?? url;
|
|
4984
|
-
const ext =
|
|
5853
|
+
const ext = extname4(clean);
|
|
4985
5854
|
return SAFE_EXT.test(ext) ? ext.toLowerCase() : ".png";
|
|
4986
5855
|
};
|
|
4987
5856
|
var materializeAssets = async (markdown, ctx) => {
|
|
4988
5857
|
const doFetch = ctx.fetchImpl ?? globalThis.fetch;
|
|
4989
5858
|
const diagnostics = [];
|
|
4990
5859
|
const fences = [];
|
|
4991
|
-
const masked = markdown.replace(
|
|
5860
|
+
const masked = markdown.replace(CODE_FENCE_BLOCK2, (block) => {
|
|
4992
5861
|
fences.push(block);
|
|
4993
5862
|
return `\x00blume-fence-${fences.length - 1}\x00`;
|
|
4994
5863
|
});
|
|
@@ -5007,7 +5876,7 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
5007
5876
|
throw new Error(`${res.status}`);
|
|
5008
5877
|
}
|
|
5009
5878
|
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
5010
|
-
const file = `${hashText(url)}${extFor(url)}`;
|
|
5879
|
+
const file = `${hashText(url.split("?")[0] ?? url)}${extFor(url)}`;
|
|
5011
5880
|
await mkdir5(ctx.assetsDir, { recursive: true });
|
|
5012
5881
|
await writeFile5(join13(ctx.assetsDir, file), bytes);
|
|
5013
5882
|
rewrites.set(url, `${ctx.assetsBaseUrl}/${file}`);
|
|
@@ -5022,18 +5891,27 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
5022
5891
|
const rewritten = masked.replaceAll(MD_IMAGE, (match, alt, url) => {
|
|
5023
5892
|
const local = rewrites.get(url);
|
|
5024
5893
|
return local ? `` : match;
|
|
5025
|
-
}).replaceAll(
|
|
5894
|
+
}).replaceAll(FENCE_TOKEN2, (token, index) => fences[Number(index)] ?? token);
|
|
5026
5895
|
return { diagnostics, markdown: rewritten };
|
|
5027
5896
|
};
|
|
5028
5897
|
|
|
5029
5898
|
// src/core/sources/normalize.ts
|
|
5030
5899
|
import { existsSync as existsSync9, readFileSync as readFileSync3 } from "node:fs";
|
|
5031
5900
|
import GithubSlugger from "github-slugger";
|
|
5032
|
-
import { extname as
|
|
5901
|
+
import { extname as extname5 } from "pathe";
|
|
5033
5902
|
|
|
5034
5903
|
// src/core/schema.ts
|
|
5035
5904
|
import { z as z2 } from "zod";
|
|
5036
5905
|
|
|
5906
|
+
// src/seo/x-handle.ts
|
|
5907
|
+
var normalizeXHandle = (value) => {
|
|
5908
|
+
if (typeof value !== "string") {
|
|
5909
|
+
return;
|
|
5910
|
+
}
|
|
5911
|
+
const handle = value.trim().replace(/^@+/u, "");
|
|
5912
|
+
return handle ? `@${handle}` : undefined;
|
|
5913
|
+
};
|
|
5914
|
+
|
|
5037
5915
|
// src/theme/fonts.ts
|
|
5038
5916
|
var FALLBACKS = {
|
|
5039
5917
|
mono: ["ui-monospace", "SF Mono", "Menlo", "monospace"],
|
|
@@ -5191,12 +6069,14 @@ var sidebarMetaSchema = z2.strictObject({
|
|
|
5191
6069
|
label: z2.string().optional(),
|
|
5192
6070
|
order: z2.number().optional()
|
|
5193
6071
|
});
|
|
6072
|
+
var xHandleSchema = z2.string().transform(normalizeXHandle).optional();
|
|
5194
6073
|
var seoMetaSchema = z2.strictObject({
|
|
5195
6074
|
canonical: z2.string().url().optional(),
|
|
5196
6075
|
description: z2.string().optional(),
|
|
5197
6076
|
image: z2.string().optional(),
|
|
5198
6077
|
noindex: z2.boolean().default(false),
|
|
5199
|
-
title: z2.string().optional()
|
|
6078
|
+
title: z2.string().optional(),
|
|
6079
|
+
x: z2.strictObject({ creator: xHandleSchema }).optional()
|
|
5200
6080
|
});
|
|
5201
6081
|
var searchMetaSchema = z2.strictObject({
|
|
5202
6082
|
boost: z2.number().optional(),
|
|
@@ -5503,7 +6383,16 @@ var aiConfigSchema = z2.strictObject({
|
|
|
5503
6383
|
});
|
|
5504
6384
|
}
|
|
5505
6385
|
}).optional(),
|
|
5506
|
-
llmsTxt: z2.
|
|
6386
|
+
llmsTxt: z2.union([
|
|
6387
|
+
z2.boolean(),
|
|
6388
|
+
z2.strictObject({
|
|
6389
|
+
enabled: z2.boolean().default(true),
|
|
6390
|
+
openapi: z2.boolean().default(true)
|
|
6391
|
+
})
|
|
6392
|
+
]).default(true).transform((value) => typeof value === "boolean" ? { enabled: value, openapi: true } : value),
|
|
6393
|
+
markdownComponents: z2.record(z2.string(), z2.custom((value) => typeof value === "function", {
|
|
6394
|
+
message: "Expected a serializer function."
|
|
6395
|
+
})).default({})
|
|
5507
6396
|
});
|
|
5508
6397
|
var featuredLinkSchema = z2.strictObject({
|
|
5509
6398
|
href: z2.string(),
|
|
@@ -5534,7 +6423,7 @@ var mcpConfigSchema = z2.strictObject({
|
|
|
5534
6423
|
enabled: z2.boolean().default(false),
|
|
5535
6424
|
instructions: z2.string().optional(),
|
|
5536
6425
|
name: z2.string().optional(),
|
|
5537
|
-
route: z2.string().default("/mcp")
|
|
6426
|
+
route: z2.string().default("/mcp").transform(normalizeRoute)
|
|
5538
6427
|
});
|
|
5539
6428
|
var localeSchema = z2.strictObject({
|
|
5540
6429
|
code: z2.string().min(1),
|
|
@@ -5592,6 +6481,10 @@ var redirectSchema = z2.strictObject({
|
|
|
5592
6481
|
status: z2.union([z2.literal(301), z2.literal(302), z2.literal(307), z2.literal(308)]).default(301),
|
|
5593
6482
|
to: z2.string()
|
|
5594
6483
|
});
|
|
6484
|
+
var xConfigSchema = z2.strictObject({
|
|
6485
|
+
creator: xHandleSchema,
|
|
6486
|
+
handle: xHandleSchema
|
|
6487
|
+
});
|
|
5595
6488
|
var ogConfigSchema = z2.strictObject({
|
|
5596
6489
|
enabled: z2.boolean().optional()
|
|
5597
6490
|
});
|
|
@@ -5621,7 +6514,8 @@ var seoConfigSchema = z2.strictObject({
|
|
|
5621
6514
|
robots: z2.boolean().default(true),
|
|
5622
6515
|
rss: rssConfigSchema.default({}),
|
|
5623
6516
|
sitemap: z2.boolean().default(true),
|
|
5624
|
-
structuredData: z2.boolean().default(true)
|
|
6517
|
+
structuredData: z2.boolean().default(true),
|
|
6518
|
+
x: xConfigSchema.default({})
|
|
5625
6519
|
});
|
|
5626
6520
|
var githubConfigSchema = z2.strictObject({
|
|
5627
6521
|
branch: z2.string().default("main"),
|
|
@@ -5697,6 +6591,8 @@ var tocConfigSchema = z2.union([
|
|
|
5697
6591
|
maxLevel: value.maxHeadingLevel ?? 3,
|
|
5698
6592
|
minLevel: value.minHeadingLevel ?? 2
|
|
5699
6593
|
};
|
|
6594
|
+
}).refine((value) => value.minLevel <= value.maxLevel, {
|
|
6595
|
+
message: "toc.minHeadingLevel must be less than or equal to toc.maxHeadingLevel."
|
|
5700
6596
|
});
|
|
5701
6597
|
var blumeConfigSchema = z2.strictObject({
|
|
5702
6598
|
ai: aiConfigSchema.default({}),
|
|
@@ -5751,7 +6647,7 @@ var addRouteSegment = (part, segments, groups) => {
|
|
|
5751
6647
|
segments.push(clean);
|
|
5752
6648
|
};
|
|
5753
6649
|
var mapRoute = (relativePath) => {
|
|
5754
|
-
const withoutExt = relativePath.slice(0, relativePath.length -
|
|
6650
|
+
const withoutExt = relativePath.slice(0, relativePath.length - extname5(relativePath).length);
|
|
5755
6651
|
const rawParts = withoutExt.split("/");
|
|
5756
6652
|
const segments = [];
|
|
5757
6653
|
const groups = [];
|
|
@@ -5761,41 +6657,78 @@ var mapRoute = (relativePath) => {
|
|
|
5761
6657
|
const route = segments.length === 0 ? "/" : `/${segments.join("/")}`;
|
|
5762
6658
|
return { groups, route, segments };
|
|
5763
6659
|
};
|
|
5764
|
-
var CODE_FENCE2 =
|
|
5765
|
-
var
|
|
5766
|
-
|
|
5767
|
-
if (
|
|
5768
|
-
return
|
|
6660
|
+
var CODE_FENCE2 = /^(?<delimiter>```|~~~)/u;
|
|
6661
|
+
var nextFenceState = (line, fence) => {
|
|
6662
|
+
const delimiter = line.trimStart().match(CODE_FENCE2)?.groups?.delimiter;
|
|
6663
|
+
if (delimiter === undefined) {
|
|
6664
|
+
return fence;
|
|
6665
|
+
}
|
|
6666
|
+
if (fence === null) {
|
|
6667
|
+
return delimiter;
|
|
6668
|
+
}
|
|
6669
|
+
return fence === delimiter ? null : fence;
|
|
6670
|
+
};
|
|
6671
|
+
var ATX_HEADING = /^ {0,3}(?<hashes>#{1,6})\s+(?<text>.+?)(?:\s+#+)?\s*$/u;
|
|
6672
|
+
var SETEXT_UNDERLINE = /^ {0,3}(?<marker>=+|-+)\s*$/u;
|
|
6673
|
+
var PARAGRAPH_INTERRUPT = /^ {0,3}(?:[-+*][ \t]|\d{1,9}[.)][ \t]|>)/u;
|
|
6674
|
+
var THEMATIC_BREAK = /^ {0,3}(?:(?:-[ \t]*){3,}|(?:\*[ \t]*){3,}|(?:_[ \t]*){3,})$/u;
|
|
6675
|
+
var FRONT_MATTER_CLOSE = /^(?:-{3}|\.{3})\s*$/u;
|
|
6676
|
+
var linesWithoutFrontMatter = (body) => {
|
|
6677
|
+
const lines = body.split(`
|
|
6678
|
+
`);
|
|
6679
|
+
if (!/^-{3}\s*$/u.test(lines[0] ?? "")) {
|
|
6680
|
+
return lines;
|
|
5769
6681
|
}
|
|
5770
|
-
|
|
5771
|
-
|
|
6682
|
+
const close = lines.findIndex((line, index) => index > 0 && FRONT_MATTER_CLOSE.test(line));
|
|
6683
|
+
return close === -1 ? lines : lines.slice(close + 1);
|
|
6684
|
+
};
|
|
6685
|
+
var scanHeadingLine = (line, state, slugger, headings) => {
|
|
6686
|
+
const next = nextFenceState(line, state.fence);
|
|
6687
|
+
if (state.fence !== null || next !== null) {
|
|
6688
|
+
state.fence = next;
|
|
6689
|
+
state.paragraph = [];
|
|
6690
|
+
return;
|
|
5772
6691
|
}
|
|
5773
|
-
const
|
|
5774
|
-
if (
|
|
5775
|
-
const depth =
|
|
5776
|
-
const text = (
|
|
6692
|
+
const atx = line.match(ATX_HEADING);
|
|
6693
|
+
if (atx?.groups) {
|
|
6694
|
+
const depth = atx.groups.hashes?.length ?? 1;
|
|
6695
|
+
const text = (atx.groups.text ?? "").trim();
|
|
5777
6696
|
headings.push({ depth, slug: slugger.slug(text), text });
|
|
6697
|
+
state.paragraph = [];
|
|
6698
|
+
return;
|
|
5778
6699
|
}
|
|
5779
|
-
|
|
6700
|
+
const setext = line.match(SETEXT_UNDERLINE);
|
|
6701
|
+
if (setext?.groups && state.paragraph.length > 0) {
|
|
6702
|
+
const text = state.paragraph.join(" ").trim();
|
|
6703
|
+
headings.push({
|
|
6704
|
+
depth: setext.groups.marker?.startsWith("=") ? 1 : 2,
|
|
6705
|
+
slug: slugger.slug(text),
|
|
6706
|
+
text
|
|
6707
|
+
});
|
|
6708
|
+
state.paragraph = [];
|
|
6709
|
+
return;
|
|
6710
|
+
}
|
|
6711
|
+
if (line.trim() === "" || THEMATIC_BREAK.test(line) || PARAGRAPH_INTERRUPT.test(line)) {
|
|
6712
|
+
state.paragraph = [];
|
|
6713
|
+
return;
|
|
6714
|
+
}
|
|
6715
|
+
state.paragraph.push(line.trim());
|
|
5780
6716
|
};
|
|
5781
6717
|
var extractHeadings = (body) => {
|
|
5782
6718
|
const headings = [];
|
|
5783
6719
|
const slugger = new GithubSlugger;
|
|
5784
|
-
|
|
5785
|
-
for (const line of body
|
|
5786
|
-
|
|
5787
|
-
inFence = scanHeadingLine(line, inFence, slugger, headings);
|
|
6720
|
+
const state = { fence: null, paragraph: [] };
|
|
6721
|
+
for (const line of linesWithoutFrontMatter(body)) {
|
|
6722
|
+
scanHeadingLine(line, state, slugger, headings);
|
|
5788
6723
|
}
|
|
5789
6724
|
return headings;
|
|
5790
6725
|
};
|
|
5791
6726
|
var MD_LINK = /\[[^\]]*\]\((?<target>[^)\s]+)(?:\s+"[^"]*")?\)/gu;
|
|
5792
6727
|
var INLINE_CODE2 = /`[^`]*`/gu;
|
|
5793
|
-
var scanLinkLine = (line, lineNumber,
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
if (inFence) {
|
|
5798
|
-
return inFence;
|
|
6728
|
+
var scanLinkLine = (line, lineNumber, fence, links) => {
|
|
6729
|
+
const next = nextFenceState(line, fence);
|
|
6730
|
+
if (fence !== null || next !== null) {
|
|
6731
|
+
return next;
|
|
5799
6732
|
}
|
|
5800
6733
|
const masked = line.replaceAll(INLINE_CODE2, (span) => " ".repeat(span.length));
|
|
5801
6734
|
for (const match of masked.matchAll(MD_LINK)) {
|
|
@@ -5810,27 +6743,25 @@ var scanLinkLine = (line, lineNumber, inFence, links) => {
|
|
|
5810
6743
|
target
|
|
5811
6744
|
});
|
|
5812
6745
|
}
|
|
5813
|
-
return
|
|
6746
|
+
return next;
|
|
5814
6747
|
};
|
|
5815
|
-
var extractLinks = (body) => {
|
|
6748
|
+
var extractLinks = (body, lineOffset = 0) => {
|
|
5816
6749
|
const links = [];
|
|
5817
|
-
let
|
|
5818
|
-
let lineNumber =
|
|
6750
|
+
let fence = null;
|
|
6751
|
+
let lineNumber = lineOffset;
|
|
5819
6752
|
for (const line of body.split(`
|
|
5820
6753
|
`)) {
|
|
5821
6754
|
lineNumber += 1;
|
|
5822
|
-
|
|
6755
|
+
fence = scanLinkLine(line, lineNumber, fence, links);
|
|
5823
6756
|
}
|
|
5824
6757
|
return links;
|
|
5825
6758
|
};
|
|
5826
6759
|
var DOUBLE_QUOTED = /"[^"]*"/gu;
|
|
5827
6760
|
var JSX_OPEN = /<(?<tag>[A-Z][A-Za-z0-9]*)/gu;
|
|
5828
|
-
var scanTagLine = (line,
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
if (inFence) {
|
|
5833
|
-
return inFence;
|
|
6761
|
+
var scanTagLine = (line, fence, tags) => {
|
|
6762
|
+
const next = nextFenceState(line, fence);
|
|
6763
|
+
if (fence !== null || next !== null) {
|
|
6764
|
+
return next;
|
|
5834
6765
|
}
|
|
5835
6766
|
const clean = line.replaceAll(INLINE_CODE2, "").replaceAll(DOUBLE_QUOTED, "");
|
|
5836
6767
|
for (const match of clean.matchAll(JSX_OPEN)) {
|
|
@@ -5839,17 +6770,20 @@ var scanTagLine = (line, inFence, tags) => {
|
|
|
5839
6770
|
tags.add(tag);
|
|
5840
6771
|
}
|
|
5841
6772
|
}
|
|
5842
|
-
return
|
|
6773
|
+
return next;
|
|
5843
6774
|
};
|
|
5844
6775
|
var extractComponentTags = (body) => {
|
|
5845
6776
|
const tags = new Set;
|
|
5846
|
-
let
|
|
6777
|
+
let fence = null;
|
|
5847
6778
|
for (const line of body.split(`
|
|
5848
6779
|
`)) {
|
|
5849
|
-
|
|
6780
|
+
fence = scanTagLine(line, fence, tags);
|
|
5850
6781
|
}
|
|
5851
6782
|
return [...tags];
|
|
5852
6783
|
};
|
|
6784
|
+
var strippedLineOffset = (raw, body) => raw ? Math.max(0, raw.split(`
|
|
6785
|
+
`).length - body.split(`
|
|
6786
|
+
`).length) : 0;
|
|
5853
6787
|
var deriveTitle = (meta, headings, id2) => {
|
|
5854
6788
|
if (meta.title) {
|
|
5855
6789
|
return meta.title;
|
|
@@ -5859,7 +6793,7 @@ var deriveTitle = (meta, headings, id2) => {
|
|
|
5859
6793
|
return firstHeading.text;
|
|
5860
6794
|
}
|
|
5861
6795
|
const base = id2.split("/").pop() ?? id2;
|
|
5862
|
-
return titleCase(stripNumericPrefix(base.replace(
|
|
6796
|
+
return titleCase(stripNumericPrefix(base.replace(extname5(base), "")));
|
|
5863
6797
|
};
|
|
5864
6798
|
var trimSlashes = (value) => value.replaceAll(/^\/+|\/+$/gu, "");
|
|
5865
6799
|
var withPrefix = (prefix, path) => {
|
|
@@ -5910,7 +6844,7 @@ var normalizeEntry2 = (entry, ctx) => {
|
|
|
5910
6844
|
headings,
|
|
5911
6845
|
id: `${ctx.source.name}:${entry.ref}`,
|
|
5912
6846
|
lastModified: meta.lastModified ?? entry.lastModified,
|
|
5913
|
-
links: extractLinks(entry.body.text),
|
|
6847
|
+
links: extractLinks(entry.body.text, strippedLineOffset(entry.raw, entry.body.text)),
|
|
5914
6848
|
meta,
|
|
5915
6849
|
navPath,
|
|
5916
6850
|
segments,
|
|
@@ -6129,12 +7063,9 @@ ${nested}`;
|
|
|
6129
7063
|
return Object.values(page.properties).find((p) => p.type === "title");
|
|
6130
7064
|
};
|
|
6131
7065
|
const isDraft = (page) => {
|
|
6132
|
-
if (!options.publishedValue) {
|
|
6133
|
-
return false;
|
|
6134
|
-
}
|
|
6135
7066
|
const prop = page.properties[props.status ?? "Status"];
|
|
6136
7067
|
const status = prop?.status?.name ?? prop?.select?.name;
|
|
6137
|
-
return Boolean(status && status !== options.publishedValue);
|
|
7068
|
+
return Boolean(status && status !== (options.publishedValue ?? "Published"));
|
|
6138
7069
|
};
|
|
6139
7070
|
const orderOf = (page) => {
|
|
6140
7071
|
const order = page.properties[props.order ?? "Order"]?.number;
|
|
@@ -6267,7 +7198,7 @@ var renderSpan = (span, defs) => {
|
|
|
6267
7198
|
}
|
|
6268
7199
|
return link?.href ? `[${text}](${link.href})` : text;
|
|
6269
7200
|
};
|
|
6270
|
-
var
|
|
7201
|
+
var renderChildren2 = (block) => {
|
|
6271
7202
|
const defs = new Map((block.markDefs ?? []).map((def) => [def._key, def]));
|
|
6272
7203
|
return (block.children ?? []).map((span) => renderSpan(span, defs)).join("");
|
|
6273
7204
|
};
|
|
@@ -6284,7 +7215,7 @@ var renderBlock = (block, options) => {
|
|
|
6284
7215
|
if (block._type !== "block") {
|
|
6285
7216
|
return `<!-- unsupported Portable Text block: ${block._type} -->`;
|
|
6286
7217
|
}
|
|
6287
|
-
const inline =
|
|
7218
|
+
const inline = renderChildren2(block);
|
|
6288
7219
|
if (block.listItem) {
|
|
6289
7220
|
const indent = " ".repeat(Math.max(0, (block.level ?? 1) - 1));
|
|
6290
7221
|
const marker = block.listItem === "number" ? "1." : "-";
|
|
@@ -6708,7 +7639,7 @@ import { isAbsolute as isAbsolute8, join as join19 } from "pathe";
|
|
|
6708
7639
|
// src/astro/templates.ts
|
|
6709
7640
|
import { existsSync as existsSync11, readFileSync as readFileSync5 } from "node:fs";
|
|
6710
7641
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
6711
|
-
import { dirname as dirname7, isAbsolute as isAbsolute7, join as join18, relative as
|
|
7642
|
+
import { dirname as dirname7, isAbsolute as isAbsolute7, join as join18, relative as relative6 } from "pathe";
|
|
6712
7643
|
var WORKSPACE_MARKERS = [
|
|
6713
7644
|
".git",
|
|
6714
7645
|
"bun.lock",
|
|
@@ -6798,7 +7729,8 @@ var RENDER_EXTERNAL_DEPS = [
|
|
|
6798
7729
|
var renderUserAliases = (aliases) => Object.entries(aliases ?? {}).toSorted(([a], [b]) => b.length - a.length).map(([find, replacement]) => `
|
|
6799
7730
|
${JSON.stringify(find)}: ${JSON.stringify(replacement)},`).join("");
|
|
6800
7731
|
var astroOutDir = (context) => context.distDir ?? `${context.root}/dist`;
|
|
6801
|
-
var
|
|
7732
|
+
var REACT_EXCLUDE = String.raw`exclude: [/\/node_modules\/\.vite\//]`;
|
|
7733
|
+
var reactIntegration = (compilerPath) => compilerPath ? `react({ babel: { plugins: [[${JSON.stringify(compilerPath)}, { target: "19" }]] }, ${REACT_EXCLUDE} })` : `react({ ${REACT_EXCLUDE} })`;
|
|
6802
7734
|
var astroConfigTemplate = (options) => {
|
|
6803
7735
|
const { context, config, needsReact, pages, dataPath, themePath } = options;
|
|
6804
7736
|
const {
|
|
@@ -6852,11 +7784,12 @@ var astroConfigTemplate = (options) => {
|
|
|
6852
7784
|
const twoslashImport = `import { transformerTwoslash } from "@shikijs/twoslash";
|
|
6853
7785
|
`;
|
|
6854
7786
|
const twoslashTransformer = "transformerTwoslash({ explicitTrigger: true }), ";
|
|
6855
|
-
const
|
|
7787
|
+
const deployBase = normalizeBasePath(deployment.base);
|
|
6856
7788
|
const integrations = [
|
|
6857
7789
|
`mdx({ processor: blumeMdxProcessor(${JSON.stringify({
|
|
6858
|
-
basePath:
|
|
7790
|
+
basePath: config.basePath,
|
|
6859
7791
|
codeThemes: config.markdown.codeBlocks.theme,
|
|
7792
|
+
deployBase,
|
|
6860
7793
|
headingAnchors: config.markdown.headingAnchors
|
|
6861
7794
|
})}) })`
|
|
6862
7795
|
];
|
|
@@ -6885,8 +7818,9 @@ export default defineConfig({
|
|
|
6885
7818
|
integrations: [${integrations.join(", ")}],
|
|
6886
7819
|
markdown: {
|
|
6887
7820
|
processor: blumeMarkdownProcessor(${JSON.stringify({
|
|
6888
|
-
basePath:
|
|
7821
|
+
basePath: config.basePath,
|
|
6889
7822
|
codeThemes: config.markdown.codeBlocks.theme,
|
|
7823
|
+
deployBase,
|
|
6890
7824
|
headingAnchors: config.markdown.headingAnchors
|
|
6891
7825
|
})}),
|
|
6892
7826
|
shikiConfig: {
|
|
@@ -6953,7 +7887,7 @@ var contentConfigTemplate = (options) => {
|
|
|
6953
7887
|
const collectionBase = options.collection?.base ?? context.contentRoot;
|
|
6954
7888
|
const includeGlobs = options.collection?.include ?? config.content.include;
|
|
6955
7889
|
const excludeGlobs = options.collection?.exclude ?? config.content.exclude;
|
|
6956
|
-
const outDirRel =
|
|
7890
|
+
const outDirRel = relative6(collectionBase, context.outDir);
|
|
6957
7891
|
const outDirIgnore = outDirRel && !outDirRel.startsWith("..") && !isAbsolute7(outDirRel) ? [`!${outDirRel}/**`] : [];
|
|
6958
7892
|
const filesystem = options.filesystem ?? true;
|
|
6959
7893
|
const docsPattern = filesystem ? [
|
|
@@ -7041,6 +7975,21 @@ const ground = createAskContext(askData);
|
|
|
7041
7975
|
content: m.content,
|
|
7042
7976
|
role: m.role,
|
|
7043
7977
|
}));`;
|
|
7978
|
+
const keyCheck = backend.kind === "gateway" ? ` // The AI Gateway authenticates with an API key or Vercel's OIDC token.
|
|
7979
|
+
if (!(process.env.AI_GATEWAY_API_KEY || process.env.VERCEL_OIDC_TOKEN)) {
|
|
7980
|
+
return new Response(
|
|
7981
|
+
"Ask AI is not configured: set AI_GATEWAY_API_KEY (or deploy on Vercel with OIDC).",
|
|
7982
|
+
{ status: 500 }
|
|
7983
|
+
);
|
|
7984
|
+
}` : ` if (!process.env[${JSON.stringify(backend.apiKeyEnv)}]) {
|
|
7985
|
+
return new Response(
|
|
7986
|
+
${JSON.stringify(`Ask AI is not configured: set ${backend.apiKeyEnv}.`)},
|
|
7987
|
+
{ status: 500 }
|
|
7988
|
+
);
|
|
7989
|
+
}`;
|
|
7990
|
+
const onError = ` onError({ error }) {
|
|
7991
|
+
console.error("Ask AI provider error:", error);
|
|
7992
|
+
},`;
|
|
7044
7993
|
const stream = grounded ? ` const system =
|
|
7045
7994
|
(await ground(messages, body.page)) ??
|
|
7046
7995
|
"You are a helpful documentation assistant. Answer using the project's documentation.";
|
|
@@ -7048,14 +7997,17 @@ const ground = createAskContext(askData);
|
|
|
7048
7997
|
model: ${modelExpr},
|
|
7049
7998
|
system,
|
|
7050
7999
|
messages,
|
|
8000
|
+
${onError}
|
|
7051
8001
|
});` : ` const result = streamText({
|
|
7052
8002
|
model: ${modelExpr},
|
|
7053
8003
|
system:
|
|
7054
8004
|
"You are a helpful documentation assistant. Answer using the project's documentation.",
|
|
7055
8005
|
messages,
|
|
8006
|
+
${onError}
|
|
7056
8007
|
});`;
|
|
7057
8008
|
const handler = `export const POST: APIRoute = async ({ request }) => {
|
|
7058
8009
|
${validate}
|
|
8010
|
+
${keyCheck}
|
|
7059
8011
|
try {
|
|
7060
8012
|
${stream}
|
|
7061
8013
|
return result.toTextStreamResponse();
|
|
@@ -7182,7 +8134,7 @@ export const POST: APIRoute = async ({ request }) => {
|
|
|
7182
8134
|
});
|
|
7183
8135
|
};
|
|
7184
8136
|
`;
|
|
7185
|
-
var rawMarkdownEndpointTemplate = () => `// Generated by Blume. Do not edit.
|
|
8137
|
+
var rawMarkdownEndpointTemplate = (kind) => `// Generated by Blume. Do not edit.
|
|
7186
8138
|
import raw from "../generated/raw-markdown.json";
|
|
7187
8139
|
|
|
7188
8140
|
export const prerender = true;
|
|
@@ -7195,7 +8147,8 @@ export function getStaticPaths() {
|
|
|
7195
8147
|
}
|
|
7196
8148
|
|
|
7197
8149
|
export function GET({ props }) {
|
|
7198
|
-
|
|
8150
|
+
const entry = raw[props.route];
|
|
8151
|
+
return new Response(entry ? ${kind === "md" ? "(entry.md ?? entry.mdx)" : "entry.mdx"} : "", {
|
|
7199
8152
|
headers: { "Content-Type": "text/markdown; charset=utf-8" },
|
|
7200
8153
|
});
|
|
7201
8154
|
}
|
|
@@ -7320,12 +8273,24 @@ import data from ${JSON.stringify(options.dataImport)};
|
|
|
7320
8273
|
export const prerender = true;
|
|
7321
8274
|
|
|
7322
8275
|
const configuration = ${JSON.stringify(options.configuration, null, 2)};
|
|
8276
|
+
|
|
8277
|
+
// The reference is an unlocalized route, so its chrome renders in the default
|
|
8278
|
+
// locale's language and direction (\`data.ui\` is the default locale's resolved
|
|
8279
|
+
// dictionary), mirroring the changelog index's locale wiring.
|
|
8280
|
+
const i18n = data.config.i18n;
|
|
8281
|
+
const localeMeta = i18n
|
|
8282
|
+
? i18n.locales.find((l) => l.code === i18n.defaultLocale)
|
|
8283
|
+
: null;
|
|
8284
|
+
const dir = localeMeta?.dir ?? "ltr";
|
|
8285
|
+
const htmlLang = i18n ? i18n.defaultLocale : "en";
|
|
7323
8286
|
---
|
|
7324
8287
|
|
|
7325
8288
|
<ReferenceLayout
|
|
7326
8289
|
analytics={data.config.analytics}
|
|
7327
8290
|
banner={data.config.banner}
|
|
8291
|
+
dir={dir}
|
|
7328
8292
|
fontCssVars={data.fontCssVars}
|
|
8293
|
+
locale={htmlLang}
|
|
7329
8294
|
logo={data.config.logo}
|
|
7330
8295
|
favicon={data.config.favicon}
|
|
7331
8296
|
appleIcon={data.config.appleIcon}
|
|
@@ -7335,6 +8300,7 @@ const configuration = ${JSON.stringify(options.configuration, null, 2)};
|
|
|
7335
8300
|
searchEnabled={data.config.search.enabled}
|
|
7336
8301
|
site={{ title: data.config.title, description: data.config.description }}
|
|
7337
8302
|
themeMode={data.config.theme.mode}
|
|
8303
|
+
ui={data.ui}
|
|
7338
8304
|
>
|
|
7339
8305
|
<ScalarComponent configuration={configuration} renderMode="client" />
|
|
7340
8306
|
</ReferenceLayout>
|
|
@@ -7485,6 +8451,13 @@ const ogRel = seo.image ?? ogPath;
|
|
|
7485
8451
|
// an external URL, which passes through verbatim (mirrors PageLayout).
|
|
7486
8452
|
const ogImage =
|
|
7487
8453
|
ogRel && base && ogRel.startsWith("/") ? \`\${base}\${withBase(ogRel)}\` : ogRel;
|
|
8454
|
+
// Blume's generated card has known dimensions the layout can declare; a user's
|
|
8455
|
+
// \`seo.image\` could be any size or format, so it gets none.
|
|
8456
|
+
const ogGenerated = !seo.image && Boolean(ogPath);
|
|
8457
|
+
|
|
8458
|
+
// X attribution: the site's account, plus a creator the page can claim for
|
|
8459
|
+
// itself (a guest post crediting its own author) over the configured default.
|
|
8460
|
+
const x = { ...data.config.x, ...(seo.x?.creator ? { creator: seo.x.creator } : {}) };
|
|
7488
8461
|
|
|
7489
8462
|
const basedRoute = withBase(route);
|
|
7490
8463
|
const canonical =
|
|
@@ -7581,6 +8554,8 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
7581
8554
|
searchEnabled={data.config.search.enabled}
|
|
7582
8555
|
indexable={indexable}
|
|
7583
8556
|
ogImage={ogImage}
|
|
8557
|
+
ogGenerated={ogGenerated}
|
|
8558
|
+
x={x}
|
|
7584
8559
|
canonical={canonical}
|
|
7585
8560
|
editUrl={editUrl}
|
|
7586
8561
|
feedback={data.config.feedback}
|
|
@@ -7607,7 +8582,7 @@ var changelogIndexTemplate = (options) => {
|
|
|
7607
8582
|
const askSlot = options.askEnabled ? `
|
|
7608
8583
|
<AskAI slot="ask" strings={data.ui.ask} suggestions={data.config.ask?.suggestions ?? []} />` : "";
|
|
7609
8584
|
const clientData = options.needsReact ? `
|
|
7610
|
-
clientData={{ config: data.config, navigation: data.navigation, page: { route: "/changelog", title:
|
|
8585
|
+
clientData={{ config: data.config, navigation: data.navigation, page: { route: "/changelog", title: pageTitle } }}` : "";
|
|
7611
8586
|
const stagedSpread = options.staged ? `
|
|
7612
8587
|
...(await getCollection("staged")),` : "";
|
|
7613
8588
|
return `---
|
|
@@ -7615,6 +8590,7 @@ var changelogIndexTemplate = (options) => {
|
|
|
7615
8590
|
import { getCollection, render } from "astro:content";
|
|
7616
8591
|
import RootLayout from "blume/components/layout/RootLayout.astro";
|
|
7617
8592
|
import Update from "blume/components/content/Update.astro";
|
|
8593
|
+
import { withBase } from "blume/components/islands/base-path.ts";
|
|
7618
8594
|
import { resolveSlot } from "blume/components/layout/overrides.ts";
|
|
7619
8595
|
import { layoutOverrides } from "../generated/components.ts";
|
|
7620
8596
|
${askImport}import data from "../generated/data.json";
|
|
@@ -7695,6 +8671,20 @@ const items = await Promise.all(
|
|
|
7695
8671
|
})
|
|
7696
8672
|
);
|
|
7697
8673
|
|
|
8674
|
+
// Repeated labels slug to the same id (e.g. two entries with neither a title
|
|
8675
|
+
// nor a version both falling back to "update"); suffix the later ones -2, -3,
|
|
8676
|
+
// ... so every heading deep-links to its own entry. The first keeps the plain
|
|
8677
|
+
// slug, and the rendered ids stay in lockstep with the \`headings\` list below.
|
|
8678
|
+
const seenIds = new Set();
|
|
8679
|
+
for (const item of items) {
|
|
8680
|
+
let uniqueId = item.id;
|
|
8681
|
+
for (let n = 2; seenIds.has(uniqueId); n += 1) {
|
|
8682
|
+
uniqueId = item.id + "-" + n;
|
|
8683
|
+
}
|
|
8684
|
+
seenIds.add(uniqueId);
|
|
8685
|
+
item.id = uniqueId;
|
|
8686
|
+
}
|
|
8687
|
+
|
|
7698
8688
|
// A changelog is semver-paginated only when every visible release parses as
|
|
7699
8689
|
// semver and they span more than one major line. Older majors then collapse
|
|
7700
8690
|
// into groups the reader reveals one at a time; otherwise the timeline is flat.
|
|
@@ -7715,7 +8705,29 @@ const headings = items.map((item) => ({
|
|
|
7715
8705
|
}));
|
|
7716
8706
|
|
|
7717
8707
|
const base = data.config.site ? data.config.site.replace(/\\/$/, "") : null;
|
|
7718
|
-
|
|
8708
|
+
// The canonical URL carries the deployment base (the page is served under it),
|
|
8709
|
+
// matching how the catch-all canonicalizes via \`withBase(route)\`.
|
|
8710
|
+
const basedRoute = withBase("/changelog");
|
|
8711
|
+
const canonical = base ? base + basedRoute : null;
|
|
8712
|
+
|
|
8713
|
+
// The changelog is an unlocalized route, so its chrome renders in the default
|
|
8714
|
+
// locale's dictionary and direction (\`data.ui\` is the default locale's resolved
|
|
8715
|
+
// dictionary), mirroring the catch-all's locale wiring.
|
|
8716
|
+
const i18n = data.config.i18n;
|
|
8717
|
+
const localeMeta = i18n
|
|
8718
|
+
? i18n.locales.find((l) => l.code === i18n.defaultLocale)
|
|
8719
|
+
: null;
|
|
8720
|
+
const dir = localeMeta?.dir ?? "ltr";
|
|
8721
|
+
const htmlLang = i18n ? i18n.defaultLocale : "en";
|
|
8722
|
+
|
|
8723
|
+
// The page chrome (h1, title, description) comes from the same translatable
|
|
8724
|
+
// \`changelog\` group as the reveal button; optional chaining tolerates a
|
|
8725
|
+
// not-yet-regenerated data snapshot from before these keys existed.
|
|
8726
|
+
const changelogTitle = data.ui.changelog?.title ?? "Changelog";
|
|
8727
|
+
const changelogDescription =
|
|
8728
|
+
data.ui.changelog?.description ??
|
|
8729
|
+
"Product updates, new features, and fixes from every release.";
|
|
8730
|
+
const pageTitle = data.config.title + " " + changelogTitle;
|
|
7719
8731
|
|
|
7720
8732
|
const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
7721
8733
|
---
|
|
@@ -7732,9 +8744,12 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
7732
8744
|
imageZoom={data.config.imageZoom}
|
|
7733
8745
|
codeWrap={data.config.codeWrap}
|
|
7734
8746
|
navigation={data.navigation}
|
|
8747
|
+
locale={htmlLang}
|
|
8748
|
+
dir={dir}
|
|
8749
|
+
ui={data.ui}
|
|
7735
8750
|
page={{
|
|
7736
|
-
title:
|
|
7737
|
-
description:
|
|
8751
|
+
title: pageTitle,
|
|
8752
|
+
description: changelogDescription,
|
|
7738
8753
|
route: "/changelog",
|
|
7739
8754
|
}}
|
|
7740
8755
|
headings={headings}
|
|
@@ -7745,6 +8760,7 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
7745
8760
|
searchEnabled={data.config.search.enabled}
|
|
7746
8761
|
indexable={true}
|
|
7747
8762
|
ogImage={null}
|
|
8763
|
+
x={data.config.x}
|
|
7748
8764
|
canonical={canonical}
|
|
7749
8765
|
askEnabled={${options.askEnabled}}
|
|
7750
8766
|
exportPdf={${options.exportPdf}}
|
|
@@ -7754,12 +8770,15 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
7754
8770
|
noindex={false}
|
|
7755
8771
|
structuredDataEnabled={data.config.structuredData}
|
|
7756
8772
|
>${askSlot}
|
|
7757
|
-
<h1>
|
|
8773
|
+
<h1>{changelogTitle}</h1>
|
|
7758
8774
|
{
|
|
7759
8775
|
items.length === 0 ? (
|
|
7760
8776
|
<p>No changelog entries yet.</p>
|
|
7761
8777
|
) : paginate ? (
|
|
7762
|
-
<blume-changelog
|
|
8778
|
+
<blume-changelog
|
|
8779
|
+
class="not-prose mt-8 block"
|
|
8780
|
+
data-i18n-more={data.ui.changelog?.showReleases}
|
|
8781
|
+
>
|
|
7763
8782
|
{majorGroups[0].items.map(({ Content, href, id, label, date, tags }) => (
|
|
7764
8783
|
<Update description={date} href={href} id={id} label={label} tags={tags}>
|
|
7765
8784
|
<Content />
|
|
@@ -7808,11 +8827,22 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
7808
8827
|
var notFoundPageTemplate = () => `---
|
|
7809
8828
|
// Generated by Blume. Do not edit. Override by adding \`pages/404.astro\`.
|
|
7810
8829
|
import PageLayout from "blume/components/layout/PageLayout.astro";
|
|
8830
|
+
import { withBase } from "blume/components/islands/base-path.ts";
|
|
7811
8831
|
import data from "../generated/data.json";
|
|
7812
8832
|
|
|
7813
8833
|
export const prerender = true;
|
|
7814
8834
|
|
|
7815
8835
|
const nf = data.ui.notFound;
|
|
8836
|
+
|
|
8837
|
+
// The 404 page is an unlocalized route, so its chrome renders in the default
|
|
8838
|
+
// locale's dictionary and direction (\`data.ui\` is the default locale's resolved
|
|
8839
|
+
// dictionary), mirroring the catch-all's locale wiring.
|
|
8840
|
+
const i18n = data.config.i18n;
|
|
8841
|
+
const localeMeta = i18n
|
|
8842
|
+
? i18n.locales.find((l) => l.code === i18n.defaultLocale)
|
|
8843
|
+
: null;
|
|
8844
|
+
const dir = localeMeta?.dir ?? "ltr";
|
|
8845
|
+
const htmlLang = i18n ? i18n.defaultLocale : "en";
|
|
7816
8846
|
---
|
|
7817
8847
|
|
|
7818
8848
|
<PageLayout
|
|
@@ -7827,6 +8857,8 @@ const nf = data.ui.notFound;
|
|
|
7827
8857
|
themeMode={data.config.theme.mode}
|
|
7828
8858
|
fontCssVars={data.fontCssVars}
|
|
7829
8859
|
searchEnabled={data.config.search.enabled}
|
|
8860
|
+
locale={htmlLang}
|
|
8861
|
+
dir={dir}
|
|
7830
8862
|
ui={data.ui}
|
|
7831
8863
|
noindex={true}
|
|
7832
8864
|
>
|
|
@@ -7838,7 +8870,7 @@ const nf = data.ui.notFound;
|
|
|
7838
8870
|
<p class="text-muted-foreground">{nf.description}</p>
|
|
7839
8871
|
<a
|
|
7840
8872
|
class="mt-2 rounded-md bg-accent px-4 py-2 text-sm font-medium text-accent-foreground"
|
|
7841
|
-
href="/">{nf.home}</a
|
|
8873
|
+
href={withBase("/")}>{nf.home}</a
|
|
7842
8874
|
>
|
|
7843
8875
|
</div>
|
|
7844
8876
|
</PageLayout>
|
|
@@ -8948,7 +9980,7 @@ ${clause}
|
|
|
8948
9980
|
<Component ${directiveFor(override)} {...Astro.props}><slot /></Component>
|
|
8949
9981
|
`;
|
|
8950
9982
|
};
|
|
8951
|
-
var sanitize = (value) => value.replaceAll(/[^A-Za-z0-9]/gu,
|
|
9983
|
+
var sanitize = (value) => value.replaceAll(/[^A-Za-z0-9]/gu, (char) => `_${(char.codePointAt(0) ?? 0).toString(16)}_`);
|
|
8952
9984
|
var planComponentSlots = (componentsFile, analysis) => {
|
|
8953
9985
|
const frameworks = new Set;
|
|
8954
9986
|
if (!componentsFile) {
|
|
@@ -9011,13 +10043,13 @@ export const layoutOverrides = { ...(overrides.layout ?? {})${layoutEntries.leng
|
|
|
9011
10043
|
|
|
9012
10044
|
// src/astro/examples.ts
|
|
9013
10045
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
9014
|
-
import { join as join21, relative as
|
|
9015
|
-
import { glob as
|
|
10046
|
+
import { join as join21, relative as relative7 } from "pathe";
|
|
10047
|
+
import { glob as glob4 } from "tinyglobby";
|
|
9016
10048
|
|
|
9017
10049
|
// src/astro/islands.ts
|
|
9018
10050
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
9019
10051
|
import { basename, join as join20 } from "pathe";
|
|
9020
|
-
import { glob as
|
|
10052
|
+
import { glob as glob3 } from "tinyglobby";
|
|
9021
10053
|
var DEFAULT_CLIENT = "visible";
|
|
9022
10054
|
var VALID_MODES = new Set([
|
|
9023
10055
|
"idle",
|
|
@@ -9046,7 +10078,7 @@ var readClientMode = (source, file, warnings) => {
|
|
|
9046
10078
|
};
|
|
9047
10079
|
var discoverIslands = async (root) => {
|
|
9048
10080
|
const dir = join20(root, "islands");
|
|
9049
|
-
const matches = await
|
|
10081
|
+
const matches = await glob3(["**/*.{jsx,svelte,tsx,vue}"], {
|
|
9050
10082
|
absolute: true,
|
|
9051
10083
|
cwd: dir,
|
|
9052
10084
|
onlyFiles: true
|
|
@@ -9109,7 +10141,7 @@ var splitGlobBase = (pattern) => {
|
|
|
9109
10141
|
var discoverExamples = async (root, pattern = "examples") => {
|
|
9110
10142
|
const { base, rest } = GLOB_MAGIC.test(pattern) ? splitGlobBase(pattern) : { base: pattern, rest: DEFAULT_EXAMPLE_GLOB };
|
|
9111
10143
|
const dir = join21(root, base);
|
|
9112
|
-
const matches = await
|
|
10144
|
+
const matches = await glob4([rest], {
|
|
9113
10145
|
absolute: true,
|
|
9114
10146
|
cwd: dir,
|
|
9115
10147
|
onlyFiles: true
|
|
@@ -9125,7 +10157,7 @@ var discoverExamples = async (root, pattern = "examples") => {
|
|
|
9125
10157
|
if (!(ext && framework)) {
|
|
9126
10158
|
return;
|
|
9127
10159
|
}
|
|
9128
|
-
const path =
|
|
10160
|
+
const path = relative7(dir, file).slice(0, -(ext.length + 1));
|
|
9129
10161
|
const existing = seen.get(path);
|
|
9130
10162
|
if (existing) {
|
|
9131
10163
|
warnings.push(`Two examples both resolve to "${path}" ("${existing}" and "${file}"); ignoring the second. Give them distinct paths.`);
|
|
@@ -9147,52 +10179,6 @@ var discoverExamples = async (root, pattern = "examples") => {
|
|
|
9147
10179
|
return { examples, warnings };
|
|
9148
10180
|
};
|
|
9149
10181
|
|
|
9150
|
-
// src/astro/pages.ts
|
|
9151
|
-
import { extname as extname5, relative as relative7 } from "pathe";
|
|
9152
|
-
import { glob as glob4 } from "tinyglobby";
|
|
9153
|
-
var discoverPages = async (pagesRoot) => {
|
|
9154
|
-
const files = await glob4(["**/*.astro"], {
|
|
9155
|
-
absolute: true,
|
|
9156
|
-
cwd: pagesRoot,
|
|
9157
|
-
onlyFiles: true
|
|
9158
|
-
});
|
|
9159
|
-
files.sort();
|
|
9160
|
-
return files.map((file) => {
|
|
9161
|
-
const rel = relative7(pagesRoot, file);
|
|
9162
|
-
const withoutExt = rel.slice(0, rel.length - extname5(rel).length);
|
|
9163
|
-
const parts = withoutExt.split("/");
|
|
9164
|
-
if (parts.at(-1) === "index") {
|
|
9165
|
-
parts.pop();
|
|
9166
|
-
}
|
|
9167
|
-
const pattern = parts.length === 0 ? "/" : `/${parts.join("/")}`;
|
|
9168
|
-
return { entrypoint: file, pattern };
|
|
9169
|
-
});
|
|
9170
|
-
};
|
|
9171
|
-
var routeIsTaken = (pages, contentPages, route) => pages.some((page) => page.pattern === route) || contentPages.some((page) => page.route === route);
|
|
9172
|
-
var PRIVATE_SEGMENT = /^[._]/u;
|
|
9173
|
-
var humanizeSegment = (segment) => segment.split(/[-_]/u).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
9174
|
-
var customOgRoutes = (pages, siteTitle) => {
|
|
9175
|
-
const seen = new Set;
|
|
9176
|
-
const routes = [];
|
|
9177
|
-
const collectRoute = (pattern) => {
|
|
9178
|
-
const segments = pattern.split("/").filter(Boolean);
|
|
9179
|
-
if (segments.some((part) => PRIVATE_SEGMENT.test(part) || part.includes("["))) {
|
|
9180
|
-
return;
|
|
9181
|
-
}
|
|
9182
|
-
const slug = segments.length === 0 ? "index" : segments.join("/");
|
|
9183
|
-
if (seen.has(slug)) {
|
|
9184
|
-
return;
|
|
9185
|
-
}
|
|
9186
|
-
seen.add(slug);
|
|
9187
|
-
const last = segments.at(-1);
|
|
9188
|
-
routes.push({ slug, title: last ? humanizeSegment(last) : siteTitle });
|
|
9189
|
-
};
|
|
9190
|
-
for (const { pattern } of pages) {
|
|
9191
|
-
collectRoute(pattern);
|
|
9192
|
-
}
|
|
9193
|
-
return routes;
|
|
9194
|
-
};
|
|
9195
|
-
|
|
9196
10182
|
// src/astro/generate.ts
|
|
9197
10183
|
var BLUME_SRC = join22(packageRoot(), "src");
|
|
9198
10184
|
var canResolveFrom = (fromDir, spec) => {
|
|
@@ -9281,6 +10267,10 @@ var ISLAND_FRAMEWORK_DEPS = {
|
|
|
9281
10267
|
svelte: "@astrojs/svelte",
|
|
9282
10268
|
vue: "@astrojs/vue"
|
|
9283
10269
|
};
|
|
10270
|
+
var DEPLOYMENT_ADAPTER_DEPS = {
|
|
10271
|
+
cloudflare: "@astrojs/cloudflare",
|
|
10272
|
+
netlify: "@astrojs/netlify"
|
|
10273
|
+
};
|
|
9284
10274
|
var islandFrameworkWarnings = (frameworks, root) => {
|
|
9285
10275
|
const warnings = [];
|
|
9286
10276
|
for (const framework of frameworks) {
|
|
@@ -9291,6 +10281,15 @@ var islandFrameworkWarnings = (frameworks, root) => {
|
|
|
9291
10281
|
}
|
|
9292
10282
|
return warnings;
|
|
9293
10283
|
};
|
|
10284
|
+
var deploymentAdapterWarnings = (deployment, root) => {
|
|
10285
|
+
const dep = deployment.output === "server" && deployment.adapter ? DEPLOYMENT_ADAPTER_DEPS[deployment.adapter] : undefined;
|
|
10286
|
+
if (dep && !(canResolveFrom(root, dep) || canResolveFrom(packageRoot(), dep))) {
|
|
10287
|
+
return [
|
|
10288
|
+
`Deployment adapter "${deployment.adapter}" needs "${dep}", which isn't installed. Run \`npm install ${dep}\` (or your package manager's equivalent).`
|
|
10289
|
+
];
|
|
10290
|
+
}
|
|
10291
|
+
return [];
|
|
10292
|
+
};
|
|
9294
10293
|
var examplesCssFile = (root, config) => config.examples.css ? join22(root, config.examples.css) : null;
|
|
9295
10294
|
var writeExamplesPreview = async (options) => {
|
|
9296
10295
|
const { config, hasExamples, root, srcDir, write } = options;
|
|
@@ -9320,14 +10319,15 @@ var detectNeedsReact = async (root) => {
|
|
|
9320
10319
|
});
|
|
9321
10320
|
return matches.length > 0;
|
|
9322
10321
|
};
|
|
9323
|
-
var
|
|
9324
|
-
|
|
10322
|
+
var containsMath = (content) => content.includes("$$") || content.includes("<Math");
|
|
10323
|
+
var detectUsesMath = async (root, staged = []) => {
|
|
10324
|
+
const files = await glob5(["**/*.{md,mdx}"], {
|
|
9325
10325
|
cwd: root,
|
|
9326
10326
|
ignore: ["**/node_modules/**", "**/.blume/**", "**/dist/**"],
|
|
9327
10327
|
onlyFiles: true
|
|
9328
10328
|
});
|
|
9329
10329
|
const contents = await Promise.all(files.map((file) => readOptional(join22(root, file))));
|
|
9330
|
-
return contents.some(
|
|
10330
|
+
return [...contents, ...staged].some(containsMath);
|
|
9331
10331
|
};
|
|
9332
10332
|
var writeIfChanged = async (path, content) => {
|
|
9333
10333
|
let existing = null;
|
|
@@ -9518,6 +10518,7 @@ var buildRuntimeData = (project) => {
|
|
|
9518
10518
|
appleIcon: resolveAppleIcon(project),
|
|
9519
10519
|
ask: config.ai.ask?.enabled ? { suggestions: config.ai.ask.suggestions } : null,
|
|
9520
10520
|
banner: resolveBanner(config),
|
|
10521
|
+
basePath: config.basePath,
|
|
9521
10522
|
codeThemes: config.markdown.codeBlocks.theme,
|
|
9522
10523
|
codeWrap: config.markdown.code.wrap,
|
|
9523
10524
|
description: config.description,
|
|
@@ -9546,7 +10547,8 @@ var buildRuntimeData = (project) => {
|
|
|
9546
10547
|
structuredData: config.seo.structuredData,
|
|
9547
10548
|
theme: config.theme,
|
|
9548
10549
|
title: config.title,
|
|
9549
|
-
toc: config.toc
|
|
10550
|
+
toc: config.toc,
|
|
10551
|
+
x: config.seo.x
|
|
9550
10552
|
},
|
|
9551
10553
|
feeds: buildRssFeeds(project).map((feed) => ({
|
|
9552
10554
|
href: feed.path,
|
|
@@ -9620,6 +10622,7 @@ var writeMcpFiles = async (project, plan, write) => {
|
|
|
9620
10622
|
}
|
|
9621
10623
|
const data = await buildMcpData(project);
|
|
9622
10624
|
const discoveryInput = {
|
|
10625
|
+
base: data.base,
|
|
9623
10626
|
name: data.name,
|
|
9624
10627
|
route: plan.route,
|
|
9625
10628
|
site: data.site,
|
|
@@ -9651,11 +10654,6 @@ var writeNotFoundPage = async (write, srcDir, pages, contentPages) => {
|
|
|
9651
10654
|
}
|
|
9652
10655
|
await write(join22(srcDir, "pages", "404.astro"), notFoundPageTemplate());
|
|
9653
10656
|
};
|
|
9654
|
-
var shouldGenerateChangelog = (project, userPages) => {
|
|
9655
|
-
const hasChangelog = project.graph.pages.some((page) => page.contentType === "changelog" && !(page.meta.draft || page.meta.sidebar.hidden));
|
|
9656
|
-
const hasChangelogSource = (project.config.content.sources ?? []).some((source) => source.type === "github-releases");
|
|
9657
|
-
return (hasChangelog || hasChangelogSource) && !routeIsTaken(userPages, project.graph.pages, "/changelog");
|
|
9658
|
-
};
|
|
9659
10657
|
var buildComponentSlots = async (componentsFile) => {
|
|
9660
10658
|
const analysis = componentsFile ? analyzeComponentOverrides(await readFile11(componentsFile, "utf-8"), componentsFile) : null;
|
|
9661
10659
|
return {
|
|
@@ -9683,6 +10681,7 @@ var generateRuntime = async (project) => {
|
|
|
9683
10681
|
const askEnabled = config.ai.ask?.enabled ?? false;
|
|
9684
10682
|
const exportPdf = config.export.pdf;
|
|
9685
10683
|
const exportEpub = config.export.epub;
|
|
10684
|
+
const staged = collectStaged(project);
|
|
9686
10685
|
const [
|
|
9687
10686
|
pages,
|
|
9688
10687
|
detectedReact,
|
|
@@ -9695,7 +10694,7 @@ var generateRuntime = async (project) => {
|
|
|
9695
10694
|
] = await Promise.all([
|
|
9696
10695
|
context.pagesRoot ? discoverPages(context.pagesRoot) : Promise.resolve([]),
|
|
9697
10696
|
detectNeedsReact(context.root),
|
|
9698
|
-
detectUsesMath(context.root),
|
|
10697
|
+
detectUsesMath(context.root, staged.values()),
|
|
9699
10698
|
readOptional(context.themeFile),
|
|
9700
10699
|
readOptional(examplesCssFile(context.root, config)),
|
|
9701
10700
|
discoverIslands(context.root),
|
|
@@ -9719,7 +10718,6 @@ var generateRuntime = async (project) => {
|
|
|
9719
10718
|
const ogRoutes = customOgRoutes(pages, config.title);
|
|
9720
10719
|
const mcp = planMcp(project, srcDir, pages);
|
|
9721
10720
|
pages.push(...mcp.discoveryPages);
|
|
9722
|
-
const staged = collectStaged(project);
|
|
9723
10721
|
const hasStaged = staged.size > 0;
|
|
9724
10722
|
const hasFilesystemSource = project.sources.some((source) => !source.staged);
|
|
9725
10723
|
const [structural] = await Promise.all([
|
|
@@ -9785,7 +10783,7 @@ var generateRuntime = async (project) => {
|
|
|
9785
10783
|
if (config.seo.og.enabled) {
|
|
9786
10784
|
await write(join22(srcDir, "pages", "og", "[...slug].png.ts"), ogEndpointTemplate(ogRoutes));
|
|
9787
10785
|
}
|
|
9788
|
-
if (
|
|
10786
|
+
if (hasGeneratedChangelog(project, pages)) {
|
|
9789
10787
|
await write(join22(srcDir, "pages", "changelog.astro"), changelogIndexTemplate({
|
|
9790
10788
|
askEnabled,
|
|
9791
10789
|
exportEpub,
|
|
@@ -9818,8 +10816,8 @@ var generateRuntime = async (project) => {
|
|
|
9818
10816
|
await Promise.all([
|
|
9819
10817
|
write(join22(srcDir, "generated", "raw-markdown.json"), `${JSON.stringify(rawMarkdown)}
|
|
9820
10818
|
`),
|
|
9821
|
-
write(join22(srcDir, "pages", "[...slug].md.ts"), rawMarkdownEndpointTemplate()),
|
|
9822
|
-
write(join22(srcDir, "pages", "[...slug].mdx.ts"), rawMarkdownEndpointTemplate())
|
|
10819
|
+
write(join22(srcDir, "pages", "[...slug].md.ts"), rawMarkdownEndpointTemplate("md")),
|
|
10820
|
+
write(join22(srcDir, "pages", "[...slug].mdx.ts"), rawMarkdownEndpointTemplate("mdx"))
|
|
9823
10821
|
]);
|
|
9824
10822
|
const feeds = buildRssFeeds(project);
|
|
9825
10823
|
if (feeds.length > 0) {
|
|
@@ -9844,7 +10842,7 @@ var generateRuntime = async (project) => {
|
|
|
9844
10842
|
...pages.map((page) => page.pattern),
|
|
9845
10843
|
...referenceTabs(config).map((tab) => tab.path)
|
|
9846
10844
|
]);
|
|
9847
|
-
if (
|
|
10845
|
+
if (hasGeneratedChangelog(project, pages)) {
|
|
9848
10846
|
navTargetRoutes.add("/changelog");
|
|
9849
10847
|
}
|
|
9850
10848
|
warnings.push(...validateNavTargets(project.graph.navigation, navTargetRoutes).map((diagnostic) => diagnostic.suggestion ? `${diagnostic.message} ${diagnostic.suggestion}` : diagnostic.message));
|
|
@@ -9858,7 +10856,7 @@ var generateRuntime = async (project) => {
|
|
|
9858
10856
|
warnings.push(`Search provider "${config.search.provider}" needs "${dep}", which isn't installed. Run \`npm install ${dep}\` (or your package manager's equivalent).`);
|
|
9859
10857
|
}
|
|
9860
10858
|
}
|
|
9861
|
-
warnings.push(...islandFrameworkWarnings(frameworks, context.root));
|
|
10859
|
+
warnings.push(...deploymentAdapterWarnings(config.deployment, context.root), ...islandFrameworkWarnings(frameworks, context.root));
|
|
9862
10860
|
if (hasScalarReferences(config)) {
|
|
9863
10861
|
const references = await buildReferenceFiles({
|
|
9864
10862
|
config,
|
|
@@ -10005,6 +11003,7 @@ var segmentKey = (raw) => {
|
|
|
10005
11003
|
const group = raw.match(GROUP_FOLDER2)?.groups?.label;
|
|
10006
11004
|
return (group ?? raw).replace(NUMERIC_PREFIX2, "");
|
|
10007
11005
|
};
|
|
11006
|
+
var isIndexStem = (stem) => stem.replace(NUMERIC_PREFIX2, "") === "index";
|
|
10008
11007
|
var createGroup = (key, path, label, order) => ({
|
|
10009
11008
|
children: [],
|
|
10010
11009
|
index: new Map,
|
|
@@ -10029,7 +11028,7 @@ var pageOrder = (page, filename) => {
|
|
|
10029
11028
|
if (page.meta.sidebar.order !== undefined) {
|
|
10030
11029
|
return page.meta.sidebar.order;
|
|
10031
11030
|
}
|
|
10032
|
-
if (filename.replace(extname6(filename), "")
|
|
11031
|
+
if (isIndexStem(filename.replace(extname6(filename), ""))) {
|
|
10033
11032
|
return Number.NEGATIVE_INFINITY;
|
|
10034
11033
|
}
|
|
10035
11034
|
if (page.contentType === "changelog") {
|
|
@@ -10138,7 +11137,7 @@ var buildFileSystemSidebar = (pages, folderMeta, sharedMeta, metaPrefix, display
|
|
|
10138
11137
|
const stem = filename.replace(extname6(filename), "");
|
|
10139
11138
|
const dirs = parts.slice(0, -1);
|
|
10140
11139
|
const routeSegments = page.route.split("/").filter(Boolean);
|
|
10141
|
-
const folderParts = stem
|
|
11140
|
+
const folderParts = isIndexStem(stem) ? routeSegments : routeSegments.slice(0, -1);
|
|
10142
11141
|
const routeDirCount = dirs.filter((dir) => !GROUP_FOLDER2.test(dir)).length;
|
|
10143
11142
|
const offset = Math.max(0, folderParts.length - routeDirCount);
|
|
10144
11143
|
let parent = root;
|
|
@@ -10266,7 +11265,7 @@ var buildNavigation = (pages, options) => {
|
|
|
10266
11265
|
...selector,
|
|
10267
11266
|
items: selector.items.map(rebasePath)
|
|
10268
11267
|
})) : options.selectors ?? [];
|
|
10269
|
-
const
|
|
11268
|
+
const tabs2 = basePath ? (options.tabs ?? []).map((tab) => ({
|
|
10270
11269
|
...tab,
|
|
10271
11270
|
items: tab.items?.map(rebasePath),
|
|
10272
11271
|
path: withBasePath(basePath, tab.path)
|
|
@@ -10288,14 +11287,15 @@ var buildNavigation = (pages, options) => {
|
|
|
10288
11287
|
featured,
|
|
10289
11288
|
selectors,
|
|
10290
11289
|
sidebar: buildConfigSidebar(options.sidebar, byRoute, display, basePath),
|
|
10291
|
-
tabs
|
|
11290
|
+
tabs: tabs2
|
|
10292
11291
|
};
|
|
10293
11292
|
}
|
|
11293
|
+
const rootTabPath = withBasePath(basePath, options.localizedRoot ?? "/");
|
|
10294
11294
|
return {
|
|
10295
11295
|
featured,
|
|
10296
11296
|
selectors,
|
|
10297
|
-
sidebar: buildFileSystemSidebar(pages, options.folderMeta, sharedFolderMeta, metaPrefix, display, new Set(
|
|
10298
|
-
tabs
|
|
11297
|
+
sidebar: buildFileSystemSidebar(pages, options.folderMeta, sharedFolderMeta, metaPrefix, display, new Set(tabs2.flatMap((tab) => tab.path === rootTabPath ? [] : [tab.path]))),
|
|
11298
|
+
tabs: tabs2
|
|
10299
11299
|
};
|
|
10300
11300
|
};
|
|
10301
11301
|
|
|
@@ -10337,9 +11337,14 @@ var localePagesFor = (code, real, fallback, fallbackByKey, i18n, basePath) => {
|
|
|
10337
11337
|
return [...real, ...filled];
|
|
10338
11338
|
};
|
|
10339
11339
|
var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n) => {
|
|
10340
|
-
const
|
|
11340
|
+
const localizePath = (path) => path.startsWith("/") ? localizeRoute(path, code, i18n) : path;
|
|
11341
|
+
const tabs2 = options.navigation.tabs?.map((tab) => ({
|
|
10341
11342
|
...tab,
|
|
10342
|
-
|
|
11343
|
+
items: tab.items?.map((item) => ({
|
|
11344
|
+
...item,
|
|
11345
|
+
path: localizePath(item.path)
|
|
11346
|
+
})),
|
|
11347
|
+
path: localizePath(tab.path)
|
|
10343
11348
|
}));
|
|
10344
11349
|
const real = pages.filter((page) => page.locale === code);
|
|
10345
11350
|
const localePages = localePagesFor(code, real, fallback, fallbackByKey, i18n, options.basePath ?? "");
|
|
@@ -10348,12 +11353,13 @@ var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n
|
|
|
10348
11353
|
display: options.navigation.sidebar.display,
|
|
10349
11354
|
featured: options.navigation.featured,
|
|
10350
11355
|
folderMeta: options.folderMeta,
|
|
11356
|
+
localizedRoot: localizeRoute("/", code, i18n),
|
|
10351
11357
|
metaPrefix: i18n.parser === "dir" && code !== i18n.defaultLocale ? code : "",
|
|
10352
11358
|
refByLogical: true,
|
|
10353
11359
|
selectors: options.navigation.selectors,
|
|
10354
11360
|
sharedFolderMeta: options.sharedFolderMeta,
|
|
10355
11361
|
sidebar: options.navigation.sidebar.items,
|
|
10356
|
-
tabs
|
|
11362
|
+
tabs: tabs2
|
|
10357
11363
|
});
|
|
10358
11364
|
};
|
|
10359
11365
|
var buildI18nNavigation = (pages, options, i18n) => {
|
|
@@ -10429,7 +11435,10 @@ var parseGitLog = (output) => {
|
|
|
10429
11435
|
}
|
|
10430
11436
|
return times;
|
|
10431
11437
|
};
|
|
10432
|
-
var gitLastModifiedTimes = (root,
|
|
11438
|
+
var gitLastModifiedTimes = (root, contentRoots, sourcePaths) => {
|
|
11439
|
+
if (sourcePaths.length === 0) {
|
|
11440
|
+
return new Map;
|
|
11441
|
+
}
|
|
10433
11442
|
try {
|
|
10434
11443
|
const gitRoot = execFileSync("git", ["-C", root, "rev-parse", "--show-toplevel"], { encoding: "utf-8" }).trim();
|
|
10435
11444
|
const output = execFileSync("git", [
|
|
@@ -10441,7 +11450,7 @@ var gitLastModifiedTimes = (root, contentRoot, sourcePaths) => {
|
|
|
10441
11450
|
"--format=%x00%cI",
|
|
10442
11451
|
"--name-only",
|
|
10443
11452
|
"--",
|
|
10444
|
-
|
|
11453
|
+
...contentRoots
|
|
10445
11454
|
], { encoding: "utf-8", maxBuffer: 256 * 1024 * 1024 });
|
|
10446
11455
|
const byRepoPath = parseGitLog(output);
|
|
10447
11456
|
const result = new Map;
|
|
@@ -10567,7 +11576,7 @@ var entryIdDiagnostics = (pages, collectionBase) => {
|
|
|
10567
11576
|
file: page.sourcePath,
|
|
10568
11577
|
message: `Content source "${page.source.name}" is rooted outside the docs collection base, so ${page.route} resolves entry id "${entryId}" but the collection would generate "${expected}" — the page would 404 at runtime.`,
|
|
10569
11578
|
severity: "error",
|
|
10570
|
-
suggestion: "
|
|
11579
|
+
suggestion: "Use a single filesystem source (the docs collection roots at it), or root every filesystem source at content.root and partition them with include globs — a root at a subdirectory of content.root still mismatches."
|
|
10571
11580
|
});
|
|
10572
11581
|
}
|
|
10573
11582
|
}
|
|
@@ -10579,7 +11588,7 @@ var scanProject = async (root, options = {}) => {
|
|
|
10579
11588
|
const configResult = await loadConfig(root, {
|
|
10580
11589
|
devServerUrl: options.devServerUrl
|
|
10581
11590
|
});
|
|
10582
|
-
const config = applyConfigOverrides(configResult.config, options.overrides);
|
|
11591
|
+
const config = applyDeploymentEnv(applyConfigOverrides(configResult.config, options.overrides));
|
|
10583
11592
|
const context = resolveProjectContext(root, config, {
|
|
10584
11593
|
runtimeDir: options.runtimeDir
|
|
10585
11594
|
});
|
|
@@ -10620,7 +11629,8 @@ var scanProject = async (root, options = {}) => {
|
|
|
10620
11629
|
const lastModified = resolveLastModifiedConfig(config.lastModified);
|
|
10621
11630
|
if (lastModified.enabled && lastModified.source === "git") {
|
|
10622
11631
|
const fsPaths = pages.map((page) => page.sourcePath).filter((path) => path !== undefined);
|
|
10623
|
-
const
|
|
11632
|
+
const contentRoots = sources.flatMap((source) => source.staged || !source.contentRoot ? [] : [source.contentRoot]);
|
|
11633
|
+
const gitTimes = gitLastModifiedTimes(context.root, contentRoots, fsPaths);
|
|
10624
11634
|
for (const page of pages) {
|
|
10625
11635
|
if (!page.lastModified && page.sourcePath) {
|
|
10626
11636
|
page.lastModified = gitTimes.get(page.sourcePath);
|
|
@@ -10659,11 +11669,18 @@ import { dirname as dirname10, join as join23, resolve as resolve7 } from "pathe
|
|
|
10659
11669
|
var ENV_LINE = /^\s*(?:export\s+)?(?<key>[A-Za-z_][A-Za-z0-9_]*)\s*=\s*(?<value>.*?)\s*$/u;
|
|
10660
11670
|
var DOUBLE_QUOTED2 = /^"(?<body>[\s\S]*)"$/u;
|
|
10661
11671
|
var SINGLE_QUOTED = /^'(?<body>[\s\S]*)'$/u;
|
|
11672
|
+
var ESCAPE = /\\(?<char>[\\nt"])/gu;
|
|
11673
|
+
var UNESCAPED = {
|
|
11674
|
+
'"': '"',
|
|
11675
|
+
"\\": "\\",
|
|
11676
|
+
n: `
|
|
11677
|
+
`,
|
|
11678
|
+
t: "\t"
|
|
11679
|
+
};
|
|
10662
11680
|
var unquote = (raw) => {
|
|
10663
11681
|
const double = raw.match(DOUBLE_QUOTED2)?.groups?.body;
|
|
10664
11682
|
if (double !== undefined) {
|
|
10665
|
-
return double.replaceAll(
|
|
10666
|
-
`).replaceAll("\\t", "\t").replaceAll("\\\"", '"').replaceAll("\\\\", "\\");
|
|
11683
|
+
return double.replaceAll(ESCAPE, (match, char) => UNESCAPED[char] ?? match);
|
|
10667
11684
|
}
|
|
10668
11685
|
const single = raw.match(SINGLE_QUOTED)?.groups?.body;
|
|
10669
11686
|
if (single !== undefined) {
|
|
@@ -10718,9 +11735,10 @@ var RED = `${ESC2}[31m`;
|
|
|
10718
11735
|
var BOLD = `${ESC2}[1m`;
|
|
10719
11736
|
var RESET = `${ESC2}[0m`;
|
|
10720
11737
|
var ISSUES_URL = "https://github.com/haydenbleasel/blume/issues";
|
|
10721
|
-
var BLUME_FRAME = /(?<abs
|
|
11738
|
+
var BLUME_FRAME = /(?<abs>(?:\/[^\s()]*\/|[A-Za-z]:\\[^\s()]*\\)\.blume[/\\][^\s()]*)/gu;
|
|
11739
|
+
var BLUME_MARKER = /[/\\]\.blume[/\\]/u;
|
|
10722
11740
|
var remapBlumeStack = (stack) => stack.replaceAll(BLUME_FRAME, (match) => {
|
|
10723
|
-
const marker = match.
|
|
11741
|
+
const marker = match.search(BLUME_MARKER);
|
|
10724
11742
|
return `${match.slice(marker + 1)} (generated)`;
|
|
10725
11743
|
});
|
|
10726
11744
|
var reportInternalError = (error) => {
|
|
@@ -10905,6 +11923,54 @@ var enforceBudget = async (distDir, args) => {
|
|
|
10905
11923
|
}
|
|
10906
11924
|
return passed ? "pass" : "fail";
|
|
10907
11925
|
};
|
|
11926
|
+
var runClientAssetChecks = async (staticDir, args) => {
|
|
11927
|
+
if (args.analyze) {
|
|
11928
|
+
await reportBundleSizes(staticDir);
|
|
11929
|
+
}
|
|
11930
|
+
if (await enforceBudget(staticDir, args) === "fail") {
|
|
11931
|
+
process.exit(1);
|
|
11932
|
+
}
|
|
11933
|
+
};
|
|
11934
|
+
var isolatedOutputDir = (config, context) => {
|
|
11935
|
+
const { adapter, output } = config.deployment;
|
|
11936
|
+
if (output === "server" && adapter === "vercel") {
|
|
11937
|
+
return join24(context.outDir, ".vercel", "output");
|
|
11938
|
+
}
|
|
11939
|
+
return context.distDir ?? join24(context.outDir, "dist");
|
|
11940
|
+
};
|
|
11941
|
+
var isolatedStaticDir = (config, context) => {
|
|
11942
|
+
const { adapter, output } = config.deployment;
|
|
11943
|
+
const outputDir = isolatedOutputDir(config, context);
|
|
11944
|
+
if (output === "server" && adapter === "vercel") {
|
|
11945
|
+
return join24(outputDir, "static");
|
|
11946
|
+
}
|
|
11947
|
+
if (output === "server" && adapter === "node") {
|
|
11948
|
+
return join24(outputDir, "client");
|
|
11949
|
+
}
|
|
11950
|
+
return outputDir;
|
|
11951
|
+
};
|
|
11952
|
+
var publishLlmsFiles = async (project, distDir) => {
|
|
11953
|
+
const indexPath = join24(distDir, "llms.txt");
|
|
11954
|
+
const fullPath = join24(distDir, "llms-full.txt");
|
|
11955
|
+
const writeIndex = !existsSync15(indexPath);
|
|
11956
|
+
const writeFull = !existsSync15(fullPath);
|
|
11957
|
+
if (!(writeIndex || writeFull)) {
|
|
11958
|
+
return;
|
|
11959
|
+
}
|
|
11960
|
+
const { index, full } = await buildLlmsFiles(project);
|
|
11961
|
+
const writes = [];
|
|
11962
|
+
if (writeIndex) {
|
|
11963
|
+
writes.push(writeFile7(indexPath, index, "utf-8"));
|
|
11964
|
+
}
|
|
11965
|
+
if (writeFull) {
|
|
11966
|
+
writes.push(writeFile7(fullPath, full, "utf-8"));
|
|
11967
|
+
}
|
|
11968
|
+
await Promise.all(writes);
|
|
11969
|
+
logger.success(`Generated ${[
|
|
11970
|
+
writeIndex ? "llms.txt" : null,
|
|
11971
|
+
writeFull ? "llms-full.txt" : null
|
|
11972
|
+
].filter(Boolean).join(" and ")}`);
|
|
11973
|
+
};
|
|
10908
11974
|
var publishBuildArtifacts = async (project, distDir, args) => {
|
|
10909
11975
|
if (project.config.search.provider === "pagefind") {
|
|
10910
11976
|
logger.start("Building search index");
|
|
@@ -10916,13 +11982,8 @@ var publishBuildArtifacts = async (project, distDir, args) => {
|
|
|
10916
11982
|
success: (message) => logger.success(message),
|
|
10917
11983
|
warn: (message) => logger.warn(message)
|
|
10918
11984
|
});
|
|
10919
|
-
if (project.config.ai.llmsTxt) {
|
|
10920
|
-
|
|
10921
|
-
await Promise.all([
|
|
10922
|
-
writeFile7(join24(distDir, "llms.txt"), index, "utf-8"),
|
|
10923
|
-
writeFile7(join24(distDir, "llms-full.txt"), full, "utf-8")
|
|
10924
|
-
]);
|
|
10925
|
-
logger.success("Generated llms.txt and llms-full.txt");
|
|
11985
|
+
if (project.config.ai.llmsTxt.enabled) {
|
|
11986
|
+
await publishLlmsFiles(project, distDir);
|
|
10926
11987
|
}
|
|
10927
11988
|
const sitemap = buildSitemap(project);
|
|
10928
11989
|
if (sitemap && !existsSync15(join24(distDir, "sitemap.xml"))) {
|
|
@@ -10943,25 +12004,21 @@ var publishBuildArtifacts = async (project, distDir, args) => {
|
|
|
10943
12004
|
await emitRedirectFiles(project.config, distDir);
|
|
10944
12005
|
const { config } = project;
|
|
10945
12006
|
const features = serverFeatures(config);
|
|
12007
|
+
const sitemapNote = config.seo.sitemap ? "no (set deployment.site)" : "no (seo.sitemap is false)";
|
|
10946
12008
|
logger.box([
|
|
10947
12009
|
`Output ${config.deployment.output}`,
|
|
10948
12010
|
`Adapter ${config.deployment.adapter ?? "none"}`,
|
|
10949
12011
|
`Site ${config.deployment.site ?? "not set"}`,
|
|
10950
12012
|
`Search ${config.search.provider}`,
|
|
10951
12013
|
`Redirects ${config.redirects.length}`,
|
|
10952
|
-
`Sitemap ${sitemap ? "yes" :
|
|
12014
|
+
`Sitemap ${sitemap ? "yes" : sitemapNote}`,
|
|
10953
12015
|
`Robots ${robots ? "yes" : "no"}`,
|
|
10954
12016
|
`Agent JSON ${agentReadability ? "yes" : "no"}`,
|
|
10955
|
-
`LLM files ${config.ai.llmsTxt ? "yes" : "no"}`,
|
|
12017
|
+
`LLM files ${config.ai.llmsTxt.enabled ? "yes" : "no"}`,
|
|
10956
12018
|
`Server features ${features.length > 0 ? features.join(", ") : "none"}`
|
|
10957
12019
|
].join(`
|
|
10958
12020
|
`));
|
|
10959
|
-
|
|
10960
|
-
await reportBundleSizes(distDir);
|
|
10961
|
-
}
|
|
10962
|
-
if (await enforceBudget(distDir, args) === "fail") {
|
|
10963
|
-
process.exit(1);
|
|
10964
|
-
}
|
|
12021
|
+
await runClientAssetChecks(distDir, args);
|
|
10965
12022
|
logger.success(`Built to ${distDir}`);
|
|
10966
12023
|
};
|
|
10967
12024
|
var buildCommand = defineCommand2({
|
|
@@ -11007,7 +12064,7 @@ var buildCommand = defineCommand2({
|
|
|
11007
12064
|
async run({ args }) {
|
|
11008
12065
|
const root = process.cwd();
|
|
11009
12066
|
const runtimeDir = args.isolated ? ".blume-verify" : process.env.BLUME_RUNTIME_DIR;
|
|
11010
|
-
refuseIfDevRunning(root, "building", runtimeDir);
|
|
12067
|
+
refuseIfDevRunning(root, "building", { isolatedHint: true, runtimeDir });
|
|
11011
12068
|
if (args.isolated) {
|
|
11012
12069
|
await ensureGitignore(root, [".blume-verify/"]);
|
|
11013
12070
|
}
|
|
@@ -11037,9 +12094,9 @@ var buildCommand = defineCommand2({
|
|
|
11037
12094
|
logLevel: "info",
|
|
11038
12095
|
root: project.context.outDir
|
|
11039
12096
|
});
|
|
11040
|
-
const distDir = project.context.distDir ?? join24(root, "dist");
|
|
11041
12097
|
if (runtimeDir) {
|
|
11042
|
-
|
|
12098
|
+
await runClientAssetChecks(isolatedStaticDir(project.config, project.context), args);
|
|
12099
|
+
logger.success(`Isolated build OK — output at ${isolatedOutputDir(project.config, project.context)} (not published).`);
|
|
11043
12100
|
return;
|
|
11044
12101
|
}
|
|
11045
12102
|
const surfaced = await surfaceAdapterOutput(project.config, project.context);
|
|
@@ -11079,7 +12136,7 @@ var checkCommand = defineCommand3({
|
|
|
11079
12136
|
async run({ args }) {
|
|
11080
12137
|
const root = process.cwd();
|
|
11081
12138
|
const runtimeDir = args.isolated ? ".blume-verify" : process.env.BLUME_RUNTIME_DIR;
|
|
11082
|
-
refuseIfDevRunning(root, "checking", runtimeDir);
|
|
12139
|
+
refuseIfDevRunning(root, "checking", { isolatedHint: true, runtimeDir });
|
|
11083
12140
|
if (args.isolated) {
|
|
11084
12141
|
await ensureGitignore(root, [".blume-verify/"]);
|
|
11085
12142
|
}
|
|
@@ -11191,6 +12248,7 @@ var coalescedRunner = (task) => {
|
|
|
11191
12248
|
};
|
|
11192
12249
|
|
|
11193
12250
|
// src/cli/commands/dev.ts
|
|
12251
|
+
var normalizeHost = (host) => host === "" ? true : host ?? false;
|
|
11194
12252
|
var routeSignature = (routes) => routes.map((route) => `${route.path} ${route.entryId}`).toSorted().join(`
|
|
11195
12253
|
`);
|
|
11196
12254
|
var devCommand = defineCommand4({
|
|
@@ -11246,7 +12304,7 @@ var devCommand = defineCommand4({
|
|
|
11246
12304
|
const createServer = (listenPort, open) => dev({
|
|
11247
12305
|
logLevel: args.debug ? "debug" : "info",
|
|
11248
12306
|
root: project.context.outDir,
|
|
11249
|
-
server: { host: args.host
|
|
12307
|
+
server: { host: normalizeHost(args.host), open, port: listenPort }
|
|
11250
12308
|
});
|
|
11251
12309
|
let server = await createServer(explicitPort, args.open ?? false);
|
|
11252
12310
|
const boundPort = server.address.port;
|
|
@@ -11266,7 +12324,6 @@ var devCommand = defineCommand4({
|
|
|
11266
12324
|
});
|
|
11267
12325
|
const nextSignature = routeSignature(next.manifest.routes);
|
|
11268
12326
|
const structural = nextSignature !== lastSignature;
|
|
11269
|
-
lastSignature = nextSignature;
|
|
11270
12327
|
if (structural) {
|
|
11271
12328
|
await server.stop();
|
|
11272
12329
|
await generateRuntime(next);
|
|
@@ -11274,6 +12331,8 @@ var devCommand = defineCommand4({
|
|
|
11274
12331
|
} else {
|
|
11275
12332
|
await generateRuntime(next);
|
|
11276
12333
|
}
|
|
12334
|
+
lastSignature = nextSignature;
|
|
12335
|
+
reportDiagnostics(next.diagnostics, root);
|
|
11277
12336
|
showBlumeErrorOverlay(next.diagnostics);
|
|
11278
12337
|
} catch (error) {
|
|
11279
12338
|
logger.error(`Regeneration failed: ${error.message}`);
|
|
@@ -11415,15 +12474,27 @@ var doctorCommand = defineCommand5({
|
|
|
11415
12474
|
});
|
|
11416
12475
|
|
|
11417
12476
|
// src/cli/commands/eject.ts
|
|
11418
|
-
import { readFile as readFile13, writeFile as writeFile9 } from "node:fs/promises";
|
|
11419
12477
|
import { defineCommand as defineCommand6 } from "citty";
|
|
11420
|
-
import {
|
|
12478
|
+
import { relative as relative14 } from "pathe";
|
|
11421
12479
|
|
|
11422
12480
|
// src/registry/eject.ts
|
|
11423
12481
|
import { existsSync as existsSync17 } from "node:fs";
|
|
11424
12482
|
import { cp as cp2, mkdir as mkdir7, readFile as readFile12, rm as rm3, writeFile as writeFile8 } from "node:fs/promises";
|
|
11425
12483
|
import { join as join27, relative as relative12 } from "pathe";
|
|
11426
12484
|
var toPosix = (path) => path.split("\\").join("/");
|
|
12485
|
+
var LOCAL_BLUME_SOURCE = "../../node_modules/blume/src/**/*.{astro,ts,tsx}";
|
|
12486
|
+
var blumeSourceGlob = (root, genDir, resolveBlumeRoot = packageRoot) => {
|
|
12487
|
+
if (existsSync17(join27(root, "node_modules", "blume"))) {
|
|
12488
|
+
return LOCAL_BLUME_SOURCE;
|
|
12489
|
+
}
|
|
12490
|
+
try {
|
|
12491
|
+
const src = join27(resolveBlumeRoot(), "src");
|
|
12492
|
+
return `${toPosix(relative12(genDir, src))}/**/*.{astro,ts,tsx}`;
|
|
12493
|
+
} catch {
|
|
12494
|
+
console.warn('blume: could not locate the installed blume package; src/generated/app.css keeps its default `@source "../../node_modules/blume/..."` glob. If blume is hoisted elsewhere, point that glob at its install location or Blume\'s utility classes will be missing.');
|
|
12495
|
+
return LOCAL_BLUME_SOURCE;
|
|
12496
|
+
}
|
|
12497
|
+
};
|
|
11427
12498
|
var ejectOpenApiData = (project) => {
|
|
11428
12499
|
const source = project.sources.find(isOpenApiSource);
|
|
11429
12500
|
return source ? source.openApiData() : {};
|
|
@@ -11449,6 +12520,63 @@ var askFiles = async (project, srcDir, genDir) => {
|
|
|
11449
12520
|
}
|
|
11450
12521
|
return files;
|
|
11451
12522
|
};
|
|
12523
|
+
var hostsMcp = (project, userPages) => project.config.mcp.enabled && !routeIsTaken(userPages, project.graph.pages, project.config.mcp.route);
|
|
12524
|
+
var mcpDiscoveryPages = (project, userPages) => hostsMcp(project, userPages) ? [
|
|
12525
|
+
{
|
|
12526
|
+
entrypoint: "src/blume-mcp/discovery.ts",
|
|
12527
|
+
pattern: "/.well-known/mcp.json"
|
|
12528
|
+
},
|
|
12529
|
+
{
|
|
12530
|
+
entrypoint: "src/blume-mcp/server-card.ts",
|
|
12531
|
+
pattern: "/.well-known/mcp/server-card.json"
|
|
12532
|
+
}
|
|
12533
|
+
] : [];
|
|
12534
|
+
var mcpFiles = async (project, userPages, srcDir, genDir) => {
|
|
12535
|
+
if (!hostsMcp(project, userPages)) {
|
|
12536
|
+
return [];
|
|
12537
|
+
}
|
|
12538
|
+
const { route } = project.config.mcp;
|
|
12539
|
+
const data = await buildMcpData(project);
|
|
12540
|
+
const discoveryInput = {
|
|
12541
|
+
base: data.base,
|
|
12542
|
+
name: data.name,
|
|
12543
|
+
route,
|
|
12544
|
+
site: data.site,
|
|
12545
|
+
version: data.version
|
|
12546
|
+
};
|
|
12547
|
+
return [
|
|
12548
|
+
{
|
|
12549
|
+
content: `${JSON.stringify(data)}
|
|
12550
|
+
`,
|
|
12551
|
+
path: join27(genDir, "mcp-data.json")
|
|
12552
|
+
},
|
|
12553
|
+
{
|
|
12554
|
+
content: mcpEndpointTemplate(route),
|
|
12555
|
+
path: join27(srcDir, "pages", mcpPageFile(route))
|
|
12556
|
+
},
|
|
12557
|
+
{
|
|
12558
|
+
content: staticJsonEndpointTemplate(buildMcpDiscovery(discoveryInput)),
|
|
12559
|
+
path: join27(srcDir, "blume-mcp", "discovery.ts")
|
|
12560
|
+
},
|
|
12561
|
+
{
|
|
12562
|
+
content: staticJsonEndpointTemplate(buildMcpServerCard(discoveryInput)),
|
|
12563
|
+
path: join27(srcDir, "blume-mcp", "server-card.ts")
|
|
12564
|
+
}
|
|
12565
|
+
];
|
|
12566
|
+
};
|
|
12567
|
+
var changelogFiles = (project, userPages, srcDir, options) => {
|
|
12568
|
+
const hasChangelog = project.graph.pages.some((page) => page.contentType === "changelog" && !(page.meta.draft || page.meta.sidebar.hidden));
|
|
12569
|
+
const hasChangelogSource = (project.config.content.sources ?? []).some((source) => source.type === "github-releases");
|
|
12570
|
+
if (!(hasChangelog || hasChangelogSource) || routeIsTaken(userPages, project.graph.pages, "/changelog")) {
|
|
12571
|
+
return [];
|
|
12572
|
+
}
|
|
12573
|
+
return [
|
|
12574
|
+
{
|
|
12575
|
+
content: changelogIndexTemplate(options),
|
|
12576
|
+
path: join27(srcDir, "pages", "changelog.astro")
|
|
12577
|
+
}
|
|
12578
|
+
];
|
|
12579
|
+
};
|
|
11452
12580
|
var readExamplesCss = (root, css) => css && existsSync17(join27(root, css)) ? readFile12(join27(root, css), "utf-8") : Promise.resolve("");
|
|
11453
12581
|
var examplesPreviewFiles = (srcDir, basePath, hasExamples) => hasExamples ? [
|
|
11454
12582
|
{
|
|
@@ -11497,10 +12625,13 @@ var eject = async (root) => {
|
|
|
11497
12625
|
root: "."
|
|
11498
12626
|
};
|
|
11499
12627
|
const componentsImport = context.componentsFile ? `../../${toPosix(relative12(root, context.componentsFile))}` : null;
|
|
11500
|
-
const relPages =
|
|
11501
|
-
|
|
11502
|
-
|
|
11503
|
-
|
|
12628
|
+
const relPages = [
|
|
12629
|
+
...pages.map((page) => ({
|
|
12630
|
+
entrypoint: toPosix(relative12(root, page.entrypoint)),
|
|
12631
|
+
pattern: page.pattern
|
|
12632
|
+
})),
|
|
12633
|
+
...mcpDiscoveryPages(project, pages)
|
|
12634
|
+
];
|
|
11504
12635
|
const staged = collectStaged(project);
|
|
11505
12636
|
const hasStaged = staged.size > 0;
|
|
11506
12637
|
const stagedDir = "blume-staged";
|
|
@@ -11572,7 +12703,7 @@ var eject = async (root) => {
|
|
|
11572
12703
|
content: tailwindEntryTemplate({
|
|
11573
12704
|
configTokens: buildThemeCss(config.theme),
|
|
11574
12705
|
sources: [
|
|
11575
|
-
|
|
12706
|
+
blumeSourceGlob(root, genDir),
|
|
11576
12707
|
"../../**/*.{astro,mdx,ts,tsx}"
|
|
11577
12708
|
],
|
|
11578
12709
|
twoslashCss: twoslashCss(),
|
|
@@ -11592,11 +12723,11 @@ var eject = async (root) => {
|
|
|
11592
12723
|
path: join27(genDir, "raw-markdown.json")
|
|
11593
12724
|
},
|
|
11594
12725
|
{
|
|
11595
|
-
content: rawMarkdownEndpointTemplate(),
|
|
12726
|
+
content: rawMarkdownEndpointTemplate("md"),
|
|
11596
12727
|
path: join27(srcDir, "pages", "[...slug].md.ts")
|
|
11597
12728
|
},
|
|
11598
12729
|
{
|
|
11599
|
-
content: rawMarkdownEndpointTemplate(),
|
|
12730
|
+
content: rawMarkdownEndpointTemplate("mdx"),
|
|
11600
12731
|
path: join27(srcDir, "pages", "[...slug].mdx.ts")
|
|
11601
12732
|
}
|
|
11602
12733
|
];
|
|
@@ -11609,6 +12740,13 @@ var eject = async (root) => {
|
|
|
11609
12740
|
path: join27(srcDir, "pages", "og", "[...slug].png.ts")
|
|
11610
12741
|
});
|
|
11611
12742
|
}
|
|
12743
|
+
files.push(...await mcpFiles(project, pages, srcDir, genDir), ...changelogFiles(project, pages, srcDir, {
|
|
12744
|
+
askEnabled,
|
|
12745
|
+
exportEpub,
|
|
12746
|
+
exportPdf,
|
|
12747
|
+
needsReact,
|
|
12748
|
+
staged: hasStaged
|
|
12749
|
+
}));
|
|
11612
12750
|
if (!routeIsTaken(pages, project.graph.pages, "/404")) {
|
|
11613
12751
|
files.push({
|
|
11614
12752
|
content: notFoundPageTemplate(),
|
|
@@ -11648,12 +12786,14 @@ var eject = async (root) => {
|
|
|
11648
12786
|
path: join27(srcDir, "pages", "[section]", "rss.xml.ts")
|
|
11649
12787
|
});
|
|
11650
12788
|
}
|
|
12789
|
+
const warnings = [];
|
|
11651
12790
|
if (hasScalarReferences(config)) {
|
|
11652
12791
|
const references = await buildReferenceFiles({
|
|
11653
12792
|
config,
|
|
11654
12793
|
contentRoutes: new Set(project.graph.pages.map((page) => page.route)),
|
|
11655
12794
|
root
|
|
11656
12795
|
});
|
|
12796
|
+
warnings.push(...references.warnings);
|
|
11657
12797
|
for (const file of references.files) {
|
|
11658
12798
|
files.push({
|
|
11659
12799
|
content: file.content,
|
|
@@ -11683,10 +12823,37 @@ var eject = async (root) => {
|
|
|
11683
12823
|
});
|
|
11684
12824
|
}
|
|
11685
12825
|
await rm3(context.outDir, { force: true, recursive: true });
|
|
11686
|
-
return written.map((file) => file.path);
|
|
12826
|
+
return { files: written.map((file) => file.path), warnings };
|
|
11687
12827
|
};
|
|
11688
12828
|
|
|
11689
|
-
// src/cli/
|
|
12829
|
+
// src/cli/eject-scripts.ts
|
|
12830
|
+
import { readFile as readFile13, writeFile as writeFile9 } from "node:fs/promises";
|
|
12831
|
+
import { join as join28 } from "pathe";
|
|
12832
|
+
var droppedArtifactNotices = (config) => {
|
|
12833
|
+
const notices = [];
|
|
12834
|
+
if (config.search.provider === "pagefind") {
|
|
12835
|
+
notices.push('the Pagefind search index — the search UI loads it from the built site, so search will break in production. Add a post-build step: `"build": "astro build && pagefind --site dist"` (with `pagefind` installed as a devDependency).');
|
|
12836
|
+
}
|
|
12837
|
+
if (searchProviderMeta(config.search.provider).syncs) {
|
|
12838
|
+
notices.push(`the hosted ${config.search.provider} index sync — new and updated pages stop being pushed; re-upload your search records after each build with the provider's API or CLI.`);
|
|
12839
|
+
}
|
|
12840
|
+
if (config.ai.llmsTxt.enabled) {
|
|
12841
|
+
notices.push("llms.txt and llms-full.txt");
|
|
12842
|
+
}
|
|
12843
|
+
if (config.deployment.site && config.seo.sitemap) {
|
|
12844
|
+
notices.push("sitemap.xml — recreate it with the @astrojs/sitemap integration.");
|
|
12845
|
+
}
|
|
12846
|
+
if (config.seo.robots) {
|
|
12847
|
+
notices.push("robots.txt — recreate it as a public/robots.txt file.");
|
|
12848
|
+
}
|
|
12849
|
+
if (config.seo.agentReadability) {
|
|
12850
|
+
notices.push("agent-readability.json");
|
|
12851
|
+
}
|
|
12852
|
+
if (config.redirects.length > 0 && config.deployment.output === "static") {
|
|
12853
|
+
notices.push("the platform redirect files (_redirects, vercel.json) — your redirects still work as Astro-generated meta-refresh pages.");
|
|
12854
|
+
}
|
|
12855
|
+
return notices;
|
|
12856
|
+
};
|
|
11690
12857
|
var updatePackageScripts = async (root) => {
|
|
11691
12858
|
const pkgPath = join28(root, "package.json");
|
|
11692
12859
|
let pkg;
|
|
@@ -11705,47 +12872,21 @@ var updatePackageScripts = async (root) => {
|
|
|
11705
12872
|
await writeFile9(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
11706
12873
|
`, "utf-8");
|
|
11707
12874
|
};
|
|
11708
|
-
var ejectCommand = defineCommand6({
|
|
11709
|
-
args: {
|
|
11710
|
-
yes: { description: "Skip the confirmation prompt.", type: "boolean" }
|
|
11711
|
-
},
|
|
11712
|
-
meta: {
|
|
11713
|
-
description: "Promote the generated runtime into an owned Astro project.",
|
|
11714
|
-
name: "eject"
|
|
11715
|
-
},
|
|
11716
|
-
async run({ args }) {
|
|
11717
|
-
const root = process.cwd();
|
|
11718
|
-
refuseIfDevRunning(root, "ejecting");
|
|
11719
|
-
if (!args.yes) {
|
|
11720
|
-
logger.warn("Eject is one-way: it writes astro.config.mjs, src/, and (if absent) tsconfig.json, rewrites your package.json scripts, and removes .blume. An existing tsconfig.json is left untouched.");
|
|
11721
|
-
logger.info("Re-run with --yes to proceed.");
|
|
11722
|
-
return;
|
|
11723
|
-
}
|
|
11724
|
-
const files = await eject(root);
|
|
11725
|
-
await updatePackageScripts(root);
|
|
11726
|
-
logger.success(`Ejected ${files.length} file(s):`);
|
|
11727
|
-
for (const file of files) {
|
|
11728
|
-
process.stdout.write(` ${relative13(root, file)}
|
|
11729
|
-
`);
|
|
11730
|
-
}
|
|
11731
|
-
logger.box(`Your project is now a standalone Astro app.
|
|
11732
|
-
|
|
11733
|
-
bun run dev
|
|
11734
|
-
bun run build
|
|
11735
|
-
|
|
11736
|
-
The blume package remains importable.`);
|
|
11737
|
-
}
|
|
11738
|
-
});
|
|
11739
12875
|
|
|
11740
|
-
// src/cli/
|
|
12876
|
+
// src/cli/init/scaffold.ts
|
|
11741
12877
|
import { existsSync as existsSync18 } from "node:fs";
|
|
11742
12878
|
import { mkdir as mkdir8, writeFile as writeFile10 } from "node:fs/promises";
|
|
11743
|
-
import {
|
|
11744
|
-
import { basename as basename4, dirname as dirname11, isAbsolute as isAbsolute9, join as join29, relative as relative14 } from "pathe";
|
|
12879
|
+
import { basename as basename4, dirname as dirname11, isAbsolute as isAbsolute9, join as join29, relative as relative13 } from "pathe";
|
|
11745
12880
|
|
|
11746
12881
|
// src/core/package-json.ts
|
|
11747
12882
|
var toPackageName = (raw) => raw.toLowerCase().replaceAll(/[^a-z0-9._-]+/gu, "-").replaceAll(/^[-_.]+|[-_.]+$/gu, "") || "docs";
|
|
11748
|
-
var blumePackageJson = (name) =>
|
|
12883
|
+
var blumePackageJson = (name, extraDeps = {}) => {
|
|
12884
|
+
const dependencies = Object.entries({
|
|
12885
|
+
blume: `^${getBlumeVersion()}`,
|
|
12886
|
+
...extraDeps
|
|
12887
|
+
}).toSorted(([a], [b]) => a < b ? -1 : 1).map(([dep, range]) => ` ${JSON.stringify(dep)}: ${JSON.stringify(range)}`).join(`,
|
|
12888
|
+
`);
|
|
12889
|
+
return `{
|
|
11749
12890
|
"name": ${JSON.stringify(name)},
|
|
11750
12891
|
"private": true,
|
|
11751
12892
|
"type": "module",
|
|
@@ -11755,21 +12896,22 @@ var blumePackageJson = (name) => `{
|
|
|
11755
12896
|
"doctor": "blume doctor"
|
|
11756
12897
|
},
|
|
11757
12898
|
"dependencies": {
|
|
11758
|
-
|
|
12899
|
+
${dependencies}
|
|
11759
12900
|
}
|
|
11760
12901
|
}
|
|
11761
12902
|
`;
|
|
12903
|
+
};
|
|
11762
12904
|
|
|
11763
|
-
// src/cli/
|
|
12905
|
+
// src/cli/init/scaffold.ts
|
|
11764
12906
|
var TEMPLATES = ["docs", "api", "sdk", "changelog"];
|
|
11765
12907
|
var PACKAGE_MANAGERS = ["npm", "pnpm", "yarn", "bun"];
|
|
11766
|
-
var
|
|
11767
|
-
|
|
11768
|
-
|
|
11769
|
-
|
|
11770
|
-
|
|
11771
|
-
|
|
11772
|
-
|
|
12908
|
+
var SOURCE_KINDS = [
|
|
12909
|
+
"filesystem",
|
|
12910
|
+
"github-releases",
|
|
12911
|
+
"notion",
|
|
12912
|
+
"sanity",
|
|
12913
|
+
"mdx-remote"
|
|
12914
|
+
];
|
|
11773
12915
|
var page = (title, description, body) => `---
|
|
11774
12916
|
title: ${title}
|
|
11775
12917
|
description: ${description}
|
|
@@ -11779,7 +12921,7 @@ ${body}
|
|
|
11779
12921
|
`;
|
|
11780
12922
|
var STARTERS = {
|
|
11781
12923
|
api: {
|
|
11782
|
-
|
|
12924
|
+
configExtra: `
|
|
11783
12925
|
openapi: {
|
|
11784
12926
|
enabled: true,
|
|
11785
12927
|
route: "/api",
|
|
@@ -11789,7 +12931,7 @@ var STARTERS = {
|
|
|
11789
12931
|
spec: "https://petstore3.swagger.io/api/v3/openapi.json",
|
|
11790
12932
|
},
|
|
11791
12933
|
],
|
|
11792
|
-
}
|
|
12934
|
+
},`,
|
|
11793
12935
|
files: (dir) => [
|
|
11794
12936
|
{
|
|
11795
12937
|
content: page("API Reference", "Explore the API.", "# API Reference\n\nYour OpenAPI spec renders at [`/api`](/api). Point `openapi.sources` at your own spec in `blume.config.ts`."),
|
|
@@ -11798,13 +12940,13 @@ var STARTERS = {
|
|
|
11798
12940
|
]
|
|
11799
12941
|
},
|
|
11800
12942
|
changelog: {
|
|
11801
|
-
|
|
12943
|
+
configExtra: `
|
|
11802
12944
|
navigation: {
|
|
11803
12945
|
tabs: [
|
|
11804
12946
|
{ label: "Docs", path: "/" },
|
|
11805
12947
|
{ label: "Changelog", path: "/changelog" },
|
|
11806
12948
|
],
|
|
11807
|
-
}
|
|
12949
|
+
},`,
|
|
11808
12950
|
files: (dir) => [
|
|
11809
12951
|
{
|
|
11810
12952
|
content: page("Introduction", "Welcome to your new Blume docs.", "# Introduction\n\nWrite your docs here, and log releases under `changelog/`."),
|
|
@@ -11824,7 +12966,7 @@ The first release. Edit \`${dir}/changelog/v1-0-0.mdx\` or add new entries besid
|
|
|
11824
12966
|
]
|
|
11825
12967
|
},
|
|
11826
12968
|
docs: {
|
|
11827
|
-
|
|
12969
|
+
configExtra: "",
|
|
11828
12970
|
files: (dir) => [
|
|
11829
12971
|
{
|
|
11830
12972
|
content: page("Introduction", "Welcome to your new Blume docs.", `# Introduction
|
|
@@ -11837,7 +12979,7 @@ Edit \`${dir}/index.mdx\` to get started, then run \`blume dev\`.`),
|
|
|
11837
12979
|
]
|
|
11838
12980
|
},
|
|
11839
12981
|
sdk: {
|
|
11840
|
-
|
|
12982
|
+
configExtra: "",
|
|
11841
12983
|
files: (dir) => [
|
|
11842
12984
|
{
|
|
11843
12985
|
content: page("Introduction", "Get started with the SDK.", `# Introduction
|
|
@@ -11853,26 +12995,331 @@ Install the SDK and make your first call. See [Installation](/installation).`),
|
|
|
11853
12995
|
}
|
|
11854
12996
|
};
|
|
11855
12997
|
var commandsFor = (pm) => ({
|
|
12998
|
+
build: pm === "npm" || pm === "bun" ? `${pm} run build` : `${pm} build`,
|
|
11856
12999
|
dev: pm === "npm" ? "npm run dev" : `${pm} dev`,
|
|
13000
|
+
exec: { bun: "bunx", npm: "npx", pnpm: "pnpm exec", yarn: "yarn" }[pm],
|
|
11857
13001
|
install: `${pm} install`
|
|
11858
13002
|
});
|
|
11859
|
-
var
|
|
11860
|
-
|
|
11861
|
-
|
|
13003
|
+
var detectPackageManager = (userAgent) => {
|
|
13004
|
+
const name = userAgent?.split("/")[0];
|
|
13005
|
+
return name !== undefined && PACKAGE_MANAGERS.includes(name) ? name : "npm";
|
|
13006
|
+
};
|
|
13007
|
+
var validateContentDir = (root, dir) => isAbsolute9(dir) || relative13(root, join29(root, dir)).startsWith("..") ? "Must be a relative path inside the project." : undefined;
|
|
13008
|
+
var titleize = (raw) => {
|
|
13009
|
+
const words = raw.replaceAll(/[-_.]+/gu, " ").split(/\s+/u).filter(Boolean);
|
|
13010
|
+
return words.length === 0 ? "My Docs" : words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
13011
|
+
};
|
|
13012
|
+
var hasRemoteSource = (sources) => sources.some((source) => source !== "filesystem");
|
|
13013
|
+
var sourceSnippetFor = (kind) => {
|
|
13014
|
+
switch (kind) {
|
|
13015
|
+
case "github-releases": {
|
|
13016
|
+
return ` // Changelog entries from GitHub Releases. Private repos read
|
|
13017
|
+
// GITHUB_TOKEN from the environment.
|
|
13018
|
+
{
|
|
13019
|
+
type: "github-releases",
|
|
13020
|
+
owner: "your-org",
|
|
13021
|
+
repo: "your-repo",
|
|
13022
|
+
prefix: "changelog",
|
|
13023
|
+
},`;
|
|
13024
|
+
}
|
|
13025
|
+
case "notion": {
|
|
13026
|
+
return ` // Pages from a Notion database. Reads NOTION_TOKEN from the environment.
|
|
13027
|
+
{
|
|
13028
|
+
type: "notion",
|
|
13029
|
+
database: "your-database-id",
|
|
13030
|
+
prefix: "notion",
|
|
13031
|
+
},`;
|
|
13032
|
+
}
|
|
13033
|
+
case "sanity": {
|
|
13034
|
+
return ` // Documents from a Sanity dataset. Private datasets read SANITY_TOKEN
|
|
13035
|
+
// from the environment.
|
|
13036
|
+
{
|
|
13037
|
+
type: "sanity",
|
|
13038
|
+
projectId: "your-project-id",
|
|
13039
|
+
dataset: "production",
|
|
13040
|
+
query: \`*[_type == "doc"]\`,
|
|
13041
|
+
prefix: "sanity",
|
|
13042
|
+
},`;
|
|
13043
|
+
}
|
|
13044
|
+
case "mdx-remote": {
|
|
13045
|
+
return ` // MDX fetched from a GitHub repo. Private repos read GITHUB_TOKEN
|
|
13046
|
+
// from the environment.
|
|
13047
|
+
{
|
|
13048
|
+
type: "mdx-remote",
|
|
13049
|
+
github: { owner: "your-org", repo: "your-repo", path: "docs" },
|
|
13050
|
+
prefix: "remote",
|
|
13051
|
+
},`;
|
|
13052
|
+
}
|
|
13053
|
+
default: {
|
|
13054
|
+
return kind;
|
|
13055
|
+
}
|
|
13056
|
+
}
|
|
13057
|
+
};
|
|
13058
|
+
var contentBlockFor = (answers) => {
|
|
13059
|
+
const sources = answers.sources.length === 0 ? ["filesystem"] : answers.sources;
|
|
13060
|
+
if (!hasRemoteSource(sources)) {
|
|
13061
|
+
return answers.contentDir === "docs" ? "" : `
|
|
13062
|
+
content: {
|
|
13063
|
+
root: ${JSON.stringify(answers.contentDir)},
|
|
13064
|
+
},`;
|
|
13065
|
+
}
|
|
13066
|
+
const entries = SOURCE_KINDS.filter((kind) => sources.includes(kind)).map((kind) => kind === "filesystem" ? ` { type: "filesystem", root: ${JSON.stringify(answers.contentDir)} },` : sourceSnippetFor(kind));
|
|
13067
|
+
return `
|
|
13068
|
+
content: {
|
|
13069
|
+
sources: [
|
|
13070
|
+
${entries.join(`
|
|
13071
|
+
`)}
|
|
13072
|
+
],
|
|
13073
|
+
},`;
|
|
13074
|
+
};
|
|
13075
|
+
var buildConfig = (answers) => `import { defineConfig } from "blume";
|
|
13076
|
+
|
|
13077
|
+
export default defineConfig({
|
|
13078
|
+
title: ${JSON.stringify(answers.title)},
|
|
13079
|
+
description: "Documentation powered by Blume.",${STARTERS[answers.template].configExtra}${contentBlockFor(answers)}
|
|
13080
|
+
});
|
|
13081
|
+
`;
|
|
13082
|
+
var extraDepsFor = (sources) => ({
|
|
13083
|
+
...sources.includes("notion") && { "@notionhq/client": "^2.2.15" },
|
|
13084
|
+
...sources.includes("sanity") && { "@sanity/client": "^6.21.0" }
|
|
13085
|
+
});
|
|
13086
|
+
var buildPlan = (root, answers) => {
|
|
13087
|
+
const files = [
|
|
13088
|
+
{
|
|
13089
|
+
content: blumePackageJson(toPackageName(basename4(root)), extraDepsFor(answers.sources)),
|
|
13090
|
+
path: join29(root, "package.json")
|
|
13091
|
+
},
|
|
13092
|
+
{ content: buildConfig(answers), path: join29(root, "blume.config.ts") }
|
|
13093
|
+
];
|
|
13094
|
+
if (answers.sources.length === 0 || answers.sources.includes("filesystem")) {
|
|
13095
|
+
files.push(...STARTERS[answers.template].files(answers.contentDir).map((file) => ({ ...file, path: join29(root, file.path) })));
|
|
13096
|
+
}
|
|
13097
|
+
return files;
|
|
13098
|
+
};
|
|
13099
|
+
var writeFileSafe = async (file, log) => {
|
|
13100
|
+
if (existsSync18(file.path)) {
|
|
13101
|
+
log.info(`Skipped existing ${file.path}`);
|
|
11862
13102
|
return false;
|
|
11863
13103
|
}
|
|
11864
|
-
await mkdir8(dirname11(path), { recursive: true });
|
|
11865
|
-
await writeFile10(path, content, "utf-8");
|
|
11866
|
-
|
|
13104
|
+
await mkdir8(dirname11(file.path), { recursive: true });
|
|
13105
|
+
await writeFile10(file.path, file.content, "utf-8");
|
|
13106
|
+
log.success(`Created ${file.path}`);
|
|
11867
13107
|
return true;
|
|
11868
13108
|
};
|
|
13109
|
+
var applyPlan = async (files, log) => {
|
|
13110
|
+
const created = await Promise.all(files.map((file) => writeFileSafe(file, log)));
|
|
13111
|
+
const createdPackage = files.some((file, index) => created[index] && basename4(file.path) === "package.json");
|
|
13112
|
+
return { createdPackage };
|
|
13113
|
+
};
|
|
13114
|
+
var envVarsFor = (sources) => [
|
|
13115
|
+
["GITHUB_TOKEN", ["github-releases", "mdx-remote"]],
|
|
13116
|
+
["NOTION_TOKEN", ["notion"]],
|
|
13117
|
+
["SANITY_TOKEN", ["sanity"]]
|
|
13118
|
+
].filter(([, kinds]) => kinds.some((kind) => sources.includes(kind))).map(([envVar]) => envVar);
|
|
13119
|
+
var nextSteps = (answers, createdPackage) => {
|
|
13120
|
+
const commands = commandsFor(answers.packageManager);
|
|
13121
|
+
const lines = [];
|
|
13122
|
+
if (answers.directory !== ".") {
|
|
13123
|
+
lines.push(`cd ${answers.directory}`);
|
|
13124
|
+
}
|
|
13125
|
+
if (createdPackage) {
|
|
13126
|
+
lines.push(commands.install);
|
|
13127
|
+
}
|
|
13128
|
+
lines.push(commands.dev);
|
|
13129
|
+
const envVars = envVarsFor(answers.sources);
|
|
13130
|
+
const auth = envVars.length > 0 ? `
|
|
13131
|
+
Set ${envVars.join(" and ")} in .env.local so your sources can authenticate.
|
|
13132
|
+
` : "";
|
|
13133
|
+
return `Next steps:
|
|
13134
|
+
|
|
13135
|
+
${lines.join(`
|
|
13136
|
+
`)}
|
|
13137
|
+
${auth}`;
|
|
13138
|
+
};
|
|
13139
|
+
|
|
13140
|
+
// src/cli/commands/eject.ts
|
|
13141
|
+
var reportDroppedArtifacts = (notices) => {
|
|
13142
|
+
if (notices.length === 0) {
|
|
13143
|
+
return;
|
|
13144
|
+
}
|
|
13145
|
+
logger.warn([
|
|
13146
|
+
"The ejected build script runs plain `astro build`, which stops producing these `blume build` artifacts:",
|
|
13147
|
+
...notices.map((notice) => ` - ${notice}`)
|
|
13148
|
+
].join(`
|
|
13149
|
+
`));
|
|
13150
|
+
};
|
|
13151
|
+
var ejectCommand = defineCommand6({
|
|
13152
|
+
args: {
|
|
13153
|
+
yes: { description: "Skip the confirmation prompt.", type: "boolean" }
|
|
13154
|
+
},
|
|
13155
|
+
meta: {
|
|
13156
|
+
description: "Promote the generated runtime into an owned Astro project.",
|
|
13157
|
+
name: "eject"
|
|
13158
|
+
},
|
|
13159
|
+
async run({ args }) {
|
|
13160
|
+
const root = process.cwd();
|
|
13161
|
+
refuseIfDevRunning(root, "ejecting");
|
|
13162
|
+
let notices = [];
|
|
13163
|
+
try {
|
|
13164
|
+
const { config } = await loadConfig(root);
|
|
13165
|
+
notices = droppedArtifactNotices(config);
|
|
13166
|
+
} catch {}
|
|
13167
|
+
if (!args.yes) {
|
|
13168
|
+
logger.warn("Eject is one-way: it writes astro.config.mjs, src/, and (if absent) tsconfig.json, rewrites your package.json scripts, and removes .blume. An existing tsconfig.json is left untouched.");
|
|
13169
|
+
reportDroppedArtifacts(notices);
|
|
13170
|
+
logger.info("Re-run with --yes to proceed.");
|
|
13171
|
+
return;
|
|
13172
|
+
}
|
|
13173
|
+
const { files, warnings } = await eject(root);
|
|
13174
|
+
await updatePackageScripts(root);
|
|
13175
|
+
for (const warning of warnings) {
|
|
13176
|
+
logger.warn(warning);
|
|
13177
|
+
}
|
|
13178
|
+
logger.success(`Ejected ${files.length} file(s):`);
|
|
13179
|
+
for (const file of files) {
|
|
13180
|
+
process.stdout.write(` ${relative14(root, file)}
|
|
13181
|
+
`);
|
|
13182
|
+
}
|
|
13183
|
+
reportDroppedArtifacts(notices);
|
|
13184
|
+
const pm = detectPackageManager(process.env.npm_config_user_agent);
|
|
13185
|
+
const { build: build2, dev: dev2 } = commandsFor(pm);
|
|
13186
|
+
logger.box(`Your project is now a standalone Astro app.
|
|
13187
|
+
|
|
13188
|
+
${dev2}
|
|
13189
|
+
${build2}
|
|
13190
|
+
|
|
13191
|
+
The blume package remains importable.`);
|
|
13192
|
+
}
|
|
13193
|
+
});
|
|
13194
|
+
|
|
13195
|
+
// src/cli/commands/init.ts
|
|
13196
|
+
import * as clack from "@clack/prompts";
|
|
13197
|
+
import { defineCommand as defineCommand7 } from "citty";
|
|
13198
|
+
import { resolve as resolve9 } from "pathe";
|
|
13199
|
+
|
|
13200
|
+
// src/cli/init/questions.ts
|
|
13201
|
+
import { basename as basename5, resolve as resolve8 } from "pathe";
|
|
13202
|
+
var cancelled = (value) => typeof value === "symbol";
|
|
13203
|
+
var collectAnswers = async (prompter, flags, defaults) => {
|
|
13204
|
+
const directory = flags.directory ?? await prompter.text({
|
|
13205
|
+
defaultValue: ".",
|
|
13206
|
+
message: "Where should we create your project?",
|
|
13207
|
+
placeholder: "./my-docs"
|
|
13208
|
+
});
|
|
13209
|
+
if (cancelled(directory)) {
|
|
13210
|
+
return null;
|
|
13211
|
+
}
|
|
13212
|
+
const root = resolve8(defaults.cwd, directory);
|
|
13213
|
+
const title = await prompter.text({
|
|
13214
|
+
initialValue: titleize(basename5(root)),
|
|
13215
|
+
message: "What's your docs site called?",
|
|
13216
|
+
validate: (value) => value?.trim() ? undefined : "Give your docs site a name."
|
|
13217
|
+
});
|
|
13218
|
+
if (cancelled(title)) {
|
|
13219
|
+
return null;
|
|
13220
|
+
}
|
|
13221
|
+
const template = flags.template ?? await prompter.select({
|
|
13222
|
+
message: "Which template?",
|
|
13223
|
+
options: [
|
|
13224
|
+
{ hint: "Markdown docs site", label: "docs", value: "docs" },
|
|
13225
|
+
{ hint: "OpenAPI reference at /api", label: "api", value: "api" },
|
|
13226
|
+
{ hint: "SDK docs with an install page", label: "sdk", value: "sdk" },
|
|
13227
|
+
{
|
|
13228
|
+
hint: "Docs plus a changelog tab",
|
|
13229
|
+
label: "changelog",
|
|
13230
|
+
value: "changelog"
|
|
13231
|
+
}
|
|
13232
|
+
]
|
|
13233
|
+
});
|
|
13234
|
+
if (cancelled(template)) {
|
|
13235
|
+
return null;
|
|
13236
|
+
}
|
|
13237
|
+
const picked = await prompter.multiselect({
|
|
13238
|
+
initialValues: ["filesystem"],
|
|
13239
|
+
message: "Where does your content live?",
|
|
13240
|
+
options: [
|
|
13241
|
+
{ hint: "Local .mdx files", label: "filesystem", value: "filesystem" },
|
|
13242
|
+
{
|
|
13243
|
+
hint: "Changelog from GitHub Releases",
|
|
13244
|
+
label: "github-releases",
|
|
13245
|
+
value: "github-releases"
|
|
13246
|
+
},
|
|
13247
|
+
{ hint: "A Notion database", label: "notion", value: "notion" },
|
|
13248
|
+
{ hint: "A Sanity dataset", label: "sanity", value: "sanity" },
|
|
13249
|
+
{
|
|
13250
|
+
hint: "MDX fetched from a GitHub repo",
|
|
13251
|
+
label: "mdx-remote",
|
|
13252
|
+
value: "mdx-remote"
|
|
13253
|
+
}
|
|
13254
|
+
],
|
|
13255
|
+
required: false
|
|
13256
|
+
});
|
|
13257
|
+
if (cancelled(picked)) {
|
|
13258
|
+
return null;
|
|
13259
|
+
}
|
|
13260
|
+
const sources = picked.length === 0 ? ["filesystem"] : picked;
|
|
13261
|
+
let contentDir = flags.contentDir ?? "docs";
|
|
13262
|
+
if (flags.contentDir === undefined && sources.includes("filesystem")) {
|
|
13263
|
+
const answer = await prompter.text({
|
|
13264
|
+
defaultValue: "docs",
|
|
13265
|
+
message: "Content directory?",
|
|
13266
|
+
placeholder: "docs",
|
|
13267
|
+
validate: (value) => validateContentDir(root, value || "docs")
|
|
13268
|
+
});
|
|
13269
|
+
if (cancelled(answer)) {
|
|
13270
|
+
return null;
|
|
13271
|
+
}
|
|
13272
|
+
contentDir = answer;
|
|
13273
|
+
}
|
|
13274
|
+
return {
|
|
13275
|
+
contentDir,
|
|
13276
|
+
directory,
|
|
13277
|
+
packageManager: flags.packageManager ?? detectPackageManager(defaults.userAgent),
|
|
13278
|
+
sources,
|
|
13279
|
+
template,
|
|
13280
|
+
title
|
|
13281
|
+
};
|
|
13282
|
+
};
|
|
13283
|
+
|
|
13284
|
+
// src/cli/commands/init.ts
|
|
13285
|
+
var ejectScaffold = async (root, answers) => {
|
|
13286
|
+
const commands = commandsFor(answers.packageManager);
|
|
13287
|
+
const cd = answers.directory === "." ? [] : [`cd ${answers.directory}`];
|
|
13288
|
+
try {
|
|
13289
|
+
await eject(root);
|
|
13290
|
+
await updatePackageScripts(root);
|
|
13291
|
+
logger.success("Ejected to a standalone Astro project.");
|
|
13292
|
+
const steps2 = [...cd, commands.install, commands.dev];
|
|
13293
|
+
logger.box(`Next steps:
|
|
13294
|
+
|
|
13295
|
+
${steps2.join(`
|
|
13296
|
+
`)}
|
|
13297
|
+
`);
|
|
13298
|
+
} catch (error) {
|
|
13299
|
+
logger.warn(`Scaffolded, but eject needs the project's dependencies installed to load blume.config.ts: ${error.message}`);
|
|
13300
|
+
const steps2 = [
|
|
13301
|
+
...cd,
|
|
13302
|
+
commands.install,
|
|
13303
|
+
`${commands.exec} blume eject --yes`
|
|
13304
|
+
];
|
|
13305
|
+
logger.box(`Next steps:
|
|
13306
|
+
|
|
13307
|
+
${steps2.join(`
|
|
13308
|
+
`)}
|
|
13309
|
+
`);
|
|
13310
|
+
}
|
|
13311
|
+
};
|
|
11869
13312
|
var initCommand = defineCommand7({
|
|
11870
13313
|
args: {
|
|
11871
13314
|
"content-dir": {
|
|
11872
|
-
default: "docs",
|
|
11873
13315
|
description: "Content directory.",
|
|
11874
13316
|
type: "string"
|
|
11875
13317
|
},
|
|
13318
|
+
dir: {
|
|
13319
|
+
description: "Directory to scaffold into (default: current directory).",
|
|
13320
|
+
required: false,
|
|
13321
|
+
type: "positional"
|
|
13322
|
+
},
|
|
11876
13323
|
eject: {
|
|
11877
13324
|
description: "Eject to a standalone Astro project after scaffolding.",
|
|
11878
13325
|
type: "boolean"
|
|
@@ -11885,66 +13332,74 @@ var initCommand = defineCommand7({
|
|
|
11885
13332
|
description: "Starter template: docs | api | sdk | changelog.",
|
|
11886
13333
|
type: "string"
|
|
11887
13334
|
},
|
|
11888
|
-
yes: {
|
|
13335
|
+
yes: {
|
|
13336
|
+
description: "Skip prompts and scaffold with defaults.",
|
|
13337
|
+
type: "boolean"
|
|
13338
|
+
}
|
|
11889
13339
|
},
|
|
11890
13340
|
meta: {
|
|
11891
13341
|
description: "Scaffold a minimal Blume project.",
|
|
11892
13342
|
name: "init"
|
|
11893
13343
|
},
|
|
11894
13344
|
async run({ args }) {
|
|
11895
|
-
const
|
|
11896
|
-
const
|
|
11897
|
-
if (
|
|
11898
|
-
logger.error(`Invalid --content-dir "${contentDir}" (must be a path inside the project).`);
|
|
11899
|
-
process.exit(1);
|
|
11900
|
-
}
|
|
11901
|
-
const template = args.template ?? "docs";
|
|
11902
|
-
if (!TEMPLATES.includes(template)) {
|
|
13345
|
+
const cwd = process.cwd();
|
|
13346
|
+
const template = args.template;
|
|
13347
|
+
if (template !== undefined && !TEMPLATES.includes(template)) {
|
|
11903
13348
|
logger.error(`Unknown template "${args.template}" (use ${TEMPLATES.join(" | ")}).`);
|
|
11904
13349
|
process.exit(1);
|
|
11905
13350
|
}
|
|
11906
|
-
const pm = args["package-manager"]
|
|
11907
|
-
if (!PACKAGE_MANAGERS.includes(pm)) {
|
|
13351
|
+
const pm = args["package-manager"];
|
|
13352
|
+
if (pm !== undefined && !PACKAGE_MANAGERS.includes(pm)) {
|
|
11908
13353
|
logger.error(`Unknown package manager "${args["package-manager"]}" (use ${PACKAGE_MANAGERS.join(" | ")}).`);
|
|
11909
13354
|
process.exit(1);
|
|
11910
13355
|
}
|
|
11911
|
-
const
|
|
11912
|
-
|
|
11913
|
-
|
|
11914
|
-
|
|
13356
|
+
const interactive = !args.yes && process.stdin.isTTY === true && clack.isTTY(process.stdout) && !clack.isCI();
|
|
13357
|
+
let answers;
|
|
13358
|
+
if (interactive) {
|
|
13359
|
+
clack.intro("blume init");
|
|
13360
|
+
const collected = await collectAnswers(clack, {
|
|
13361
|
+
contentDir: args["content-dir"],
|
|
13362
|
+
directory: args.dir,
|
|
13363
|
+
packageManager: pm,
|
|
13364
|
+
template
|
|
13365
|
+
}, { cwd, userAgent: process.env.npm_config_user_agent });
|
|
13366
|
+
if (collected === null) {
|
|
13367
|
+
clack.cancel("Cancelled — nothing was written.");
|
|
13368
|
+
process.exit(0);
|
|
13369
|
+
}
|
|
13370
|
+
answers = collected;
|
|
13371
|
+
} else {
|
|
13372
|
+
answers = {
|
|
13373
|
+
contentDir: args["content-dir"] ?? "docs",
|
|
13374
|
+
directory: args.dir ?? ".",
|
|
13375
|
+
packageManager: pm ?? detectPackageManager(process.env.npm_config_user_agent),
|
|
13376
|
+
sources: ["filesystem"],
|
|
13377
|
+
template: template ?? "docs",
|
|
13378
|
+
title: "My Docs"
|
|
13379
|
+
};
|
|
13380
|
+
}
|
|
13381
|
+
const root = resolve9(cwd, answers.directory);
|
|
13382
|
+
if (validateContentDir(root, answers.contentDir) !== undefined) {
|
|
13383
|
+
logger.error(`Invalid --content-dir "${answers.contentDir}" (must be a path inside the project).`);
|
|
13384
|
+
process.exit(1);
|
|
13385
|
+
}
|
|
13386
|
+
const sink = interactive ? clack.log : logger;
|
|
13387
|
+
const { createdPackage } = await applyPlan(buildPlan(root, answers), sink);
|
|
11915
13388
|
const ignored = await ensureGitignore(root, [".blume/", "dist/"]);
|
|
11916
13389
|
if (ignored.length > 0) {
|
|
11917
|
-
|
|
13390
|
+
sink.success(`Added ${ignored.join(", ")} to .gitignore`);
|
|
11918
13391
|
}
|
|
11919
|
-
const commands = commandsFor(pm);
|
|
11920
13392
|
if (args.eject) {
|
|
11921
|
-
|
|
11922
|
-
await eject(root);
|
|
11923
|
-
logger.success("Ejected to a standalone Astro project.");
|
|
11924
|
-
logger.box(`Next steps:
|
|
11925
|
-
|
|
11926
|
-
${commands.install}
|
|
11927
|
-
npx astro dev
|
|
11928
|
-
`);
|
|
11929
|
-
} catch (error) {
|
|
11930
|
-
logger.warn(`Scaffolded, but eject failed: ${error.message}`);
|
|
11931
|
-
logger.box(`Next steps:
|
|
11932
|
-
|
|
11933
|
-
${commands.install}
|
|
11934
|
-
blume eject --yes
|
|
11935
|
-
`);
|
|
11936
|
-
}
|
|
13393
|
+
await ejectScaffold(root, answers);
|
|
11937
13394
|
return;
|
|
11938
13395
|
}
|
|
11939
|
-
const
|
|
11940
|
-
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
|
|
11946
|
-
`;
|
|
11947
|
-
logger.box(nextSteps);
|
|
13396
|
+
const steps2 = nextSteps(answers, createdPackage);
|
|
13397
|
+
if (interactive) {
|
|
13398
|
+
clack.note(steps2.trimEnd());
|
|
13399
|
+
clack.outro("You're all set.");
|
|
13400
|
+
} else {
|
|
13401
|
+
logger.box(steps2);
|
|
13402
|
+
}
|
|
11948
13403
|
}
|
|
11949
13404
|
});
|
|
11950
13405
|
|
|
@@ -11974,7 +13429,7 @@ var previewCommand = defineCommand8({
|
|
|
11974
13429
|
logLevel: "info",
|
|
11975
13430
|
root: context.outDir,
|
|
11976
13431
|
server: {
|
|
11977
|
-
host: args.host
|
|
13432
|
+
host: normalizeHost(args.host),
|
|
11978
13433
|
port: parsePort(args.port)
|
|
11979
13434
|
}
|
|
11980
13435
|
});
|
|
@@ -12030,7 +13485,7 @@ import { join as join33 } from "pathe";
|
|
|
12030
13485
|
|
|
12031
13486
|
// src/core/links.ts
|
|
12032
13487
|
import { existsSync as existsSync20 } from "node:fs";
|
|
12033
|
-
import { basename as
|
|
13488
|
+
import { basename as basename6, join as join32 } from "pathe";
|
|
12034
13489
|
var HTTP = /^https?:\/\//iu;
|
|
12035
13490
|
var PROTOCOL_RELATIVE = /^\/\//u;
|
|
12036
13491
|
var SCHEME = /^[a-z][a-z0-9+.-]*:/iu;
|
|
@@ -12050,10 +13505,8 @@ var STATUS_GONE = 410;
|
|
|
12050
13505
|
var STATUS_METHOD_NOT_ALLOWED = 405;
|
|
12051
13506
|
var STATUS_NOT_IMPLEMENTED = 501;
|
|
12052
13507
|
var assetIsPresent = (resolved, ctx) => ctx.publicDir !== null && existsSync20(join32(ctx.publicDir, resolved));
|
|
12053
|
-
var
|
|
12054
|
-
|
|
12055
|
-
return /^index\.(?:md|mdx)$/iu.test(basename5(ref));
|
|
12056
|
-
};
|
|
13508
|
+
var NUMERIC_PREFIX3 = /^\d+[-_.]/u;
|
|
13509
|
+
var isIndexPage = (page2) => /^index\.(?:md|mdx)$/iu.test(basename6(page2.navPath).replace(NUMERIC_PREFIX3, ""));
|
|
12057
13510
|
var applyRelativePart = (segments, part) => {
|
|
12058
13511
|
if (part === "" || part === ".") {
|
|
12059
13512
|
return;
|
|
@@ -12107,6 +13560,9 @@ var checkPathLink = (resolved, fragment, target, site, ctx) => {
|
|
|
12107
13560
|
if (ctx.routes.has(route)) {
|
|
12108
13561
|
return fragment ? checkAnchor(route, fragment, site, ctx) : null;
|
|
12109
13562
|
}
|
|
13563
|
+
if (ctx.extraRoutes.has(route)) {
|
|
13564
|
+
return null;
|
|
13565
|
+
}
|
|
12110
13566
|
if (ctx.redirects.has(route)) {
|
|
12111
13567
|
return null;
|
|
12112
13568
|
}
|
|
@@ -12244,6 +13700,7 @@ var validateLinks = async (graph, options) => {
|
|
|
12244
13700
|
const ctx = {
|
|
12245
13701
|
anchors: buildAnchorIndex(graph.pages),
|
|
12246
13702
|
basePath,
|
|
13703
|
+
extraRoutes: new Set((options.extraRoutes ?? []).map(toRoute)),
|
|
12247
13704
|
publicDir: options.publicDir,
|
|
12248
13705
|
redirects: new Set((options.redirects ?? []).map((redirect) => toRoute(withBasePath(basePath, redirect.from)))),
|
|
12249
13706
|
routes: new Set(graph.routes.keys())
|
|
@@ -12300,10 +13757,24 @@ var validateCommand = defineCommand10({
|
|
|
12300
13757
|
try {
|
|
12301
13758
|
const project = await scanProject(root, { mode: "build" });
|
|
12302
13759
|
diagnostics.push(...project.diagnostics);
|
|
13760
|
+
const userPages = project.context.pagesRoot ? await discoverPages(project.context.pagesRoot) : [];
|
|
13761
|
+
const extraRoutes = customStaticRoutes(userPages);
|
|
13762
|
+
if (hasGeneratedChangelog(project, userPages)) {
|
|
13763
|
+
extraRoutes.push("/changelog");
|
|
13764
|
+
}
|
|
13765
|
+
if (project.config.i18n) {
|
|
13766
|
+
const manifest = buildManifest({
|
|
13767
|
+
config: project.config,
|
|
13768
|
+
context: project.context,
|
|
13769
|
+
graph: project.graph
|
|
13770
|
+
});
|
|
13771
|
+
extraRoutes.push(...manifest.routes.flatMap((route) => route.fallback ? [route.path] : []));
|
|
13772
|
+
}
|
|
12303
13773
|
const publicDir = join33(root, "public");
|
|
12304
13774
|
diagnostics.push(...await validateLinks(project.graph, {
|
|
12305
13775
|
basePath: project.config.basePath,
|
|
12306
13776
|
checkExternal: Boolean(args.external),
|
|
13777
|
+
extraRoutes,
|
|
12307
13778
|
publicDir: existsSync21(publicDir) ? publicDir : null,
|
|
12308
13779
|
redirects: project.config.redirects
|
|
12309
13780
|
}));
|
|
@@ -12315,9 +13786,10 @@ var validateCommand = defineCommand10({
|
|
|
12315
13786
|
process.exit(1);
|
|
12316
13787
|
}
|
|
12317
13788
|
}
|
|
13789
|
+
const strictFailure = Boolean(args.strict) && diagnostics.some((diagnostic) => diagnostic.severity !== "info");
|
|
12318
13790
|
if (args.json) {
|
|
12319
13791
|
const hadErrors2 = reportDiagnosticsJson(diagnostics, root);
|
|
12320
|
-
if (hadErrors2 ||
|
|
13792
|
+
if (hadErrors2 || strictFailure) {
|
|
12321
13793
|
await flushStdout();
|
|
12322
13794
|
process.exit(1);
|
|
12323
13795
|
}
|
|
@@ -12327,7 +13799,7 @@ var validateCommand = defineCommand10({
|
|
|
12327
13799
|
if (diagnostics.length === 0) {
|
|
12328
13800
|
logger.success("No broken links found.");
|
|
12329
13801
|
}
|
|
12330
|
-
if (hadErrors ||
|
|
13802
|
+
if (hadErrors || strictFailure) {
|
|
12331
13803
|
process.exit(1);
|
|
12332
13804
|
}
|
|
12333
13805
|
}
|
|
@@ -12364,5 +13836,5 @@ process.on("unhandledRejection", (error) => {
|
|
|
12364
13836
|
});
|
|
12365
13837
|
runMain(main);
|
|
12366
13838
|
|
|
12367
|
-
//# debugId=
|
|
13839
|
+
//# debugId=066FB7264FFC708364756E2164756E21
|
|
12368
13840
|
//# sourceMappingURL=index.js.map
|