@f5-sales-demo/docs-theme 4.11.5 → 4.11.6
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/components/Footer.astro +12 -36
- package/components/Head.astro +10 -0
- package/components/LinkCard.astro +17 -8
- package/components/ProviderHeader.astro +8 -3
- package/components/SharedHeader.astro +66 -4
- package/config.ts +172 -326
- package/index.ts +1 -0
- package/package.json +2 -1
- package/src/utils/localize-ecosystem-href.ts +4 -0
- package/src/utils/page-title.test.ts +7 -0
- package/src/utils/page-title.ts +4 -0
- package/src/utils/search-sites.ts +32 -0
- package/src/utils/search-source.test.ts +9 -0
- package/src/utils/search-source.ts +11 -0
- package/src/utils/showcase-navigation.test.ts +34 -0
- package/src/utils/statistics-navigation.test.ts +4 -4
- package/styles/custom.css +30 -0
package/components/Footer.astro
CHANGED
|
@@ -1,47 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
import Default from '@astrojs/starlight/components/Footer.astro';
|
|
3
|
-
import Icon from './Icon.astro';
|
|
4
3
|
---
|
|
5
4
|
|
|
6
5
|
<Default {...Astro.props}><slot /></Default>
|
|
7
6
|
|
|
8
|
-
{process.env.DOCS_PROFILE !== 'canonical-provider' && <
|
|
9
|
-
<a href="https://
|
|
10
|
-
|
|
11
|
-
</a>
|
|
12
|
-
|
|
13
|
-
<Icon name="hashicorp-flight:twitter-x" size="1.5rem" />
|
|
14
|
-
</a>
|
|
15
|
-
<a href="https://www.linkedin.com/company/f5/" target="_blank" rel="noopener noreferrer" aria-label="LinkedIn">
|
|
16
|
-
<Icon name="hashicorp-flight:linkedin-color" size="1.5rem" />
|
|
17
|
-
</a>
|
|
18
|
-
<a href="https://www.instagram.com/f5.global/" target="_blank" rel="noopener noreferrer" aria-label="Instagram">
|
|
19
|
-
<Icon name="hashicorp-flight:instagram-color" size="1.5rem" />
|
|
20
|
-
</a>
|
|
21
|
-
<a href="https://www.youtube.com/user/f5networksinc" target="_blank" rel="noopener noreferrer" aria-label="YouTube">
|
|
22
|
-
<Icon name="hashicorp-flight:youtube-color" size="1.5rem" />
|
|
23
|
-
</a>
|
|
24
|
-
</div>}
|
|
7
|
+
{process.env.DOCS_PROFILE !== 'canonical-provider' && <nav class="project-links" aria-label="Project information">
|
|
8
|
+
<a href="https://f5-sales-demo.github.io/en/ecosystem/">Ecosystem directory</a>
|
|
9
|
+
<a href="https://github.com/f5-sales-demo">Project sources</a>
|
|
10
|
+
<a href="https://docs.cloud.f5.com/">Official F5 documentation</a>
|
|
11
|
+
</nav>}
|
|
25
12
|
|
|
26
13
|
<style>
|
|
27
|
-
.
|
|
14
|
+
.project-links {
|
|
28
15
|
display: flex;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
.social-links a {
|
|
36
|
-
display: inline-flex;
|
|
37
|
-
transition: opacity 0.2s ease;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.social-links a:hover {
|
|
41
|
-
opacity: 0.7;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.social-links :global(svg) {
|
|
45
|
-
display: block;
|
|
16
|
+
flex-wrap: wrap;
|
|
17
|
+
gap: 0.5rem 1.5rem;
|
|
18
|
+
border-top: 1px solid var(--sl-color-gray-5);
|
|
19
|
+
margin-top: 2rem;
|
|
20
|
+
padding-block: 1rem;
|
|
46
21
|
}
|
|
22
|
+
.project-links a { padding-block: 0.5rem; }
|
|
47
23
|
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { pageTitle } from '../src/utils/page-title';
|
|
3
|
+
|
|
4
|
+
const route = Astro.locals.starlightRoute;
|
|
5
|
+
const head = route.head.map((entry) => entry.tag === 'title'
|
|
6
|
+
? { ...entry, content: pageTitle(route.entry.data.title, route.siteTitle, entry.content || '') }
|
|
7
|
+
: entry);
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
{head.map(({ tag: Tag, attrs, content }) => <Tag {...attrs} set:html={content} />)}
|
|
@@ -18,7 +18,7 @@ if (attributes.href && localeSlug) {
|
|
|
18
18
|
|
|
19
19
|
<div class:list={['sl-link-card', { 'has-icon': !!icon }]}>
|
|
20
20
|
{icon && (
|
|
21
|
-
<span class="card-icon">
|
|
21
|
+
<span class="card-icon" aria-hidden="true">
|
|
22
22
|
<Icon name={icon} />
|
|
23
23
|
</span>
|
|
24
24
|
)}
|
|
@@ -28,13 +28,13 @@ if (attributes.href && localeSlug) {
|
|
|
28
28
|
</a>
|
|
29
29
|
{description && <span class="description" set:html={description} />}
|
|
30
30
|
</span>
|
|
31
|
-
<Icon name="right-arrow" size="1.333em" class="icon rtl:flip"
|
|
31
|
+
<span aria-hidden="true"><Icon name="right-arrow" size="1.333em" class="icon rtl:flip" /></span>
|
|
32
32
|
</div>
|
|
33
33
|
|
|
34
34
|
<style>
|
|
35
35
|
.sl-link-card {
|
|
36
36
|
display: grid;
|
|
37
|
-
grid-template-columns: 1fr auto;
|
|
37
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
38
38
|
gap: 0.5rem;
|
|
39
39
|
border: 1px solid var(--sl-color-gray-5);
|
|
40
40
|
border-radius: 0.5rem;
|
|
@@ -46,7 +46,7 @@ if (attributes.href && localeSlug) {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
.sl-link-card.has-icon {
|
|
49
|
-
grid-template-columns: auto 1fr auto;
|
|
49
|
+
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
a {
|
|
@@ -62,7 +62,10 @@ if (attributes.href && localeSlug) {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
.stack {
|
|
65
|
-
|
|
65
|
+
min-width: 0;
|
|
66
|
+
overflow-wrap: anywhere;
|
|
67
|
+
display: grid;
|
|
68
|
+
align-content: start;
|
|
66
69
|
gap: 0.5rem;
|
|
67
70
|
}
|
|
68
71
|
|
|
@@ -75,6 +78,7 @@ if (attributes.href && localeSlug) {
|
|
|
75
78
|
.description {
|
|
76
79
|
color: var(--sl-color-gray-3);
|
|
77
80
|
line-height: 1.5;
|
|
81
|
+
margin: 0;
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
.icon {
|
|
@@ -83,10 +87,10 @@ if (attributes.href && localeSlug) {
|
|
|
83
87
|
|
|
84
88
|
.card-icon {
|
|
85
89
|
color: var(--sl-color-white);
|
|
86
|
-
align-self:
|
|
90
|
+
align-self: start;
|
|
87
91
|
position: relative;
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
width: 3rem;
|
|
93
|
+
height: 3rem;
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
.card-icon :global(svg) {
|
|
@@ -96,6 +100,11 @@ if (attributes.href && localeSlug) {
|
|
|
96
100
|
height: 100%;
|
|
97
101
|
}
|
|
98
102
|
|
|
103
|
+
.sl-link-card:focus-within {
|
|
104
|
+
outline: 2px solid var(--sl-color-text-accent);
|
|
105
|
+
outline-offset: 3px;
|
|
106
|
+
}
|
|
107
|
+
|
|
99
108
|
/* Hover state */
|
|
100
109
|
.sl-link-card:hover {
|
|
101
110
|
background: var(--sl-color-gray-7, var(--sl-color-gray-6));
|
|
@@ -49,6 +49,11 @@ const shouldRenderSearch = config.pagefind || config.components.Search !== '@ast
|
|
|
49
49
|
min-width: 0;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
.right-group { display: none; }
|
|
53
|
+
@media (min-width: 90rem) {
|
|
54
|
+
.right-group { display: flex; }
|
|
55
|
+
}
|
|
56
|
+
|
|
52
57
|
.right-group,
|
|
53
58
|
.social-icons {
|
|
54
59
|
gap: 1rem;
|
|
@@ -71,7 +76,7 @@ const shouldRenderSearch = config.pagefind || config.components.Search !== '@ast
|
|
|
71
76
|
align-items: center;
|
|
72
77
|
}
|
|
73
78
|
|
|
74
|
-
@media (min-width:
|
|
79
|
+
@media (min-width: 90rem) {
|
|
75
80
|
:global(:root[data-has-sidebar]) {
|
|
76
81
|
--__sidebar-pad: calc(2 * var(--sl-nav-pad-x));
|
|
77
82
|
}
|
|
@@ -90,9 +95,9 @@ const shouldRenderSearch = config.pagefind || config.components.Search !== '@ast
|
|
|
90
95
|
display: grid;
|
|
91
96
|
grid-template-columns:
|
|
92
97
|
/* 1 (site title) */
|
|
93
|
-
|
|
98
|
+
minmax(0, 1fr)
|
|
94
99
|
/* 2 (mega-menu nav) */
|
|
95
|
-
|
|
100
|
+
auto
|
|
96
101
|
/* 3 (search box) */
|
|
97
102
|
auto
|
|
98
103
|
/* 4 (right items) */
|
|
@@ -7,6 +7,7 @@ import ThemeSelect from 'virtual:starlight/components/ThemeSelect';
|
|
|
7
7
|
import config from 'virtual:starlight/user-config';
|
|
8
8
|
import MegaMenu from './SharedMegaMenu.tsx';
|
|
9
9
|
import MegaMenuMobile from './SharedMegaMenuMobile.tsx';
|
|
10
|
+
import { federatedSearchSites } from '../src/utils/search-sites';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Render the `Search` component if Pagefind is enabled or the default search component has been overridden.
|
|
@@ -14,7 +15,7 @@ import MegaMenuMobile from './SharedMegaMenuMobile.tsx';
|
|
|
14
15
|
const shouldRenderSearch = config.pagefind || config.components.Search !== '@astrojs/starlight/components/Search.astro';
|
|
15
16
|
---
|
|
16
17
|
|
|
17
|
-
<div class="header sl-mega-menu-header">
|
|
18
|
+
<div class="header sl-mega-menu-header" data-search-sources={JSON.stringify(federatedSearchSites)}>
|
|
18
19
|
<div class="title-wrapper sl-flex">
|
|
19
20
|
<SiteTitle />
|
|
20
21
|
</div>
|
|
@@ -34,8 +35,38 @@ const shouldRenderSearch = config.pagefind || config.components.Search !== '@ast
|
|
|
34
35
|
<div class="smm-mobile-toggle">
|
|
35
36
|
<MegaMenuMobile client:only="react" />
|
|
36
37
|
</div>
|
|
38
|
+
<details class="compact-preferences">
|
|
39
|
+
<summary aria-label="Display and language">Aa</summary>
|
|
40
|
+
<div class="preferences-panel"><ThemeSelect /><LanguageSelect /></div>
|
|
41
|
+
</details>
|
|
37
42
|
</div>
|
|
38
43
|
|
|
44
|
+
<script>
|
|
45
|
+
import { searchSource } from '../src/utils/search-source';
|
|
46
|
+
const header = document.querySelector<HTMLElement>('[data-search-sources]');
|
|
47
|
+
const sources = JSON.parse(header?.dataset.searchSources || '[]');
|
|
48
|
+
const annotateResults = () => {
|
|
49
|
+
for (const link of document.querySelectorAll<HTMLAnchorElement>('.pagefind-ui__result-link')) {
|
|
50
|
+
if (link.dataset.sourceAnnotated) continue;
|
|
51
|
+
link.dataset.sourceAnnotated = 'true';
|
|
52
|
+
const label = searchSource(link.href, sources);
|
|
53
|
+
if (!label) continue;
|
|
54
|
+
const source = document.createElement('span');
|
|
55
|
+
source.className = 'search-project-source';
|
|
56
|
+
source.textContent = label;
|
|
57
|
+
link.closest('.pagefind-ui__result-title')?.append(source);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
new MutationObserver(annotateResults).observe(document.body, { childList: true, subtree: true });
|
|
61
|
+
document.addEventListener('keydown', (event) => {
|
|
62
|
+
const preferences = document.querySelector<HTMLDetailsElement>('.compact-preferences[open]');
|
|
63
|
+
if (event.key === 'Escape' && preferences) {
|
|
64
|
+
preferences.open = false;
|
|
65
|
+
preferences.querySelector('summary')?.focus();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
</script>
|
|
69
|
+
|
|
39
70
|
<style>
|
|
40
71
|
@layer starlight.core {
|
|
41
72
|
.header {
|
|
@@ -55,6 +86,37 @@ const shouldRenderSearch = config.pagefind || config.components.Search !== '@ast
|
|
|
55
86
|
min-width: 0;
|
|
56
87
|
}
|
|
57
88
|
|
|
89
|
+
.right-group { display: none; }
|
|
90
|
+
.compact-preferences { position: relative; flex-shrink: 0; }
|
|
91
|
+
.compact-preferences summary {
|
|
92
|
+
cursor: pointer;
|
|
93
|
+
padding: 0.75rem;
|
|
94
|
+
min-height: 44px;
|
|
95
|
+
list-style: none;
|
|
96
|
+
}
|
|
97
|
+
.preferences-panel {
|
|
98
|
+
position: absolute;
|
|
99
|
+
inset-inline-end: 0;
|
|
100
|
+
top: calc(100% + 0.5rem);
|
|
101
|
+
display: grid;
|
|
102
|
+
gap: 0.5rem;
|
|
103
|
+
padding: 0.75rem;
|
|
104
|
+
background: var(--sl-color-bg-nav);
|
|
105
|
+
border: 1px solid var(--sl-color-gray-5);
|
|
106
|
+
border-radius: 0.5rem;
|
|
107
|
+
}
|
|
108
|
+
:global(.search-project-source) {
|
|
109
|
+
display: block;
|
|
110
|
+
font-size: var(--sl-text-sm);
|
|
111
|
+
font-weight: 400;
|
|
112
|
+
color: var(--sl-color-gray-2);
|
|
113
|
+
margin-top: 0.25rem;
|
|
114
|
+
}
|
|
115
|
+
@media (min-width: 90rem) {
|
|
116
|
+
.right-group { display: flex; }
|
|
117
|
+
.compact-preferences { display: none; }
|
|
118
|
+
}
|
|
119
|
+
|
|
58
120
|
.right-group,
|
|
59
121
|
.social-icons {
|
|
60
122
|
gap: 1rem;
|
|
@@ -77,7 +139,7 @@ const shouldRenderSearch = config.pagefind || config.components.Search !== '@ast
|
|
|
77
139
|
align-items: center;
|
|
78
140
|
}
|
|
79
141
|
|
|
80
|
-
@media (min-width:
|
|
142
|
+
@media (min-width: 90rem) {
|
|
81
143
|
:global(:root[data-has-sidebar]) {
|
|
82
144
|
--__sidebar-pad: calc(2 * var(--sl-nav-pad-x));
|
|
83
145
|
}
|
|
@@ -96,9 +158,9 @@ const shouldRenderSearch = config.pagefind || config.components.Search !== '@ast
|
|
|
96
158
|
display: grid;
|
|
97
159
|
grid-template-columns:
|
|
98
160
|
/* 1 (site title) */
|
|
99
|
-
|
|
161
|
+
minmax(0, 1fr)
|
|
100
162
|
/* 2 (mega-menu nav) */
|
|
101
|
-
|
|
163
|
+
auto
|
|
102
164
|
/* 3 (search box) */
|
|
103
165
|
auto
|
|
104
166
|
/* 4 (right items) */
|
package/config.ts
CHANGED
|
@@ -20,15 +20,7 @@ import starlightScrollToTop from 'starlight-scroll-to-top';
|
|
|
20
20
|
import starlightVideosPlugin from 'starlight-videos';
|
|
21
21
|
import f5xcDocsTheme from './index.ts';
|
|
22
22
|
import { defaultLocale as f5xcDefaultLocale, f5xcDefaultLocales } from './src/i18n/locales.ts';
|
|
23
|
-
import {
|
|
24
|
-
categoryTitles,
|
|
25
|
-
footerDescriptions,
|
|
26
|
-
footerLabels,
|
|
27
|
-
itemDescriptions,
|
|
28
|
-
itemLabels,
|
|
29
|
-
menuLabels,
|
|
30
|
-
mobileLabels,
|
|
31
|
-
} from './src/i18n/mega-menu-translations.ts';
|
|
23
|
+
import { mobileLabels } from './src/i18n/mega-menu-translations.ts';
|
|
32
24
|
import { sidebarTranslations } from './src/i18n/translations.ts';
|
|
33
25
|
import remarkMermaid from './src/plugins/remark-mermaid.mjs';
|
|
34
26
|
import canonicalLlms from './src/utils/canonical-llms.mjs';
|
|
@@ -37,6 +29,7 @@ import { menuLocalizationPolicy } from './src/utils/menu-localization.ts';
|
|
|
37
29
|
import { stagedProviderSections } from './src/utils/provider-sections.ts';
|
|
38
30
|
import { publicationSidebar, repositoryPublicationProfile } from './src/utils/publication-profiles.ts';
|
|
39
31
|
import { resolveMegaMenuIcon } from './src/utils/resolve-icon.ts';
|
|
32
|
+
import { federatedSearchSites } from './src/utils/search-sites';
|
|
40
33
|
import providerSharedAssets from './src/utils/share-provider-assets.mjs';
|
|
41
34
|
import { statisticsScriptMarkdown } from './src/utils/statistics-script-markdown.mjs';
|
|
42
35
|
import { buildSubcategorySidebar } from './src/utils/subcategory-sidebar.ts';
|
|
@@ -133,130 +126,79 @@ export interface F5xcDocsConfigOptions {
|
|
|
133
126
|
};
|
|
134
127
|
}
|
|
135
128
|
|
|
136
|
-
const developerAutomationTranslations = Object.fromEntries(
|
|
137
|
-
Object.entries(categoryTitles.Automation).map(([locale, automation]) => [
|
|
138
|
-
locale,
|
|
139
|
-
`${categoryTitles['Developer Tools'][locale]} / ${automation}`,
|
|
140
|
-
]),
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
const xcshActionDescriptionTranslations = Object.fromEntries(
|
|
144
|
-
Object.entries(categoryTitles.Automation).map(([locale, automation]) => [locale, `F5 XC — ${automation}`]),
|
|
145
|
-
);
|
|
146
|
-
|
|
147
129
|
export const defaultMegaMenuItems: MegaMenuItem[] = [
|
|
148
130
|
{
|
|
149
|
-
label: '
|
|
150
|
-
translations: menuLabels.Security,
|
|
131
|
+
label: 'Demos',
|
|
151
132
|
content: {
|
|
152
133
|
layout: 'grid',
|
|
153
134
|
columns: 2,
|
|
154
135
|
categories: [
|
|
155
136
|
{
|
|
156
|
-
title: '
|
|
157
|
-
translations: categoryTitles['App & API Security'],
|
|
137
|
+
title: 'Security',
|
|
158
138
|
items: [
|
|
159
139
|
{
|
|
160
140
|
label: 'Web App & API Protection',
|
|
161
|
-
description: '
|
|
162
|
-
href: 'https://f5-sales-demo.github.io/webapp-api-protection/',
|
|
141
|
+
description: 'Deploy an application security demo with Terraform and follow its protection walkthroughs.',
|
|
142
|
+
href: 'https://f5-sales-demo.github.io/webapp-api-protection/en/',
|
|
163
143
|
icon: resolveMegaMenuIcon('f5xc:web-app-and-api-protection'),
|
|
164
144
|
},
|
|
165
145
|
{
|
|
166
|
-
label: 'API
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
descriptionTranslations: itemDescriptions['API discovery and protection'],
|
|
170
|
-
href: 'https://f5-sales-demo.github.io/api-protection/',
|
|
146
|
+
label: 'API Protection',
|
|
147
|
+
description: 'Find guides to API discovery, schema validation, and request controls.',
|
|
148
|
+
href: 'https://f5-sales-demo.github.io/api-protection/en/',
|
|
171
149
|
icon: resolveMegaMenuIcon('f5xc:application-traffic-insight'),
|
|
172
150
|
},
|
|
173
151
|
{
|
|
174
|
-
label: '
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
href: 'https://f5-sales-demo.github.io/csd/',
|
|
179
|
-
icon: resolveMegaMenuIcon('f5xc:client-side-defense'),
|
|
152
|
+
label: 'Bot Defense Advanced',
|
|
153
|
+
description: 'Review behavioral bot detection and mitigation scenarios.',
|
|
154
|
+
href: 'https://f5-sales-demo.github.io/bot-advanced/en/',
|
|
155
|
+
icon: resolveMegaMenuIcon('f5xc:bot-defense'),
|
|
180
156
|
},
|
|
181
157
|
{
|
|
182
|
-
label: '
|
|
183
|
-
description: '
|
|
184
|
-
href: 'https://f5-sales-demo.github.io/
|
|
185
|
-
icon: resolveMegaMenuIcon('f5xc:
|
|
158
|
+
label: 'Bot Defense Standard',
|
|
159
|
+
description: 'Review bot classification, verified crawlers, and blocking policies.',
|
|
160
|
+
href: 'https://f5-sales-demo.github.io/bot-standard/en/',
|
|
161
|
+
icon: resolveMegaMenuIcon('f5xc:bot-defense'),
|
|
186
162
|
},
|
|
187
163
|
{
|
|
188
|
-
label: '
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
href: 'https://f5-sales-demo.github.io/was/',
|
|
193
|
-
icon: resolveMegaMenuIcon('f5xc:web-app-scanning'),
|
|
164
|
+
label: 'Client-Side Defense',
|
|
165
|
+
description: 'Deploy browser script monitoring with an API or Terraform workflow.',
|
|
166
|
+
href: 'https://f5-sales-demo.github.io/csd/en/',
|
|
167
|
+
icon: resolveMegaMenuIcon('f5xc:client-side-defense'),
|
|
194
168
|
},
|
|
195
|
-
],
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
title: 'Threat Defense',
|
|
199
|
-
translations: categoryTitles['Threat Defense'],
|
|
200
|
-
items: [
|
|
201
169
|
{
|
|
202
|
-
label: '
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
href: 'https://f5-sales-demo.github.io/bot-advanced/',
|
|
207
|
-
icon: resolveMegaMenuIcon('f5xc:bot-defense'),
|
|
170
|
+
label: 'DDoS Mitigation',
|
|
171
|
+
description: 'Review distributed denial-of-service defenses and demo scenarios.',
|
|
172
|
+
href: 'https://f5-sales-demo.github.io/ddos/en/',
|
|
173
|
+
icon: resolveMegaMenuIcon('f5xc:ddos-and-transit-services'),
|
|
208
174
|
},
|
|
209
175
|
{
|
|
210
|
-
label: '
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
href: 'https://f5-sales-demo.github.io/bot-standard/',
|
|
215
|
-
icon: resolveMegaMenuIcon('f5xc:bot-defense'),
|
|
176
|
+
label: 'Web App Scanning',
|
|
177
|
+
description: 'Find web application vulnerability scanning guides.',
|
|
178
|
+
href: 'https://f5-sales-demo.github.io/was/en/',
|
|
179
|
+
icon: resolveMegaMenuIcon('f5xc:web-app-scanning'),
|
|
216
180
|
},
|
|
217
181
|
{
|
|
218
|
-
label: '
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
href: 'https://f5-sales-demo.github.io/ddos/',
|
|
223
|
-
icon: resolveMegaMenuIcon('f5xc:ddos-and-transit-services'),
|
|
182
|
+
label: 'Custom responses',
|
|
183
|
+
description: 'Configure application replies, redirects, and security response pages.',
|
|
184
|
+
href: 'https://f5-sales-demo.github.io/custom-responses/en/',
|
|
185
|
+
icon: resolveMegaMenuIcon('f5xc:web-app-and-api-protection'),
|
|
224
186
|
},
|
|
225
187
|
],
|
|
226
188
|
},
|
|
227
|
-
],
|
|
228
|
-
footer: {
|
|
229
|
-
label: 'F5 Distributed Cloud Console',
|
|
230
|
-
translations: footerLabels['F5 Distributed Cloud Console'],
|
|
231
|
-
href: 'https://console.ves.volterra.io',
|
|
232
|
-
description: 'Open the XC management portal',
|
|
233
|
-
descriptionTranslations: footerDescriptions['Open the XC management portal'],
|
|
234
|
-
},
|
|
235
|
-
},
|
|
236
|
-
},
|
|
237
|
-
{
|
|
238
|
-
label: 'Networking',
|
|
239
|
-
translations: menuLabels.Networking,
|
|
240
|
-
content: {
|
|
241
|
-
layout: 'grid',
|
|
242
|
-
columns: 2,
|
|
243
|
-
categories: [
|
|
244
189
|
{
|
|
245
|
-
title: '
|
|
246
|
-
translations: categoryTitles['Connectivity & Delivery'],
|
|
190
|
+
title: 'Networking and performance',
|
|
247
191
|
items: [
|
|
248
192
|
{
|
|
249
193
|
label: 'Multi-Cloud Networking',
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
descriptionTranslations: itemDescriptions['Site connectivity across clouds'],
|
|
253
|
-
href: 'https://f5-sales-demo.github.io/multi-cloud-networking/',
|
|
194
|
+
description: 'Find site deployment and cross-cloud connectivity guides.',
|
|
195
|
+
href: 'https://f5-sales-demo.github.io/multi-cloud-networking/en/',
|
|
254
196
|
icon: resolveMegaMenuIcon('f5xc:multi-cloud-network-connect'),
|
|
255
197
|
},
|
|
256
198
|
{
|
|
257
|
-
label: 'Canada
|
|
258
|
-
description: 'Canadian hosting and regional access
|
|
259
|
-
href: 'https://f5-sales-demo.github.io/canada/',
|
|
199
|
+
label: 'Canada topology',
|
|
200
|
+
description: 'Deploy Canadian application hosting and demonstrate regional access controls.',
|
|
201
|
+
href: 'https://f5-sales-demo.github.io/canada/en/',
|
|
260
202
|
icon: {
|
|
261
203
|
body: fs
|
|
262
204
|
.readFileSync(new URL('./assets/canada-flag.svg', import.meta.url), 'utf8')
|
|
@@ -267,223 +209,180 @@ export const defaultMegaMenuItems: MegaMenuItem[] = [
|
|
|
267
209
|
},
|
|
268
210
|
},
|
|
269
211
|
{
|
|
270
|
-
label: 'Content Delivery',
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
descriptionTranslations: itemDescriptions['Edge caching and distribution'],
|
|
274
|
-
href: 'https://f5-sales-demo.github.io/cdn/',
|
|
212
|
+
label: 'Content Delivery Network',
|
|
213
|
+
description: 'Review content delivery network (CDN) caching and origin configuration.',
|
|
214
|
+
href: 'https://f5-sales-demo.github.io/cdn/en/',
|
|
275
215
|
icon: resolveMegaMenuIcon('f5xc:content-delivery-network'),
|
|
276
216
|
},
|
|
277
217
|
{
|
|
278
|
-
label: 'DNS
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
descriptionTranslations: itemDescriptions['DNS management and zones'],
|
|
282
|
-
href: 'https://f5-sales-demo.github.io/dns/',
|
|
218
|
+
label: 'DNS Management',
|
|
219
|
+
description: 'Find Domain Name System (DNS) zone and load balancing guides.',
|
|
220
|
+
href: 'https://f5-sales-demo.github.io/dns/en/',
|
|
283
221
|
icon: resolveMegaMenuIcon('f5xc:dns-management'),
|
|
284
222
|
},
|
|
285
223
|
{
|
|
286
|
-
label: 'NGINX
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
descriptionTranslations: itemDescriptions['NGINX integration and configuration'],
|
|
290
|
-
href: 'https://f5-sales-demo.github.io/nginx/',
|
|
224
|
+
label: 'NGINX One',
|
|
225
|
+
description: 'Review NGINX instance visibility and configuration management.',
|
|
226
|
+
href: 'https://f5-sales-demo.github.io/nginx/en/',
|
|
291
227
|
icon: resolveMegaMenuIcon('f5xc:nginx-one'),
|
|
292
228
|
},
|
|
293
229
|
],
|
|
294
230
|
},
|
|
231
|
+
],
|
|
232
|
+
footer: {
|
|
233
|
+
label: 'Demo catalog',
|
|
234
|
+
href: 'https://f5-sales-demo.github.io/en/demos/',
|
|
235
|
+
description: 'All demonstration and capability guides',
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
label: 'Demo environment',
|
|
241
|
+
content: {
|
|
242
|
+
layout: 'list',
|
|
243
|
+
categories: [
|
|
295
244
|
{
|
|
296
|
-
title: '
|
|
297
|
-
translations: categoryTitles['Manage & Monitor'],
|
|
245
|
+
title: 'Deployment resources',
|
|
298
246
|
items: [
|
|
299
247
|
{
|
|
300
|
-
label: '
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
href: 'https://f5-sales-demo.github.io/observability/',
|
|
305
|
-
icon: resolveMegaMenuIcon('f5xc:observability'),
|
|
248
|
+
label: 'Origin server',
|
|
249
|
+
description: 'Compare the Azure full-origin stack with the separate AWS Juice Shop deployment.',
|
|
250
|
+
href: 'https://f5-sales-demo.github.io/origin-server/en/',
|
|
251
|
+
icon: resolveMegaMenuIcon('f5xc:distributed-apps'),
|
|
306
252
|
},
|
|
307
253
|
{
|
|
308
|
-
label: '
|
|
309
|
-
description:
|
|
310
|
-
|
|
311
|
-
|
|
254
|
+
label: 'Traffic generator',
|
|
255
|
+
description:
|
|
256
|
+
'Choose Azure or AWS deployment guides for controlled security traffic and browser scenarios.',
|
|
257
|
+
href: 'https://f5-sales-demo.github.io/traffic-generator/en/',
|
|
258
|
+
icon: resolveMegaMenuIcon('f5xc:application-traffic-insight'),
|
|
312
259
|
},
|
|
313
260
|
{
|
|
314
|
-
label: '
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
href: 'https://f5-sales-demo.github.io/administration/',
|
|
319
|
-
icon: resolveMegaMenuIcon('f5xc:administration'),
|
|
261
|
+
label: 'CDN simulator',
|
|
262
|
+
description: 'Deploy an Azure proxy that adds CDN headers to origin requests.',
|
|
263
|
+
href: 'https://f5-sales-demo.github.io/cdn-simulator/en/',
|
|
264
|
+
icon: resolveMegaMenuIcon('f5xc:content-delivery-network'),
|
|
320
265
|
},
|
|
321
266
|
],
|
|
322
267
|
},
|
|
323
268
|
],
|
|
324
269
|
footer: {
|
|
325
|
-
label: '
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
description: 'Official product documentation',
|
|
329
|
-
descriptionTranslations: footerDescriptions['Official product documentation'],
|
|
270
|
+
label: 'Demo resource catalog',
|
|
271
|
+
href: 'https://f5-sales-demo.github.io/demo-resources/en/',
|
|
272
|
+
description: 'Azure and AWS offerings vary by component',
|
|
330
273
|
},
|
|
331
274
|
},
|
|
332
275
|
},
|
|
333
276
|
{
|
|
334
|
-
label: '
|
|
335
|
-
translations: menuLabels.Platform,
|
|
277
|
+
label: 'Operations',
|
|
336
278
|
content: {
|
|
337
279
|
layout: 'list',
|
|
338
280
|
categories: [
|
|
339
281
|
{
|
|
340
|
-
title: '
|
|
341
|
-
translations: categoryTitles['Documentation Tools'],
|
|
282
|
+
title: 'Queries and administration',
|
|
342
283
|
items: [
|
|
343
284
|
{
|
|
344
|
-
label: '
|
|
345
|
-
description: '
|
|
346
|
-
href: 'https://f5-sales-demo.github.io/',
|
|
347
|
-
icon: resolveMegaMenuIcon('f5xc:doc'),
|
|
348
|
-
},
|
|
349
|
-
{
|
|
350
|
-
label: 'Docs Builder',
|
|
351
|
-
translations: itemLabels['Docs Builder'],
|
|
352
|
-
description: 'Containerized Astro build system',
|
|
353
|
-
descriptionTranslations: itemDescriptions['Containerized Astro build system'],
|
|
354
|
-
href: 'https://f5-sales-demo.github.io/docs-builder/',
|
|
355
|
-
icon: resolveMegaMenuIcon('f5xc:doc'),
|
|
356
|
-
},
|
|
357
|
-
{
|
|
358
|
-
label: 'F5 Docs Corpus',
|
|
359
|
-
translations: itemLabels['F5 Docs Corpus'],
|
|
360
|
-
description: 'Machine-readable F5 product documentation',
|
|
361
|
-
descriptionTranslations: itemDescriptions['Machine-readable F5 product documentation'],
|
|
362
|
-
href: 'https://f5-sales-demo.github.io/html-to-markdown/',
|
|
285
|
+
label: 'Statistics',
|
|
286
|
+
description: 'Query access logs, application metrics, and security telemetry through the API.',
|
|
287
|
+
href: 'https://f5-sales-demo.github.io/statistics/en/',
|
|
363
288
|
icon: resolveMegaMenuIcon('f5xc:doc'),
|
|
364
289
|
},
|
|
365
290
|
{
|
|
366
|
-
label: '
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
href: 'https://f5-sales-demo.github.io/docs-theme/',
|
|
371
|
-
icon: resolveMegaMenuIcon('f5xc:shared-configuration'),
|
|
291
|
+
label: 'Observability',
|
|
292
|
+
description: 'Find monitoring, metrics, tracing, and alerting guides.',
|
|
293
|
+
href: 'https://f5-sales-demo.github.io/observability/en/',
|
|
294
|
+
icon: resolveMegaMenuIcon('f5xc:observability'),
|
|
372
295
|
},
|
|
373
296
|
{
|
|
374
|
-
label: '
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
href: 'https://f5-sales-demo.github.io/docs-icons/',
|
|
379
|
-
icon: resolveMegaMenuIcon('f5xc:distributed-apps'),
|
|
297
|
+
label: 'Administration',
|
|
298
|
+
description: 'Find tenant, namespace, and role management guides.',
|
|
299
|
+
href: 'https://f5-sales-demo.github.io/administration/en/',
|
|
300
|
+
icon: resolveMegaMenuIcon('f5xc:administration'),
|
|
380
301
|
},
|
|
381
302
|
],
|
|
382
303
|
},
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
label: 'Developer tools',
|
|
309
|
+
content: {
|
|
310
|
+
layout: 'grid',
|
|
311
|
+
columns: 2,
|
|
312
|
+
categories: [
|
|
383
313
|
{
|
|
384
|
-
title: '
|
|
385
|
-
translations: developerAutomationTranslations,
|
|
314
|
+
title: 'Tools and automation',
|
|
386
315
|
items: [
|
|
387
316
|
{
|
|
388
|
-
label: '
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
icon: resolveMegaMenuIcon('hashicorp-flight:terraform-color'),
|
|
394
|
-
},
|
|
395
|
-
{
|
|
396
|
-
label: 'API Specs',
|
|
397
|
-
translations: itemLabels['API Specs'],
|
|
398
|
-
description: 'OpenAPI spec validation and reconciliation',
|
|
399
|
-
descriptionTranslations: itemDescriptions['OpenAPI spec validation and reconciliation'],
|
|
400
|
-
href: 'https://f5-sales-demo.github.io/api-specs/',
|
|
401
|
-
icon: resolveMegaMenuIcon('f5xc:data-intelligence'),
|
|
317
|
+
label: 'xcsh',
|
|
318
|
+
description:
|
|
319
|
+
'Install the independent terminal assistant for engineering and F5 Distributed Cloud workflows.',
|
|
320
|
+
href: 'https://f5-sales-demo.github.io/xcsh/en/',
|
|
321
|
+
icon: resolveMegaMenuIcon('carbon:terminal'),
|
|
402
322
|
},
|
|
403
323
|
{
|
|
404
|
-
label: '
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
href: 'https://f5-sales-demo.github.io/api-specs-enriched/',
|
|
409
|
-
icon: resolveMegaMenuIcon('f5xc:data-intelligence'),
|
|
324
|
+
label: 'Terraform provider',
|
|
325
|
+
description: 'Configure F5 Distributed Cloud resources with Terraform.',
|
|
326
|
+
href: 'https://f5-sales-demo.github.io/terraform-provider-xcsh/',
|
|
327
|
+
icon: resolveMegaMenuIcon('f5xc:doc'),
|
|
410
328
|
},
|
|
411
329
|
{
|
|
412
|
-
label: 'xcsh
|
|
413
|
-
description: '
|
|
414
|
-
|
|
415
|
-
href: 'https://f5-sales-demo.github.io/xcsh-action/',
|
|
330
|
+
label: 'xcsh GitHub Action',
|
|
331
|
+
description: 'Run pinned xcsh manifest operations in GitHub Actions.',
|
|
332
|
+
href: 'https://f5-sales-demo.github.io/xcsh-action/en/',
|
|
416
333
|
icon: resolveMegaMenuIcon('carbon:workflow-automation'),
|
|
417
334
|
},
|
|
418
335
|
{
|
|
419
|
-
label: 'VS Code
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
descriptionTranslations: itemDescriptions['Manage F5 XC resources from VS Code'],
|
|
423
|
-
href: 'https://f5-sales-demo.github.io/vscode-xcsh/',
|
|
336
|
+
label: 'VS Code extension',
|
|
337
|
+
description: 'Author manifests and manage F5 Distributed Cloud resources in Visual Studio Code.',
|
|
338
|
+
href: 'https://f5-sales-demo.github.io/vscode-xcsh/en/',
|
|
424
339
|
icon: resolveMegaMenuIcon('carbon:code'),
|
|
425
340
|
},
|
|
426
341
|
{
|
|
427
|
-
label: 'xcsh
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
href: 'https://f5-sales-demo.github.io/xcsh/',
|
|
432
|
-
icon: resolveMegaMenuIcon('carbon:terminal'),
|
|
342
|
+
label: 'xcsh Chrome extension',
|
|
343
|
+
description: 'Connect xcsh to the F5 Distributed Cloud console through a local browser bridge.',
|
|
344
|
+
href: 'https://f5-sales-demo.github.io/xcsh-chrome-extension/en/',
|
|
345
|
+
icon: resolveMegaMenuIcon('carbon:application-web'),
|
|
433
346
|
},
|
|
434
347
|
{
|
|
435
|
-
label: '
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
href: 'https://f5-sales-demo.github.io/xcsh-chrome-extension/',
|
|
440
|
-
icon: resolveMegaMenuIcon('carbon:application-web'),
|
|
348
|
+
label: 'APT repository',
|
|
349
|
+
description: 'Install signed Debian and Ubuntu packages for xcsh and supporting tools.',
|
|
350
|
+
href: 'https://f5-sales-demo.github.io/apt-repo/en/',
|
|
351
|
+
icon: resolveMegaMenuIcon('f5xc:doc'),
|
|
441
352
|
},
|
|
442
353
|
],
|
|
443
354
|
},
|
|
444
|
-
],
|
|
445
|
-
footer: {
|
|
446
|
-
label: 'GitHub Organization',
|
|
447
|
-
translations: footerLabels['GitHub Organization'],
|
|
448
|
-
href: 'https://github.com/f5-sales-demo',
|
|
449
|
-
description: 'View all repositories',
|
|
450
|
-
descriptionTranslations: footerDescriptions['View all repositories'],
|
|
451
|
-
},
|
|
452
|
-
},
|
|
453
|
-
},
|
|
454
|
-
{
|
|
455
|
-
label: 'AI',
|
|
456
|
-
translations: menuLabels.AI,
|
|
457
|
-
content: {
|
|
458
|
-
layout: 'list',
|
|
459
|
-
categories: [
|
|
460
355
|
{
|
|
461
|
-
title: '
|
|
462
|
-
translations: categoryTitles['AI Tools'],
|
|
356
|
+
title: 'Specifications and plugins',
|
|
463
357
|
items: [
|
|
464
358
|
{
|
|
465
|
-
label: '
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
href: 'https://f5-sales-demo.github.io/marketplace/',
|
|
470
|
-
icon: resolveMegaMenuIcon('f5xc:ai_assistant_logo'),
|
|
359
|
+
label: 'API specifications',
|
|
360
|
+
description: 'Find validated OpenAPI specifications and the specification update pipeline.',
|
|
361
|
+
href: 'https://f5-sales-demo.github.io/api-specs/en/',
|
|
362
|
+
icon: resolveMegaMenuIcon('f5xc:data-intelligence'),
|
|
471
363
|
},
|
|
472
364
|
{
|
|
473
|
-
label: '
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
365
|
+
label: 'Enriched API specifications',
|
|
366
|
+
description: 'Browse OpenAPI schemas with additional constraints and examples.',
|
|
367
|
+
href: 'https://f5-sales-demo.github.io/api-specs-enriched/en/',
|
|
368
|
+
icon: resolveMegaMenuIcon('f5xc:data-intelligence'),
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
label: 'xcsh marketplace',
|
|
372
|
+
description: 'Find xcsh plugins for documentation, sales, cloud, security, and desktop work.',
|
|
373
|
+
href: 'https://f5-sales-demo.github.io/marketplace/en/',
|
|
479
374
|
icon: resolveMegaMenuIcon('f5xc:ai_assistant_logo'),
|
|
480
375
|
},
|
|
481
376
|
{
|
|
482
|
-
label: '
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
377
|
+
label: 'Marketplace for Claude Code',
|
|
378
|
+
description: 'Find Language Server Protocol integrations and developer tools for Claude Code.',
|
|
379
|
+
href: 'https://f5-sales-demo.github.io/marketplace-claude-code/en/',
|
|
380
|
+
icon: resolveMegaMenuIcon('f5xc:doc'),
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
label: 'Console catalog',
|
|
384
|
+
description: 'Browse documented console routes and browser automation workflows.',
|
|
385
|
+
href: 'https://f5-sales-demo.github.io/console/en/',
|
|
487
386
|
icon: resolveMegaMenuIcon('f5xc:ai_assistant_logo'),
|
|
488
387
|
},
|
|
489
388
|
],
|
|
@@ -492,82 +391,58 @@ export const defaultMegaMenuItems: MegaMenuItem[] = [
|
|
|
492
391
|
},
|
|
493
392
|
},
|
|
494
393
|
{
|
|
495
|
-
label: '
|
|
496
|
-
translations: menuLabels['Demo Resources'],
|
|
394
|
+
label: 'Ecosystem',
|
|
497
395
|
content: {
|
|
498
396
|
layout: 'list',
|
|
499
397
|
categories: [
|
|
500
398
|
{
|
|
501
|
-
title: '
|
|
502
|
-
translations: categoryTitles.Components,
|
|
399
|
+
title: 'Public projects',
|
|
503
400
|
items: [
|
|
504
401
|
{
|
|
505
|
-
label: '
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
href: 'https://f5-sales-demo.github.io/origin-server/',
|
|
510
|
-
icon: resolveMegaMenuIcon('f5xc:distributed-apps'),
|
|
511
|
-
},
|
|
512
|
-
{
|
|
513
|
-
label: 'Traffic Generator',
|
|
514
|
-
translations: itemLabels['Traffic Generator'],
|
|
515
|
-
description: 'Security tools and attack suites for traffic generation',
|
|
516
|
-
descriptionTranslations: itemDescriptions['Security tools and attack suites for traffic generation'],
|
|
517
|
-
href: 'https://f5-sales-demo.github.io/traffic-generator/',
|
|
518
|
-
icon: resolveMegaMenuIcon('f5xc:application-traffic-insight'),
|
|
402
|
+
label: 'F5 documentation corpus',
|
|
403
|
+
description: 'Browse curated F5 documentation and its Markdown sources.',
|
|
404
|
+
href: 'https://f5-sales-demo.github.io/html-to-markdown/',
|
|
405
|
+
icon: resolveMegaMenuIcon('f5xc:doc'),
|
|
519
406
|
},
|
|
520
407
|
{
|
|
521
|
-
label: '
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
href: 'https://f5-sales-demo.github.io/cdn-simulator/',
|
|
526
|
-
icon: resolveMegaMenuIcon('f5xc:content-delivery-network'),
|
|
408
|
+
label: 'Ecosystem directory',
|
|
409
|
+
description: 'Documentation, tools, and public project sources',
|
|
410
|
+
href: 'https://f5-sales-demo.github.io/en/ecosystem/',
|
|
411
|
+
icon: resolveMegaMenuIcon('f5xc:doc'),
|
|
527
412
|
},
|
|
528
413
|
],
|
|
529
414
|
},
|
|
530
415
|
],
|
|
531
416
|
footer: {
|
|
532
|
-
label: '
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
description: 'Browse the full demo resource catalog',
|
|
536
|
-
descriptionTranslations: footerDescriptions['Browse the full demo resource catalog'],
|
|
417
|
+
label: 'Project sources',
|
|
418
|
+
href: 'https://github.com/f5-sales-demo',
|
|
419
|
+
description: 'Public repositories in the community organization',
|
|
537
420
|
},
|
|
538
421
|
},
|
|
539
422
|
},
|
|
540
423
|
{
|
|
541
|
-
label: '
|
|
542
|
-
translations: menuLabels.Resources,
|
|
424
|
+
label: 'F5 services',
|
|
543
425
|
content: {
|
|
544
426
|
layout: 'list',
|
|
545
427
|
categories: [
|
|
546
428
|
{
|
|
547
|
-
title: '
|
|
548
|
-
translations: categoryTitles['F5 Ecosystem'],
|
|
429
|
+
title: 'Official documentation and services',
|
|
549
430
|
items: [
|
|
550
431
|
{
|
|
551
|
-
label: 'F5
|
|
552
|
-
|
|
553
|
-
description: 'Distributed Cloud management portal',
|
|
554
|
-
descriptionTranslations: itemDescriptions['Distributed Cloud management portal'],
|
|
432
|
+
label: 'F5 Distributed Cloud console',
|
|
433
|
+
description: 'Management service; sign-in required',
|
|
555
434
|
href: 'https://console.ves.volterra.io',
|
|
556
435
|
icon: resolveMegaMenuIcon('f5xc:platform'),
|
|
557
436
|
},
|
|
558
437
|
{
|
|
559
|
-
label: 'F5 Cloud
|
|
560
|
-
|
|
561
|
-
description: 'Official product documentation',
|
|
562
|
-
descriptionTranslations: itemDescriptions['Official product documentation'],
|
|
438
|
+
label: 'F5 Distributed Cloud documentation',
|
|
439
|
+
description: 'Official public product documentation',
|
|
563
440
|
href: 'https://docs.cloud.f5.com',
|
|
564
441
|
icon: resolveMegaMenuIcon('f5xc:doc'),
|
|
565
442
|
},
|
|
566
443
|
{
|
|
567
|
-
label: 'MyF5
|
|
568
|
-
|
|
569
|
-
description: 'Technical support portal',
|
|
570
|
-
descriptionTranslations: itemDescriptions['Technical support portal'],
|
|
444
|
+
label: 'MyF5 support',
|
|
445
|
+
description: 'Support portal; sign-in required for account services',
|
|
571
446
|
href: 'https://my.f5.com/manage/s/',
|
|
572
447
|
icon: resolveMegaMenuIcon('f5xc:support'),
|
|
573
448
|
},
|
|
@@ -630,38 +505,7 @@ export function federatedSearchBundlePaths(site: string, base: string): string[]
|
|
|
630
505
|
);
|
|
631
506
|
}
|
|
632
507
|
|
|
633
|
-
export
|
|
634
|
-
{ repo: 'docs-builder', label: 'Docs Builder' },
|
|
635
|
-
{ repo: 'docs-theme', label: 'Docs Theme' },
|
|
636
|
-
{ repo: 'f5-sales-demo.github.io', label: 'F5 XC Docs' },
|
|
637
|
-
{ repo: 'administration', label: 'Administration' },
|
|
638
|
-
{ repo: 'nginx', label: 'NGINX' },
|
|
639
|
-
{ repo: 'observability', label: 'Observability' },
|
|
640
|
-
{ repo: 'statistics', label: 'Statistics' },
|
|
641
|
-
{ repo: 'was', label: 'Web App Scanning' },
|
|
642
|
-
{ repo: 'multi-cloud-networking', label: 'Multi-Cloud Networking' },
|
|
643
|
-
{ repo: 'canada', label: 'Canada Topology' },
|
|
644
|
-
{ repo: 'dns', label: 'DNS' },
|
|
645
|
-
{ repo: 'cdn', label: 'CDN' },
|
|
646
|
-
{ repo: 'bot-standard', label: 'Bot Standard' },
|
|
647
|
-
{ repo: 'bot-advanced', label: 'Bot Advanced' },
|
|
648
|
-
{ repo: 'ddos', label: 'DDoS' },
|
|
649
|
-
{ repo: 'webapp-api-protection', label: 'Web App & API Protection' },
|
|
650
|
-
{ repo: 'api-protection', label: 'API Security' },
|
|
651
|
-
{ repo: 'xcsh', label: 'xcsh' },
|
|
652
|
-
{ repo: 'xcsh-action', label: 'xcsh Manifest Automation' },
|
|
653
|
-
{ repo: 'csd', label: 'Client-Side Defense' },
|
|
654
|
-
{ repo: 'docs-icons', label: 'Docs Icons' },
|
|
655
|
-
{ repo: 'marketplace', label: 'Marketplace' },
|
|
656
|
-
{ repo: 'api-specs', label: 'API Specs' },
|
|
657
|
-
{ repo: 'api-specs-enriched', label: 'API Specs Enriched' },
|
|
658
|
-
{ repo: 'cdn-simulator', label: 'CDN Simulator' },
|
|
659
|
-
{ repo: 'origin-server', label: 'Origin Server' },
|
|
660
|
-
{ repo: 'traffic-generator', label: 'Traffic Generator' },
|
|
661
|
-
{ repo: 'demo-resources', label: 'Demo Resources' },
|
|
662
|
-
{ repo: 'xcsh-chrome-extension', label: 'xcsh Chrome Extension' },
|
|
663
|
-
{ repo: 'console', label: 'Console Catalog' },
|
|
664
|
-
];
|
|
508
|
+
export { federatedSearchSites } from './src/utils/search-sites';
|
|
665
509
|
|
|
666
510
|
export function createF5xcDocsConfig(options: F5xcDocsConfigOptions = {}) {
|
|
667
511
|
const canonicalProvider =
|
|
@@ -729,7 +573,9 @@ export function createF5xcDocsConfig(options: F5xcDocsConfigOptions = {}) {
|
|
|
729
573
|
(canonicalProvider
|
|
730
574
|
? [...defaultMegaMenuItems, ...providerMegaMenu(base, stagedProviderSections(canonicalProvider.manifest))]
|
|
731
575
|
: defaultMegaMenuItems);
|
|
732
|
-
const head =
|
|
576
|
+
const head =
|
|
577
|
+
options.head ||
|
|
578
|
+
(canonicalProvider || githubRepository === 'f5-sales-demo/f5-sales-demo.github.io' ? [] : defaultHead);
|
|
733
579
|
const logo = options.logo || { src: '@f5-sales-demo/docs-theme/assets/f5-distributed-cloud.svg' };
|
|
734
580
|
const additionalRemarkPlugins = options.additionalRemarkPlugins || [];
|
|
735
581
|
const additionalIntegrations = options.additionalIntegrations || [];
|
package/index.ts
CHANGED
|
@@ -25,6 +25,7 @@ export default function f5xcDocsTheme(repository = process.env.GITHUB_REPOSITORY
|
|
|
25
25
|
components: {
|
|
26
26
|
...config.components,
|
|
27
27
|
Header: '@f5-sales-demo/docs-theme/components/SharedHeader.astro',
|
|
28
|
+
Head: '@f5-sales-demo/docs-theme/components/Head.astro',
|
|
28
29
|
...(process.env.DOCS_PROFILE === 'canonical-provider'
|
|
29
30
|
? {
|
|
30
31
|
Sidebar: '@f5-sales-demo/docs-theme/components/ProviderSidebar.astro',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@f5-sales-demo/docs-theme",
|
|
3
|
-
"version": "4.11.
|
|
3
|
+
"version": "4.11.6",
|
|
4
4
|
"description": "F5 Distributed Cloud branded Starlight documentation theme",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"./components/CanadaSidebar.astro": "./components/CanadaSidebar.astro",
|
|
47
47
|
"./components/ProviderHeader.astro": "./components/ProviderHeader.astro",
|
|
48
48
|
"./components/SharedHeader.astro": "./components/SharedHeader.astro",
|
|
49
|
+
"./components/Head.astro": "./components/Head.astro",
|
|
49
50
|
"./assets/canada-flag.svg": "./assets/canada-flag.svg",
|
|
50
51
|
"./assets/canada-favicon.svg": "./assets/canada-favicon.svg"
|
|
51
52
|
},
|
|
@@ -29,6 +29,10 @@ export function localizeEcosystemHref(
|
|
|
29
29
|
const segments = url.pathname.split('/').filter(Boolean);
|
|
30
30
|
if (segments.length === 0) return href;
|
|
31
31
|
|
|
32
|
+
// Organization-root routes begin with a locale, not a project slug.
|
|
33
|
+
// Explicit catalog locale links must never become /en/fr/demos/.
|
|
34
|
+
if (VALID_SLUGS.has(segments[0])) return href;
|
|
35
|
+
|
|
32
36
|
if (NON_LOCALIZED_ECOSYSTEM_SLUGS.has(segments[0])) return href;
|
|
33
37
|
|
|
34
38
|
if (segments.length >= 2 && VALID_SLUGS.has(segments[1])) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { expect, it } from 'vitest';
|
|
2
|
+
import { pageTitle } from './page-title';
|
|
3
|
+
|
|
4
|
+
it('omits a duplicate site suffix while retaining distinct page titles', () => {
|
|
5
|
+
expect(pageTitle('Sales demos', 'Sales demos', 'Sales demos | Sales demos')).toBe('Sales demos');
|
|
6
|
+
expect(pageTitle('Demo catalog', 'Sales demos', 'Demo catalog | Sales demos')).toBe('Demo catalog | Sales demos');
|
|
7
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const federatedSearchSites = [
|
|
2
|
+
{ repo: 'docs-builder', label: 'Documentation builder' },
|
|
3
|
+
{ repo: 'docs-theme', label: 'Shared documentation theme' },
|
|
4
|
+
{ repo: 'f5-sales-demo.github.io', label: 'Sales demo portal' },
|
|
5
|
+
{ repo: 'administration', label: 'Administration' },
|
|
6
|
+
{ repo: 'nginx', label: 'NGINX One' },
|
|
7
|
+
{ repo: 'observability', label: 'Observability' },
|
|
8
|
+
{ repo: 'statistics', label: 'Statistics' },
|
|
9
|
+
{ repo: 'was', label: 'Web App Scanning' },
|
|
10
|
+
{ repo: 'multi-cloud-networking', label: 'Multi-Cloud Networking' },
|
|
11
|
+
{ repo: 'canada', label: 'Canada topology' },
|
|
12
|
+
{ repo: 'dns', label: 'DNS Management' },
|
|
13
|
+
{ repo: 'cdn', label: 'Content Delivery Network' },
|
|
14
|
+
{ repo: 'bot-standard', label: 'Bot Defense Standard' },
|
|
15
|
+
{ repo: 'bot-advanced', label: 'Bot Defense Advanced' },
|
|
16
|
+
{ repo: 'ddos', label: 'DDoS Mitigation' },
|
|
17
|
+
{ repo: 'webapp-api-protection', label: 'Web App & API Protection' },
|
|
18
|
+
{ repo: 'api-protection', label: 'API Protection' },
|
|
19
|
+
{ repo: 'xcsh', label: 'xcsh' },
|
|
20
|
+
{ repo: 'xcsh-action', label: 'xcsh GitHub Action' },
|
|
21
|
+
{ repo: 'csd', label: 'Client-Side Defense' },
|
|
22
|
+
{ repo: 'docs-icons', label: 'Icon packages' },
|
|
23
|
+
{ repo: 'marketplace', label: 'xcsh marketplace' },
|
|
24
|
+
{ repo: 'api-specs', label: 'API specifications' },
|
|
25
|
+
{ repo: 'api-specs-enriched', label: 'Enriched API specifications' },
|
|
26
|
+
{ repo: 'cdn-simulator', label: 'CDN simulator' },
|
|
27
|
+
{ repo: 'origin-server', label: 'Origin server' },
|
|
28
|
+
{ repo: 'traffic-generator', label: 'Traffic generator' },
|
|
29
|
+
{ repo: 'demo-resources', label: 'Demo resource catalog' },
|
|
30
|
+
{ repo: 'xcsh-chrome-extension', label: 'xcsh Chrome extension' },
|
|
31
|
+
{ repo: 'console', label: 'Console catalog' },
|
|
32
|
+
];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { expect, it } from 'vitest';
|
|
2
|
+
import { searchSource } from './search-source';
|
|
3
|
+
|
|
4
|
+
it('identifies the source project of federated results and root catalog pages', () => {
|
|
5
|
+
const sources = [{ repo: 'origin-server', label: 'Origin server' }];
|
|
6
|
+
expect(searchSource('https://f5-sales-demo.github.io/origin-server/en/03-deploy/', sources)).toBe('Origin server');
|
|
7
|
+
expect(searchSource('https://f5-sales-demo.github.io/en/demos/', sources)).toBe('Sales demo portal');
|
|
8
|
+
expect(searchSource('https://example.com/docs/', sources)).toBeUndefined();
|
|
9
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function searchSource(href: string, sources: Array<{ repo: string; label: string }>): string | undefined {
|
|
2
|
+
let url: URL;
|
|
3
|
+
try {
|
|
4
|
+
url = new URL(href);
|
|
5
|
+
} catch {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
if (url.hostname !== 'f5-sales-demo.github.io') return undefined;
|
|
9
|
+
const project = url.pathname.split('/').filter(Boolean)[0];
|
|
10
|
+
return sources.find((source) => source.repo === project)?.label ?? 'Sales demo portal';
|
|
11
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { defaultMegaMenuItems } from '../../config';
|
|
3
|
+
import { localizeEcosystemHref } from './localize-ecosystem-href';
|
|
4
|
+
|
|
5
|
+
describe('showcase navigation', () => {
|
|
6
|
+
it('uses the audience taxonomy without duplicate project destinations', () => {
|
|
7
|
+
expect(defaultMegaMenuItems.map((item) => item.label)).toEqual([
|
|
8
|
+
'Demos',
|
|
9
|
+
'Demo environment',
|
|
10
|
+
'Operations',
|
|
11
|
+
'Developer tools',
|
|
12
|
+
'Ecosystem',
|
|
13
|
+
'F5 services',
|
|
14
|
+
]);
|
|
15
|
+
const links = defaultMegaMenuItems.flatMap((item) => item.content?.categories?.flatMap((c) => c.items) ?? []);
|
|
16
|
+
const urls = links.map((item) => item.href);
|
|
17
|
+
expect(new Set(urls).size).toBe(urls.length);
|
|
18
|
+
expect(urls).not.toContain('https://f5-sales-demo.github.io/');
|
|
19
|
+
expect(links.find((l) => l.href.includes('/api-protection/'))?.label).toBe('API Protection');
|
|
20
|
+
expect(links.find((l) => l.href.includes('/ddos/'))?.label).toBe('DDoS Mitigation');
|
|
21
|
+
expect(defaultMegaMenuItems[1].content?.footer?.label).toBe('Demo resource catalog');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('keeps explicit English catalog destinations valid across locale selection', () => {
|
|
25
|
+
for (const locale of ['en', 'fr', 'ar']) {
|
|
26
|
+
expect(localizeEcosystemHref('https://f5-sales-demo.github.io/en/demos/', locale)).toBe(
|
|
27
|
+
'https://f5-sales-demo.github.io/en/demos/',
|
|
28
|
+
);
|
|
29
|
+
expect(localizeEcosystemHref('https://f5-sales-demo.github.io/en/ecosystem/', locale)).toBe(
|
|
30
|
+
'https://f5-sales-demo.github.io/en/ecosystem/',
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -4,15 +4,15 @@ import { localizeEcosystemHref } from './localize-ecosystem-href';
|
|
|
4
4
|
|
|
5
5
|
describe('Statistics discovery', () => {
|
|
6
6
|
it('lists Statistics beside monitoring tools exactly once', () => {
|
|
7
|
-
const networking = defaultMegaMenuItems.find((item) => item.label === '
|
|
8
|
-
const category = networking?.content?.categories?.find((item) => item.title === '
|
|
7
|
+
const networking = defaultMegaMenuItems.find((item) => item.label === 'Operations');
|
|
8
|
+
const category = networking?.content?.categories?.find((item) => item.title === 'Queries and administration');
|
|
9
9
|
const statistics = category?.items?.filter((item) => item.label === 'Statistics');
|
|
10
10
|
expect(statistics).toHaveLength(1);
|
|
11
11
|
expect(statistics?.[0]).toMatchObject({
|
|
12
12
|
href: 'https://f5-sales-demo.github.io/statistics/en/',
|
|
13
|
-
description: '
|
|
13
|
+
description: 'Query access logs, application metrics, and security telemetry through the API.',
|
|
14
14
|
});
|
|
15
|
-
expect(category?.items?.map((item) => item.label)).toEqual(['
|
|
15
|
+
expect(category?.items?.map((item) => item.label)).toEqual(['Statistics', 'Observability', 'Administration']);
|
|
16
16
|
});
|
|
17
17
|
it('adds Statistics to federated search and avoids self-index duplication', () => {
|
|
18
18
|
expect(federatedSearchSites.filter((item) => item.repo === 'statistics')).toHaveLength(1);
|
package/styles/custom.css
CHANGED
|
@@ -873,3 +873,33 @@ summary:focus-visible {
|
|
|
873
873
|
}
|
|
874
874
|
}
|
|
875
875
|
|
|
876
|
+
|
|
877
|
+
/* The sales showcase prioritizes destinations over decorative hero space. */
|
|
878
|
+
body:has(.sales-showcase) .hero {
|
|
879
|
+
padding-block: 1rem;
|
|
880
|
+
grid-template-columns: 1fr;
|
|
881
|
+
gap: 1rem;
|
|
882
|
+
}
|
|
883
|
+
body:has(.sales-showcase) .hero h1 {
|
|
884
|
+
font-size: clamp(1.75rem, 5vw, 3rem);
|
|
885
|
+
}
|
|
886
|
+
body:has(.sales-showcase) .hero .tagline {
|
|
887
|
+
max-width: 48rem;
|
|
888
|
+
font-size: var(--sl-text-lg);
|
|
889
|
+
}
|
|
890
|
+
body:has(.sales-showcase) .hero > .stack { gap: 1rem; }
|
|
891
|
+
body:has(.sales-showcase) .hero .actions { gap: 0.75rem; }
|
|
892
|
+
.sales-showcase { --showcase-gap: 1rem; }
|
|
893
|
+
.sales-showcase .card-grid { gap: var(--showcase-gap); }
|
|
894
|
+
.sales-showcase .sl-link-card { background: var(--sl-color-gray-7, var(--sl-color-gray-6)); }
|
|
895
|
+
.sales-showcase h2 { margin-block-start: 2rem; }
|
|
896
|
+
.sales-showcase h3 { margin-block-start: 1rem; }
|
|
897
|
+
@media (max-width: 49.99rem) {
|
|
898
|
+
body:has(.sales-showcase) .hero { padding-block: 0.5rem; }
|
|
899
|
+
body:has(.sales-showcase) .hero .actions { flex-wrap: wrap; }
|
|
900
|
+
}
|
|
901
|
+
@media (prefers-reduced-motion: reduce) {
|
|
902
|
+
*, *::before, *::after { scroll-behavior: auto !important; }
|
|
903
|
+
.sl-link-card, .smm-viewport, .smm-content { transition: none !important; animation: none !important; }
|
|
904
|
+
.sl-link-card:hover { transform: none; }
|
|
905
|
+
}
|