blume 1.4.3 → 1.5.1
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 +32 -0
- package/README.md +16 -12
- package/dist/cli/index.js +1784 -633
- package/dist/cli/index.js.map +111 -106
- package/dist/types/ai/component-markdown.d.ts +14 -4
- package/dist/types/core/config-input.d.ts +80 -28
- package/dist/types/core/config.d.ts +2 -1
- package/dist/types/core/data.d.ts +19 -3
- package/dist/types/core/diagnostics.d.ts +5 -1
- package/dist/types/core/i18n-ui.d.ts +12 -0
- package/dist/types/core/schema.d.ts +112 -15
- package/dist/types/core/sources/types.d.ts +3 -1
- package/dist/types/core/standard-schema.d.ts +7 -3
- package/dist/types/core/types.d.ts +43 -2
- package/dist/types/core/ui-packs/index.d.ts +9 -1
- package/dist/types/openapi/references.d.ts +6 -5
- package/dist/types/seo/x-handle.d.ts +3 -2
- package/dist/types/theme/fonts.d.ts +11 -2
- package/docs/advanced/api-reference.mdx +8 -6
- package/docs/advanced/custom-pages.mdx +5 -1
- package/docs/configuration/index.mdx +1 -1
- package/docs/configuration/search.mdx +2 -0
- package/docs/configuration/seo.mdx +1 -1
- package/docs/configuration/theming.mdx +4 -2
- package/docs/content/i18n.mdx +1 -1
- package/docs/content/meta.mdx +2 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +35 -1
- package/docs/content/versioning.mdx +106 -0
- package/docs/reference/cli.mdx +2 -1
- package/docs/reference/frontmatter.mdx +3 -0
- package/package.json +3 -1
- package/skills/blume-migrate/SKILL.md +2 -2
- package/skills/blume-migrate/references/docusaurus.md +1 -1
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- package/skills/blume-migrate/references/mintlify.md +1 -1
- package/src/ai/agent-readability.ts +37 -10
- package/src/ai/ask-context.ts +5 -1
- package/src/ai/ask.ts +10 -1
- package/src/ai/component-markdown.ts +80 -43
- package/src/ai/llms.ts +40 -16
- package/src/ai/mcp/data.ts +48 -12
- package/src/ai/mcp/discovery.ts +28 -11
- package/src/ai/mcp/server.ts +183 -38
- package/src/ai/mcp/tools.ts +3 -3
- package/src/ai/skills.ts +32 -9
- package/src/ai/visibility.ts +2 -2
- package/src/astro/component-slots.ts +2 -0
- package/src/astro/examples.ts +6 -2
- package/src/astro/generate.ts +64 -34
- package/src/astro/integration.ts +13 -2
- package/src/astro/islands.ts +16 -9
- package/src/astro/templates.ts +181 -40
- package/src/audit/agent.ts +2 -2
- package/src/audit/checks/content.ts +26 -11
- package/src/audit/checks/dns-aid.ts +3 -0
- package/src/audit/checks/indexability.ts +24 -6
- package/src/audit/checks/llms.ts +9 -4
- package/src/audit/checks/network.ts +2 -0
- package/src/audit/checks/social.ts +18 -10
- package/src/audit/crawl.ts +37 -9
- package/src/audit/report.ts +20 -19
- package/src/audit/run.ts +5 -2
- package/src/audit/snapshot.ts +2 -4
- package/src/audit/types.ts +25 -3
- package/src/blume-modules.d.ts +5 -1
- package/src/cli/commands/audit.ts +9 -4
- package/src/cli/commands/build.ts +15 -9
- package/src/cli/commands/dev.ts +2 -0
- package/src/cli/commands/doctor.ts +2 -0
- package/src/cli/commands/eval.ts +7 -3
- package/src/cli/commands/init.ts +9 -9
- package/src/cli/commands/mcp-stdio.ts +3 -0
- package/src/cli/commands/translate.ts +14 -3
- package/src/cli/commands/version.ts +85 -0
- package/src/cli/dev-lock.ts +31 -10
- package/src/cli/eject-scripts.ts +17 -2
- package/src/cli/index.ts +2 -0
- package/src/cli/init/questions.ts +1 -1
- package/src/cli/init/scaffold.ts +22 -15
- package/src/cli/internal-error.ts +1 -0
- package/src/components/content/auto-type-table.ts +3 -0
- package/src/components/content/diff.ts +9 -5
- package/src/components/content/github-info.ts +2 -0
- package/src/components/islands/ask-ai.tsx +33 -25
- package/src/components/islands/hooks.ts +5 -1
- package/src/components/islands/webmcp.ts +49 -12
- package/src/components/layout/Fonts.astro +23 -3
- package/src/components/layout/Header.astro +25 -1
- package/src/components/layout/NavSelector.astro +11 -2
- package/src/components/layout/NavTree.astro +4 -2
- package/src/components/layout/PageLayout.astro +72 -3
- package/src/components/layout/ReferenceLayout.astro +2 -1
- package/src/components/layout/RootLayout.astro +20 -1
- package/src/components/layout/Search.astro +77 -13
- package/src/components/layout/VersionBanner.astro +39 -0
- package/src/components/layout/analytics-client.ts +8 -5
- package/src/components/layout/hydration-hint.ts +1 -1
- package/src/components/layout/nav-utils.ts +1 -4
- package/src/components/layout/overrides.ts +25 -12
- package/src/components/layout/search/algolia.ts +18 -5
- package/src/components/layout/search/endpoint.ts +3 -0
- package/src/components/layout/search/flexsearch.ts +23 -7
- package/src/components/layout/search/orama-cloud.ts +1 -1
- package/src/components/layout/search/orama.ts +4 -1
- package/src/components/layout/search/pagefind.ts +2 -0
- package/src/components/layout/search/types.ts +13 -1
- package/src/components/layout/search/typesense.ts +19 -3
- package/src/components/openapi/ApiOverview.astro +32 -6
- package/src/components/openapi/AsyncApiOperation.astro +237 -0
- package/src/components/openapi/Bindings.astro +89 -0
- package/src/components/openapi/MethodBadge.astro +3 -0
- package/src/components/openapi/Operation.astro +7 -2
- package/src/components/openapi/PanelTabs.astro +131 -0
- package/src/components/openapi/ParametersTable.astro +2 -0
- package/src/components/openapi/RequestPanel.astro +12 -119
- package/src/components/openapi/async-snippets.ts +174 -0
- package/src/components/openapi/async.ts +348 -0
- package/src/components/openapi/helpers.ts +52 -20
- package/src/components/openapi/security.ts +102 -29
- package/src/components/openapi/snippets.ts +11 -11
- package/src/core/component-overrides.ts +28 -23
- package/src/core/config-input.ts +89 -28
- package/src/core/config.ts +20 -7
- package/src/core/content.ts +3 -1
- package/src/core/data.ts +19 -3
- package/src/core/define-components.ts +5 -0
- package/src/core/diagnostics.ts +46 -38
- package/src/core/frontmatter.ts +33 -7
- package/src/core/graph.ts +137 -53
- package/src/core/i18n-ui.ts +15 -0
- package/src/core/i18n.ts +16 -8
- package/src/core/last-modified.ts +49 -0
- package/src/core/load-module.ts +1 -0
- package/src/core/manifest.ts +92 -3
- package/src/core/meta.ts +44 -14
- package/src/core/nav-diagnostics.ts +3 -3
- package/src/core/navigation.ts +247 -67
- package/src/core/project-graph.ts +26 -3
- package/src/core/schema.ts +214 -68
- package/src/core/sources/assets.ts +2 -0
- package/src/core/sources/cache.ts +6 -0
- package/src/core/sources/github-releases.ts +39 -31
- package/src/core/sources/mdx-remote.ts +4 -0
- package/src/core/sources/normalize.ts +67 -20
- package/src/core/sources/notion.ts +49 -17
- package/src/core/sources/portable-text.ts +32 -11
- package/src/core/sources/sanity.ts +68 -14
- package/src/core/sources/types.ts +4 -0
- package/src/core/sources/watch.ts +1 -1
- package/src/core/standard-schema.ts +9 -3
- package/src/core/text-width.ts +26 -0
- package/src/core/tsconfig-aliases.ts +9 -5
- package/src/core/types.ts +45 -2
- package/src/core/ui-packs/index.ts +9 -1
- package/src/core/version-cut.ts +301 -0
- package/src/core/version.ts +2 -0
- package/src/core/versions.ts +170 -0
- package/src/deploy/adapter-output.ts +5 -2
- package/src/deploy/cloudflare-negotiation.ts +25 -10
- package/src/deploy/sitemap.ts +33 -1
- package/src/deploy/vercel-negotiation.ts +45 -18
- package/src/eval/report.ts +4 -4
- package/src/eval/run.ts +2 -2
- package/src/eval/schema.ts +1 -1
- package/src/markdown/base-links.ts +6 -6
- package/src/markdown/directives.ts +7 -1
- package/src/markdown/heading-anchors.ts +17 -6
- package/src/markdown/index.ts +73 -24
- package/src/markdown/inline-code.ts +14 -2
- package/src/markdown/language-icon.ts +6 -2
- package/src/markdown/mdast.ts +18 -4
- package/src/markdown/package-commands.ts +6 -8
- package/src/markdown/table-wrap.ts +4 -1
- package/src/markdown/twoslash.ts +2 -0
- package/src/og/card.ts +33 -12
- package/src/og/derive.ts +43 -27
- package/src/openapi/asyncapi.ts +366 -0
- package/src/openapi/model.ts +126 -57
- package/src/openapi/parse.ts +97 -5
- package/src/openapi/references.ts +12 -10
- package/src/openapi/render-mdx.ts +73 -34
- package/src/openapi/scalar.ts +6 -8
- package/src/openapi/source.ts +98 -28
- package/src/registry/eject.ts +7 -2
- package/src/search/documents.ts +25 -5
- package/src/search/facets.ts +7 -5
- package/src/search/orama-index.ts +66 -20
- package/src/search/popular.ts +10 -5
- package/src/search/providers.ts +2 -2
- package/src/search/sync/index.ts +2 -0
- package/src/search/sync/typesense.ts +4 -2
- package/src/seo/jsonld.ts +24 -6
- package/src/seo/x-handle.ts +8 -3
- package/src/theme/chrome-icons.ts +7 -2
- package/src/theme/entry.ts +24 -2
- package/src/theme/fonts.ts +83 -7
- package/src/theme/icons.ts +4 -2
- package/src/theme/palette.ts +22 -14
- package/src/translate/meta.ts +15 -6
- package/src/translate/report.ts +9 -5
- package/src/translate/run.ts +10 -4
- package/src/translate/validate.ts +52 -17
- package/src/translate/work-list.ts +0 -0
package/src/core/manifest.ts
CHANGED
|
@@ -8,9 +8,39 @@ import type {
|
|
|
8
8
|
ProjectContext,
|
|
9
9
|
RouteAlternate,
|
|
10
10
|
RouteManifestEntry,
|
|
11
|
+
VersionAlternate,
|
|
11
12
|
} from "./types.ts";
|
|
12
13
|
import { getBlumeVersion } from "./version.ts";
|
|
13
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Key for the same logical page across versions within one locale: the
|
|
17
|
+
* version- and locale-agnostic route plus the locale code. NUL never appears
|
|
18
|
+
* in either part, so the join is unambiguous.
|
|
19
|
+
*/
|
|
20
|
+
const versionAlternateKey = (versionKey: string, locale: string): string =>
|
|
21
|
+
`${versionKey}\u0000${locale}`;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get-or-create the shared alternate list for a (versionKey, locale) pair.
|
|
25
|
+
* Lists are attached to route entries by reference and mutated as fallback
|
|
26
|
+
* routes materialize, then sorted once at the end — every holder sees the
|
|
27
|
+
* final list.
|
|
28
|
+
*/
|
|
29
|
+
const versionAlternatesFor = (
|
|
30
|
+
byKey: Map<string, VersionAlternate[]>,
|
|
31
|
+
versionKey: string,
|
|
32
|
+
locale: string
|
|
33
|
+
): VersionAlternate[] => {
|
|
34
|
+
const key = versionAlternateKey(versionKey, locale);
|
|
35
|
+
const existing = byKey.get(key);
|
|
36
|
+
if (existing) {
|
|
37
|
+
return existing;
|
|
38
|
+
}
|
|
39
|
+
const list: VersionAlternate[] = [];
|
|
40
|
+
byKey.set(key, list);
|
|
41
|
+
return list;
|
|
42
|
+
};
|
|
43
|
+
|
|
14
44
|
/** The current manifest schema version. */
|
|
15
45
|
export const MANIFEST_VERSION = 1;
|
|
16
46
|
|
|
@@ -37,7 +67,8 @@ const buildFallbackRoutes = (
|
|
|
37
67
|
graph: ContentGraph,
|
|
38
68
|
i18n: NonNullable<ResolvedConfig["i18n"]>,
|
|
39
69
|
alternatesByKey: Map<string, RouteAlternate[]>,
|
|
40
|
-
basePath: string
|
|
70
|
+
basePath: string,
|
|
71
|
+
versionAlternatesByKey: Map<string, VersionAlternate[]> | undefined
|
|
41
72
|
): RouteManifestEntry[] => {
|
|
42
73
|
const fallback = resolveFallbackLocale(i18n);
|
|
43
74
|
if (!fallback) {
|
|
@@ -62,6 +93,17 @@ const buildFallbackRoutes = (
|
|
|
62
93
|
if (present.has(key)) {
|
|
63
94
|
continue;
|
|
64
95
|
}
|
|
96
|
+
const path = withBasePath(basePath, localizeRoute(key, code, i18n));
|
|
97
|
+
// A fallback route is a real prerendered page, so it registers as a
|
|
98
|
+
// version alternate too — the switcher on a sibling version's page
|
|
99
|
+
// lands here instead of bouncing to the version root. Its own path is
|
|
100
|
+
// recorded (not the fallback source's), keeping the target in-locale.
|
|
101
|
+
const versionAlternates: VersionAlternate[] = versionAlternatesByKey
|
|
102
|
+
? versionAlternatesFor(versionAlternatesByKey, source.versionKey, code)
|
|
103
|
+
: [];
|
|
104
|
+
if (versionAlternatesByKey) {
|
|
105
|
+
versionAlternates.push({ path, version: source.version });
|
|
106
|
+
}
|
|
65
107
|
routes.push({
|
|
66
108
|
alternates: alternatesByKey.get(key) ?? [],
|
|
67
109
|
collection: source.collection ?? "docs",
|
|
@@ -75,10 +117,12 @@ const buildFallbackRoutes = (
|
|
|
75
117
|
indexable: false,
|
|
76
118
|
lastModified: source.lastModified,
|
|
77
119
|
locale: code,
|
|
78
|
-
path
|
|
120
|
+
path,
|
|
79
121
|
source: source.source,
|
|
80
122
|
sourcePath: source.sourcePath,
|
|
81
123
|
title: source.title,
|
|
124
|
+
version: source.version,
|
|
125
|
+
versionAlternates,
|
|
82
126
|
});
|
|
83
127
|
}
|
|
84
128
|
}
|
|
@@ -106,6 +150,23 @@ export const buildManifest = (options: {
|
|
|
106
150
|
}
|
|
107
151
|
}
|
|
108
152
|
|
|
153
|
+
// The same logical page across versions, within each locale — for the
|
|
154
|
+
// version switcher and the canonical-to-latest lookup. Built only under
|
|
155
|
+
// versioning; lists are shared by reference and finalized (fallback routes
|
|
156
|
+
// appended, then sorted) before the manifest is returned.
|
|
157
|
+
const versionAlternatesByKey = config.versions
|
|
158
|
+
? new Map<string, VersionAlternate[]>()
|
|
159
|
+
: undefined;
|
|
160
|
+
if (versionAlternatesByKey) {
|
|
161
|
+
for (const page of graph.pages) {
|
|
162
|
+
versionAlternatesFor(
|
|
163
|
+
versionAlternatesByKey,
|
|
164
|
+
page.versionKey,
|
|
165
|
+
page.locale
|
|
166
|
+
).push({ path: page.route, version: page.version });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
109
170
|
const routes: RouteManifestEntry[] = graph.pages.map((page) => ({
|
|
110
171
|
alternates: alternatesByKey.get(page.translationKey) ?? [],
|
|
111
172
|
collection: page.collection ?? "docs",
|
|
@@ -122,14 +183,42 @@ export const buildManifest = (options: {
|
|
|
122
183
|
source: page.source,
|
|
123
184
|
sourcePath: page.sourcePath,
|
|
124
185
|
title: page.title,
|
|
186
|
+
version: page.version,
|
|
187
|
+
versionAlternates: versionAlternatesByKey
|
|
188
|
+
? versionAlternatesFor(
|
|
189
|
+
versionAlternatesByKey,
|
|
190
|
+
page.versionKey,
|
|
191
|
+
page.locale
|
|
192
|
+
)
|
|
193
|
+
: [],
|
|
125
194
|
}));
|
|
126
195
|
|
|
127
196
|
if (i18n) {
|
|
128
197
|
routes.push(
|
|
129
|
-
...buildFallbackRoutes(
|
|
198
|
+
...buildFallbackRoutes(
|
|
199
|
+
graph,
|
|
200
|
+
i18n,
|
|
201
|
+
alternatesByKey,
|
|
202
|
+
config.basePath,
|
|
203
|
+
versionAlternatesByKey
|
|
204
|
+
)
|
|
130
205
|
);
|
|
131
206
|
}
|
|
132
207
|
|
|
208
|
+
// Alternate lists read current-first, then archived versions in configured
|
|
209
|
+
// (switcher) order. Sorted once here — every route holding a list by
|
|
210
|
+
// reference sees the final ordering.
|
|
211
|
+
if (versionAlternatesByKey && config.versions) {
|
|
212
|
+
const rank = new Map<string, number>(
|
|
213
|
+
config.versions.archived.map((version, index) => [version.id, index + 1])
|
|
214
|
+
);
|
|
215
|
+
for (const list of versionAlternatesByKey.values()) {
|
|
216
|
+
list.sort(
|
|
217
|
+
(a, b) => (rank.get(a.version) ?? 0) - (rank.get(b.version) ?? 0)
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
133
222
|
routes.sort((a, b) => a.path.localeCompare(b.path));
|
|
134
223
|
|
|
135
224
|
return {
|
package/src/core/meta.ts
CHANGED
|
@@ -17,9 +17,23 @@ const META_FILES = [
|
|
|
17
17
|
"**/meta.$.mjs",
|
|
18
18
|
];
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* A meta module's default export before validation: `folderMetaSchema` parses
|
|
22
|
+
* it only after any factory is resolved, so it carries the loader's raw type.
|
|
23
|
+
*/
|
|
24
|
+
type MetaModuleExport = Awaited<
|
|
25
|
+
ReturnType<ReturnType<typeof createModuleLoader>>
|
|
26
|
+
>;
|
|
27
|
+
|
|
28
|
+
/** A factory-style meta module default-exports a function returning the meta. */
|
|
29
|
+
const isMetaFactory = (
|
|
30
|
+
mod: MetaModuleExport
|
|
31
|
+
): mod is () => MetaModuleExport | Promise<MetaModuleExport> =>
|
|
32
|
+
typeof mod === "function";
|
|
33
|
+
|
|
20
34
|
/** Resolve a meta module's default export, calling it if it is a factory. */
|
|
21
|
-
const resolveMeta = async (mod:
|
|
22
|
-
|
|
35
|
+
const resolveMeta = async (mod: MetaModuleExport) =>
|
|
36
|
+
isMetaFactory(mod) ? await mod() : mod;
|
|
23
37
|
|
|
24
38
|
/** A filesystem content source to scan for folder meta: its on-disk root and
|
|
25
39
|
* optional route prefix. The prefix is folded into every key so meta lines up
|
|
@@ -58,18 +72,28 @@ const metaKeyFor = (prefix: string | undefined, dir: string): string => {
|
|
|
58
72
|
* group path starts with the source prefix, so a locale directory found at a
|
|
59
73
|
* source root is hoisted in front of the prefix (`docs/fr/guides/meta.ts` keys
|
|
60
74
|
* to `fr/docs/guides`, not `docs/fr/guides`).
|
|
75
|
+
*
|
|
76
|
+
* `versionDirs` names the archived-version snapshot directories, which sit
|
|
77
|
+
* outermost on disk — a locale directory inside a snapshot is one level deeper.
|
|
78
|
+
* Both are hoisted, version first (`v1.0/fr/guides/meta.ts` keys to
|
|
79
|
+
* `v1.0/fr/<prefix>/guides`), matching navigation's version-aware meta prefix.
|
|
61
80
|
*/
|
|
62
81
|
export const discoverFolderMeta = async (
|
|
63
82
|
sources: string | FolderMetaSource[],
|
|
64
|
-
options: {
|
|
83
|
+
options: {
|
|
84
|
+
localeDirs?: readonly string[];
|
|
85
|
+
versionDirs?: readonly string[];
|
|
86
|
+
} = {}
|
|
65
87
|
): Promise<{
|
|
66
88
|
meta: Map<string, FolderMeta>;
|
|
67
89
|
shared: Map<string, FolderMeta>;
|
|
68
90
|
diagnostics: Diagnostic[];
|
|
69
91
|
}> => {
|
|
70
|
-
const list: FolderMetaSource[] =
|
|
71
|
-
|
|
92
|
+
const list: FolderMetaSource[] = Array.isArray(sources)
|
|
93
|
+
? sources
|
|
94
|
+
: [{ root: sources }];
|
|
72
95
|
const localeDirs = new Set(options.localeDirs);
|
|
96
|
+
const versionDirs = new Set(options.versionDirs);
|
|
73
97
|
|
|
74
98
|
const load = createModuleLoader();
|
|
75
99
|
const meta = new Map<string, FolderMeta>();
|
|
@@ -103,6 +127,8 @@ export const discoverFolderMeta = async (
|
|
|
103
127
|
value: await resolveMeta(await load(file)),
|
|
104
128
|
};
|
|
105
129
|
} catch (error) {
|
|
130
|
+
// SAFETY: jiti surfaces load/evaluate failures as Error
|
|
131
|
+
// instances, and only `message` is read downstream.
|
|
106
132
|
return { error: error as Error, file, ok: false };
|
|
107
133
|
}
|
|
108
134
|
}
|
|
@@ -115,16 +141,20 @@ export const discoverFolderMeta = async (
|
|
|
115
141
|
for (const { loaded, source } of perSource) {
|
|
116
142
|
for (const entry of loaded) {
|
|
117
143
|
const dir = relative(source.root, dirname(entry.file));
|
|
144
|
+
// A version snapshot dir is outermost, with a locale dir one level
|
|
145
|
+
// deeper; both are hoisted in front of the (prefixed) group path, in
|
|
146
|
+
// that order — the lookup key reads `version/locale/prefix/dir`.
|
|
118
147
|
const [head, ...tail] = dir.split("/");
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
148
|
+
const version = head && versionDirs.has(head) ? head : "";
|
|
149
|
+
const afterVersion = version ? tail : [head ?? "", ...tail];
|
|
150
|
+
const [localeHead, ...localeTail] = afterVersion;
|
|
151
|
+
const locale = localeHead && localeDirs.has(localeHead) ? localeHead : "";
|
|
152
|
+
const rest = (locale ? localeTail : afterVersion)
|
|
153
|
+
.filter(Boolean)
|
|
154
|
+
.join("/");
|
|
155
|
+
const key = [version, locale, metaKeyFor(source.prefix, rest)]
|
|
156
|
+
.filter(Boolean)
|
|
157
|
+
.join("/");
|
|
128
158
|
|
|
129
159
|
if (!entry.ok) {
|
|
130
160
|
diagnostics.push({
|
|
@@ -9,7 +9,7 @@ import type { Diagnostic, NavNode, Navigation, PageRecord } from "./types.ts";
|
|
|
9
9
|
* covers every source (config, folder meta, frontmatter) at once.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const ICON_FORMAT_HINT =
|
|
13
13
|
"Use a built-in icon name, an image path/URL, or inline SVG markup.";
|
|
14
14
|
|
|
15
15
|
/** Flatten a sidebar tree to every node, descending into groups. */
|
|
@@ -80,7 +80,7 @@ const unknownIconDiagnostics = (
|
|
|
80
80
|
|
|
81
81
|
/** Warn about icon names that aren't in Blume's set (skipping image/SVG icons). */
|
|
82
82
|
export const validateNavIcons = (navigation: Navigation): Diagnostic[] =>
|
|
83
|
-
unknownIconDiagnostics(collectIcons(navigation),
|
|
83
|
+
unknownIconDiagnostics(collectIcons(navigation), ICON_FORMAT_HINT);
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
86
|
* Warn about unknown icons on curated `search.popular` links. Same accepted
|
|
@@ -94,7 +94,7 @@ export const validateSearchPopularIcons = (
|
|
|
94
94
|
? [{ icon: link.icon, where: `popular link "${link.label}"` }]
|
|
95
95
|
: []
|
|
96
96
|
);
|
|
97
|
-
return unknownIconDiagnostics(icons,
|
|
97
|
+
return unknownIconDiagnostics(icons, ICON_FORMAT_HINT);
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
/** Whether an internal path resolves to a page or a section that has pages. */
|