@f5-sales-demo/docs-theme 4.4.8 → 4.4.10
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/canonical-route-middleware.ts +3 -2
- package/components/ProviderReference.astro +4 -1
- package/config.ts +14 -4
- package/index.ts +0 -1
- package/package.json +1 -1
- package/src/utils/availability.test.ts +25 -0
- package/src/utils/canonical-provider.ts +19 -2
- package/src/utils/menu-localization.test.ts +15 -0
- package/src/utils/menu-localization.ts +16 -0
- package/src/utils/provider-sections.ts +17 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { defineRouteMiddleware } from '@astrojs/starlight/route-data';
|
|
3
3
|
import type { ProviderPage } from './src/utils/canonical-provider.ts';
|
|
4
|
-
import { collectionNavigation
|
|
4
|
+
import { collectionNavigation } from './src/utils/canonical-provider.ts';
|
|
5
|
+
import { stagedProviderSections } from './src/utils/provider-sections.ts';
|
|
5
6
|
|
|
6
7
|
let providerNavigation: { collections: Record<string, ProviderPage[]> };
|
|
7
8
|
export const onRequest = defineRouteMiddleware(async (context, next) => {
|
|
@@ -12,7 +13,7 @@ export const onRequest = defineRouteMiddleware(async (context, next) => {
|
|
|
12
13
|
providerNavigation ||= JSON.parse(fs.readFileSync(process.env.PROVIDER_NAVIGATION || '', 'utf8'));
|
|
13
14
|
const metadata = entry.data.xcsh_docs;
|
|
14
15
|
const base = import.meta.env.BASE_URL;
|
|
15
|
-
const sections =
|
|
16
|
+
const sections = stagedProviderSections().map((section) => ({
|
|
16
17
|
type: 'link' as const,
|
|
17
18
|
label: section.label,
|
|
18
19
|
href: `${base.replace(/\/$/, '')}/${section.path}/`,
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { CardGrid } from '@astrojs/starlight/components';
|
|
3
|
-
import {
|
|
3
|
+
import { stagedProviderSections } from '../src/utils/provider-sections';
|
|
4
|
+
|
|
5
|
+
const providerSections = stagedProviderSections();
|
|
6
|
+
|
|
4
7
|
import LinkCard from './LinkCard.astro';
|
|
5
8
|
|
|
6
9
|
const { entry } = Astro.locals.starlightRoute;
|
package/config.ts
CHANGED
|
@@ -32,6 +32,8 @@ import {
|
|
|
32
32
|
import { sidebarTranslations } from './src/i18n/translations.ts';
|
|
33
33
|
import remarkMermaid from './src/plugins/remark-mermaid.mjs';
|
|
34
34
|
import { providerMegaMenu } from './src/utils/canonical-provider.ts';
|
|
35
|
+
import { menuLocalizationPolicy } from './src/utils/menu-localization.ts';
|
|
36
|
+
import { stagedProviderSections } from './src/utils/provider-sections.ts';
|
|
35
37
|
import { resolveMegaMenuIcon } from './src/utils/resolve-icon.ts';
|
|
36
38
|
import providerSharedAssets from './src/utils/share-provider-assets.mjs';
|
|
37
39
|
import { buildSubcategorySidebar } from './src/utils/subcategory-sidebar.ts';
|
|
@@ -669,7 +671,7 @@ export function createF5xcDocsConfig(options: F5xcDocsConfigOptions = {}) {
|
|
|
669
671
|
}
|
|
670
672
|
const site = options.site || process.env.DOCS_SITE || 'https://f5-sales-demo.github.io';
|
|
671
673
|
const base = options.base || process.env.DOCS_BASE || '/';
|
|
672
|
-
const title = options.title || process.env.DOCS_TITLE || 'Documentation';
|
|
674
|
+
const title = options.title || process.env.DOCS_TITLE || (canonicalProvider ? 'Terraform Provider' : 'Documentation');
|
|
673
675
|
const description = options.description || process.env.DOCS_DESCRIPTION || '';
|
|
674
676
|
const githubRepository = options.githubRepository || process.env.GITHUB_REPOSITORY || '';
|
|
675
677
|
let llmsOptionalLinks: Array<{ title: string; url: string }> = options.llmsOptionalLinks || [];
|
|
@@ -712,7 +714,11 @@ export function createF5xcDocsConfig(options: F5xcDocsConfigOptions = {}) {
|
|
|
712
714
|
console.warn('[docs-theme] OPENAPI_SPECS_CONFIG contains invalid JSON; skipping OpenAPI plugin.', e);
|
|
713
715
|
}
|
|
714
716
|
}
|
|
715
|
-
const megaMenuItems =
|
|
717
|
+
const megaMenuItems =
|
|
718
|
+
options.megaMenuItems ||
|
|
719
|
+
(canonicalProvider
|
|
720
|
+
? [...defaultMegaMenuItems, ...providerMegaMenu(base, stagedProviderSections(canonicalProvider.manifest))]
|
|
721
|
+
: defaultMegaMenuItems);
|
|
716
722
|
const head = options.head || (canonicalProvider ? [] : defaultHead);
|
|
717
723
|
const logo = options.logo || { src: '@f5-sales-demo/docs-theme/assets/f5-distributed-cloud.svg' };
|
|
718
724
|
const additionalRemarkPlugins = options.additionalRemarkPlugins || [];
|
|
@@ -869,13 +875,17 @@ export function createF5xcDocsConfig(options: F5xcDocsConfigOptions = {}) {
|
|
|
869
875
|
return defineConfig({
|
|
870
876
|
site,
|
|
871
877
|
base,
|
|
878
|
+
vite: { plugins: [menuLocalizationPolicy()], ...(canonicalProvider ? { build: { assetsInlineLimit: 0 } } : {}) },
|
|
872
879
|
...(canonicalProvider
|
|
873
880
|
? {
|
|
874
881
|
experimental: { collectionStorage: { type: 'chunked' as const, chunkSize: 1024 * 1024 } },
|
|
875
|
-
vite: { build: { assetsInlineLimit: 0 } },
|
|
876
882
|
}
|
|
877
883
|
: {}),
|
|
878
|
-
...(
|
|
884
|
+
...(canonicalProvider
|
|
885
|
+
? { redirects: { '/en/': `${normalizedBase}/` } }
|
|
886
|
+
: resolvedLocales
|
|
887
|
+
? { redirects: { '/': `${normalizedBase}/${resolvedDefaultLocale}/` } }
|
|
888
|
+
: {}),
|
|
879
889
|
markdown: {
|
|
880
890
|
processor: unified({
|
|
881
891
|
remarkPlugins: [remarkMermaid, [codeImport, { allowImportingFromOutside: true }], ...additionalRemarkPlugins],
|
package/index.ts
CHANGED
|
@@ -26,7 +26,6 @@ export default function f5xcDocsTheme(): StarlightPlugin {
|
|
|
26
26
|
...config.components,
|
|
27
27
|
...(process.env.DOCS_PROFILE === 'canonical-provider'
|
|
28
28
|
? {
|
|
29
|
-
Header: '@f5-sales-demo/docs-theme/components/ProviderHeader.astro',
|
|
30
29
|
Sidebar: '@f5-sales-demo/docs-theme/components/ProviderSidebar.astro',
|
|
31
30
|
}
|
|
32
31
|
: {}),
|
package/package.json
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { expect, it } from 'vitest';
|
|
2
|
+
import { availableProviderSections } from './canonical-provider';
|
|
3
|
+
|
|
4
|
+
it('omits missing historical setup while retaining existing type families', () => {
|
|
5
|
+
const paths = [
|
|
6
|
+
'documentation/resources/demo/index.md',
|
|
7
|
+
'documentation/data-sources/demo/index.md',
|
|
8
|
+
'documentation/actions/demo/index.md',
|
|
9
|
+
'documentation/ephemeral-resources/demo/index.md',
|
|
10
|
+
'documentation/guides/example/index.md',
|
|
11
|
+
];
|
|
12
|
+
expect(availableProviderSections(paths).map((section) => section.path)).toEqual([
|
|
13
|
+
'guides',
|
|
14
|
+
'resources',
|
|
15
|
+
'data-sources',
|
|
16
|
+
'actions',
|
|
17
|
+
'ephemeral-resources',
|
|
18
|
+
]);
|
|
19
|
+
expect(availableProviderSections([...paths, 'documentation/provider/setup/index.md'])[0].path).toBe('provider/setup');
|
|
20
|
+
});
|
|
21
|
+
it('does not infer setup from a different provider page or an unrelated folder', () => {
|
|
22
|
+
expect(
|
|
23
|
+
availableProviderSections(['documentation/provider/index.md', 'documentation/resources-other/example.md']),
|
|
24
|
+
).toEqual([]);
|
|
25
|
+
});
|
|
@@ -8,6 +8,23 @@ export const providerSections = [
|
|
|
8
8
|
{ label: 'Ephemeral resources', path: 'ephemeral-resources', icon: 'random' },
|
|
9
9
|
];
|
|
10
10
|
|
|
11
|
+
export function availableProviderSections(paths: string[]) {
|
|
12
|
+
const slugs = paths
|
|
13
|
+
.filter((path) => path.startsWith('documentation/') && /\.mdx?$/.test(path))
|
|
14
|
+
.map((path) =>
|
|
15
|
+
path
|
|
16
|
+
.slice('documentation/'.length)
|
|
17
|
+
.replace(/(^|\/)index\.mdx?$/, '')
|
|
18
|
+
.replace(/\.mdx?$/, '')
|
|
19
|
+
.replace(/\/$/, ''),
|
|
20
|
+
);
|
|
21
|
+
return providerSections.filter((section) =>
|
|
22
|
+
section.path === 'provider/setup'
|
|
23
|
+
? slugs.includes(section.path)
|
|
24
|
+
: slugs.some((slug) => slug === section.path || slug.startsWith(`${section.path}/`)),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
11
28
|
export interface ProviderPage {
|
|
12
29
|
id: string;
|
|
13
30
|
collection_id: string;
|
|
@@ -54,7 +71,7 @@ export function collectionNavigation(pages: ProviderPage[], collection: string,
|
|
|
54
71
|
return (children.get(null) || []).map((page) => tree(page));
|
|
55
72
|
}
|
|
56
73
|
|
|
57
|
-
export function providerMegaMenu(base: string) {
|
|
74
|
+
export function providerMegaMenu(base: string, sections = providerSections) {
|
|
58
75
|
return [
|
|
59
76
|
{
|
|
60
77
|
label: 'Provider documentation',
|
|
@@ -64,7 +81,7 @@ export function providerMegaMenu(base: string) {
|
|
|
64
81
|
categories: [
|
|
65
82
|
{
|
|
66
83
|
title: 'Terraform xcsh',
|
|
67
|
-
items:
|
|
84
|
+
items: sections.map((section) => ({
|
|
68
85
|
label: section.label,
|
|
69
86
|
href: `${base.replace(/\/$/, '')}/${section.path}/`,
|
|
70
87
|
})),
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { expect, it } from 'vitest';
|
|
2
|
+
import { menuLocalizationPolicy } from './menu-localization';
|
|
3
|
+
|
|
4
|
+
it('routes archived desktop and mobile menu localization through the theme policy', () => {
|
|
5
|
+
const plugin = menuLocalizationPolicy();
|
|
6
|
+
for (const name of ['MegaMenu.tsx', 'MegaMenuMobile.tsx']) {
|
|
7
|
+
expect(
|
|
8
|
+
plugin.resolveId(
|
|
9
|
+
'../libs/localize-ecosystem-href.ts',
|
|
10
|
+
`/app/node_modules/@f5-sales-demo/starlight-mega-menu/components/${name}`,
|
|
11
|
+
),
|
|
12
|
+
).toMatch(/localize-ecosystem-href\.ts$/);
|
|
13
|
+
}
|
|
14
|
+
expect(plugin.resolveId('../libs/localize-ecosystem-href.ts', '/app/other.ts')).toBeUndefined();
|
|
15
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
|
|
3
|
+
// The archived menu package has a separate localizer that blindly adds language
|
|
4
|
+
// paths. Route both its desktop and mobile components through the theme policy.
|
|
5
|
+
export function menuLocalizationPolicy() {
|
|
6
|
+
return {
|
|
7
|
+
name: 'f5-menu-localization-policy',
|
|
8
|
+
enforce: 'pre' as const,
|
|
9
|
+
resolveId(source: string, importer?: string) {
|
|
10
|
+
if (importer?.includes('/starlight-mega-menu/') && /(?:^|\/)localize-ecosystem-href(?:\.ts)?$/.test(source)) {
|
|
11
|
+
return fileURLToPath(new URL('./localize-ecosystem-href.ts', import.meta.url));
|
|
12
|
+
}
|
|
13
|
+
return undefined;
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { availableProviderSections } from './canonical-provider.ts';
|
|
3
|
+
|
|
4
|
+
const sectionsByManifest = new Map<string, ReturnType<typeof availableProviderSections>>();
|
|
5
|
+
export function stagedProviderSections(manifest = process.env.CANONICAL_MANIFEST || '') {
|
|
6
|
+
if (!manifest) throw new Error('Canonical provider navigation requires a manifest');
|
|
7
|
+
let sections = sectionsByManifest.get(manifest);
|
|
8
|
+
if (!sections) {
|
|
9
|
+
const data = JSON.parse(fs.readFileSync(manifest, 'utf8'));
|
|
10
|
+
if (!data.files || typeof data.files !== 'object' || Array.isArray(data.files)) {
|
|
11
|
+
throw new Error('Canonical provider manifest requires file receipts');
|
|
12
|
+
}
|
|
13
|
+
sections = availableProviderSections(Object.keys(data.files));
|
|
14
|
+
sectionsByManifest.set(manifest, sections);
|
|
15
|
+
}
|
|
16
|
+
return sections;
|
|
17
|
+
}
|