@ampernic/vitepress-theme-alt-docs 0.1.22 → 0.1.24
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/dist/components/ADGlobalSearch.vue +145 -25
- package/dist/components/ADProducts.vue +7 -1
- package/dist/components/ADProductsSidebar.vue +21 -5
- package/dist/components/ADSearch.vue +2 -0
- package/dist/index.mjs +26 -1
- package/dist/productNames.d.ts +2 -0
- package/dist/productNames.mjs +29 -0
- package/package.json +6 -5
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { onKeyStroke, useScrollLock } from '@vueuse/core'
|
|
3
3
|
import { useRouter } from 'vitepress'
|
|
4
|
-
import { nextTick, onMounted, onUnmounted, ref, shallowRef, watch } from 'vue'
|
|
4
|
+
import { computed, nextTick, onMounted, onUnmounted, ref, shallowRef, watch } from 'vue'
|
|
5
5
|
|
|
6
6
|
// ── Dropdown ──────────────────────────────────────────────────────────────────
|
|
7
7
|
|
|
@@ -175,17 +175,65 @@ interface ResultData {
|
|
|
175
175
|
excerpt: string
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
interface ResultStub { data: () => Promise<ResultData> }
|
|
179
|
+
|
|
180
|
+
const PAGE_SIZE = 10
|
|
181
|
+
|
|
178
182
|
const query = ref('')
|
|
179
183
|
const selectedIndex = ref(0)
|
|
180
184
|
const results = ref<ResultData[]>([])
|
|
181
185
|
const searching = ref(false)
|
|
182
186
|
|
|
187
|
+
// All relevance-ranked hits (lazy stubs); the visible page is loaded on
|
|
188
|
+
// demand so results are never truncated.
|
|
189
|
+
const stubs = shallowRef<ResultStub[]>([])
|
|
190
|
+
const total = ref(0)
|
|
191
|
+
const page = ref(1)
|
|
192
|
+
const pageCount = computed(() => Math.max(1, Math.ceil(total.value / PAGE_SIZE)))
|
|
193
|
+
const pageItems = computed<(number | '…')[]>(() => {
|
|
194
|
+
const n = pageCount.value
|
|
195
|
+
const c = page.value
|
|
196
|
+
if (n <= 7) return Array.from({ length: n }, (_, i) => i + 1)
|
|
197
|
+
const items: (number | '…')[] = [1]
|
|
198
|
+
const lo = Math.max(2, c - 1)
|
|
199
|
+
const hi = Math.min(n - 1, c + 1)
|
|
200
|
+
if (lo > 2) items.push('…')
|
|
201
|
+
for (let i = lo; i <= hi; i++) items.push(i)
|
|
202
|
+
if (hi < n - 1) items.push('…')
|
|
203
|
+
items.push(n)
|
|
204
|
+
return items
|
|
205
|
+
})
|
|
206
|
+
|
|
183
207
|
let searchTimer: ReturnType<typeof setTimeout> | null = null
|
|
208
|
+
let loadToken = 0
|
|
209
|
+
|
|
210
|
+
async function loadPage() {
|
|
211
|
+
const token = ++loadToken
|
|
212
|
+
const start = (page.value - 1) * PAGE_SIZE
|
|
213
|
+
const data = await Promise.all(
|
|
214
|
+
stubs.value.slice(start, start + PAGE_SIZE).map((r) => r.data()),
|
|
215
|
+
)
|
|
216
|
+
if (token !== loadToken) return
|
|
217
|
+
results.value = data
|
|
218
|
+
selectedIndex.value = 0
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function goPage(p: number) {
|
|
222
|
+
const next = Math.min(Math.max(1, p), pageCount.value)
|
|
223
|
+
if (next !== page.value) page.value = next
|
|
224
|
+
}
|
|
225
|
+
function nextPage() { goPage(page.value + 1) }
|
|
226
|
+
function prevPage() { goPage(page.value - 1) }
|
|
227
|
+
|
|
228
|
+
watch(page, () => { if (stubs.value.length) loadPage() })
|
|
184
229
|
|
|
185
230
|
watch([query, selectedDistro, selectedVersion], () => {
|
|
186
231
|
selectedIndex.value = 0
|
|
232
|
+
page.value = 1
|
|
187
233
|
if (searchTimer) clearTimeout(searchTimer)
|
|
188
234
|
if (!query.value.trim() || !pagefind.value) {
|
|
235
|
+
stubs.value = []
|
|
236
|
+
total.value = 0
|
|
189
237
|
results.value = []
|
|
190
238
|
searching.value = false
|
|
191
239
|
return
|
|
@@ -196,9 +244,11 @@ watch([query, selectedDistro, selectedVersion], () => {
|
|
|
196
244
|
if (selectedDistro.value) f.distro = selectedDistro.value
|
|
197
245
|
if (selectedVersion.value) f.version = selectedVersion.value
|
|
198
246
|
const search = await pagefind.value.search(query.value, Object.keys(f).length ? { filters: f } : {})
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
247
|
+
// Keep pagefind's relevance order; paginate instead of truncating.
|
|
248
|
+
stubs.value = search.results as ResultStub[]
|
|
249
|
+
total.value = search.results.length
|
|
250
|
+
page.value = 1
|
|
251
|
+
await loadPage()
|
|
202
252
|
searching.value = false
|
|
203
253
|
}, 200)
|
|
204
254
|
})
|
|
@@ -324,28 +374,46 @@ function onOverlayClick(e: MouseEvent) { if (e.target === e.currentTarget) close
|
|
|
324
374
|
</div>
|
|
325
375
|
|
|
326
376
|
<!-- Results -->
|
|
327
|
-
<
|
|
328
|
-
<
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
377
|
+
<template v-if="results.length">
|
|
378
|
+
<div class="gs-meta">
|
|
379
|
+
<span>{{ total }} результатов</span>
|
|
380
|
+
<span v-if="pageCount > 1">{{ page }} / {{ pageCount }}</span>
|
|
381
|
+
</div>
|
|
382
|
+
<ul class="gs-results">
|
|
383
|
+
<li
|
|
384
|
+
v-for="(result, i) in results"
|
|
385
|
+
:key="result.url"
|
|
386
|
+
class="gs-result"
|
|
387
|
+
:class="{ 'is-selected': i === selectedIndex }"
|
|
388
|
+
@mouseenter="selectedIndex = i"
|
|
389
|
+
@click="go(result.url)"
|
|
390
|
+
>
|
|
391
|
+
<div class="gs-result-header">
|
|
392
|
+
<span class="gs-result-title">{{ result.meta.title }}</span>
|
|
393
|
+
<span v-if="parseUrl(result.url)" class="gs-result-badges">
|
|
394
|
+
<span class="gs-badge gs-badge--distro">
|
|
395
|
+
{{ DISTRO_NAMES[parseUrl(result.url)!.distro] ?? parseUrl(result.url)!.distro }}
|
|
396
|
+
</span>
|
|
397
|
+
<span class="gs-badge gs-badge--version">{{ parseUrl(result.url)!.version }}</span>
|
|
341
398
|
</span>
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
399
|
+
</div>
|
|
400
|
+
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
401
|
+
<div class="gs-result-excerpt" v-html="result.excerpt" />
|
|
402
|
+
</li>
|
|
403
|
+
</ul>
|
|
404
|
+
<nav v-if="pageCount > 1" class="gs-pagination" aria-label="Pagination">
|
|
405
|
+
<button class="gs-page-btn" :disabled="page === 1" aria-label="Назад" @click="prevPage">‹</button>
|
|
406
|
+
<button
|
|
407
|
+
v-for="(it, idx) in pageItems"
|
|
408
|
+
:key="idx"
|
|
409
|
+
class="gs-page-btn"
|
|
410
|
+
:class="{ 'is-active': it === page }"
|
|
411
|
+
:disabled="it === '…'"
|
|
412
|
+
@click="typeof it === 'number' && goPage(it)"
|
|
413
|
+
>{{ it }}</button>
|
|
414
|
+
<button class="gs-page-btn" :disabled="page === pageCount" aria-label="Вперёд" @click="nextPage">›</button>
|
|
415
|
+
</nav>
|
|
416
|
+
</template>
|
|
349
417
|
|
|
350
418
|
<div v-else-if="indexLoading" class="gs-status">
|
|
351
419
|
<span class="gs-spinner" />
|
|
@@ -541,6 +609,17 @@ function onOverlayClick(e: MouseEvent) { if (e.target === e.currentTarget) close
|
|
|
541
609
|
font-weight: 500;
|
|
542
610
|
}
|
|
543
611
|
|
|
612
|
+
.gs-meta {
|
|
613
|
+
display: flex;
|
|
614
|
+
justify-content: space-between;
|
|
615
|
+
gap: 12px;
|
|
616
|
+
padding: 8px 16px;
|
|
617
|
+
border-bottom: 1px solid var(--vp-c-divider);
|
|
618
|
+
font-size: 12px;
|
|
619
|
+
color: var(--vp-c-text-3);
|
|
620
|
+
flex-shrink: 0;
|
|
621
|
+
}
|
|
622
|
+
|
|
544
623
|
.gs-results {
|
|
545
624
|
overflow-y: auto;
|
|
546
625
|
list-style: none;
|
|
@@ -549,6 +628,47 @@ function onOverlayClick(e: MouseEvent) { if (e.target === e.currentTarget) close
|
|
|
549
628
|
flex: 1;
|
|
550
629
|
}
|
|
551
630
|
|
|
631
|
+
.gs-pagination {
|
|
632
|
+
display: flex;
|
|
633
|
+
flex-wrap: wrap;
|
|
634
|
+
gap: 4px;
|
|
635
|
+
justify-content: center;
|
|
636
|
+
padding: 8px 16px;
|
|
637
|
+
border-top: 1px solid var(--vp-c-divider);
|
|
638
|
+
flex-shrink: 0;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
.gs-page-btn {
|
|
642
|
+
min-width: 28px;
|
|
643
|
+
height: 28px;
|
|
644
|
+
padding: 0 6px;
|
|
645
|
+
border: 1px solid var(--vp-c-divider);
|
|
646
|
+
border-radius: 6px;
|
|
647
|
+
background: transparent;
|
|
648
|
+
color: var(--vp-c-text-2);
|
|
649
|
+
font-size: 13px;
|
|
650
|
+
cursor: pointer;
|
|
651
|
+
transition: background 0.1s, border-color 0.1s, color 0.1s;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
.gs-page-btn:hover:not(:disabled):not(.is-active) {
|
|
655
|
+
border-color: var(--vp-c-brand-1);
|
|
656
|
+
color: var(--vp-c-brand-1);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
.gs-page-btn.is-active {
|
|
660
|
+
background: var(--vp-c-brand-1);
|
|
661
|
+
border-color: var(--vp-c-brand-1);
|
|
662
|
+
color: var(--vp-c-bg);
|
|
663
|
+
font-weight: 600;
|
|
664
|
+
cursor: default;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
.gs-page-btn:disabled {
|
|
668
|
+
opacity: 0.45;
|
|
669
|
+
cursor: default;
|
|
670
|
+
}
|
|
671
|
+
|
|
552
672
|
.gs-result {
|
|
553
673
|
padding: 8px 12px;
|
|
554
674
|
border-radius: 8px;
|
|
@@ -77,9 +77,15 @@ const hasLangPrefix = computed(
|
|
|
77
77
|
* mode where the distro name is encoded in the VitePress `base` and absent
|
|
78
78
|
* from route.path.
|
|
79
79
|
*/
|
|
80
|
+
// A version segment is `\d+.\d+...` OR a platform dir `pN` (p10/p11).
|
|
81
|
+
// Without the pN case, pN distros (alt-admin, Nets-Laboratories) were
|
|
82
|
+
// treated as multi-distro mode and currentProduct became "p11", so the
|
|
83
|
+
// products dropdown showed "P11" instead of the distribution name.
|
|
84
|
+
const isVersionSeg = (s: string) => /^(\d+\.\d+(\.\d+)*|p\d+)$/.test(s)
|
|
85
|
+
|
|
80
86
|
const isPerDistroMode = computed(() => {
|
|
81
87
|
const parts = pathParts.value
|
|
82
|
-
return parts.length === 0 ||
|
|
88
|
+
return parts.length === 0 || isVersionSeg(parts[0])
|
|
83
89
|
})
|
|
84
90
|
|
|
85
91
|
const currentProduct = computed<string | null>(() => {
|
|
@@ -20,7 +20,13 @@ import { computed, ref, onMounted } from 'vue'
|
|
|
20
20
|
import { useRoute, useData } from 'vitepress'
|
|
21
21
|
|
|
22
22
|
interface DistroInfo { versions: string[]; latest: string; title?: string }
|
|
23
|
-
|
|
23
|
+
// Sections come in two shapes: a group `{name, distros:[...]}` or a flat
|
|
24
|
+
// top-level item `{name, distro:<slug>}`. Handling only `distros` made
|
|
25
|
+
// `section.distros.filter` throw on flat entries, crashing the whole
|
|
26
|
+
// products sidebar (blank sidebar on every distro landing).
|
|
27
|
+
interface SectionInfo { name: string; distros?: string[]; distro?: string }
|
|
28
|
+
const sectionDistros = (s: SectionInfo): string[] =>
|
|
29
|
+
s.distros ?? (s.distro ? [s.distro] : [])
|
|
24
30
|
declare const __VERSIONS_DATA__: {
|
|
25
31
|
distros: { [distroName: string]: DistroInfo }
|
|
26
32
|
sections?: SectionInfo[]
|
|
@@ -59,6 +65,12 @@ const PRODUCT_NAMES: Record<string, string> = {
|
|
|
59
65
|
'simply-linux': 'Симпли Линукс',
|
|
60
66
|
'simply-linux-e2k': 'Симпли Линукс для Эльбрус',
|
|
61
67
|
'group-policy': 'Групповые политики',
|
|
68
|
+
'alt-domain-p10': 'Альт Домен (p10)',
|
|
69
|
+
'alt-admin': 'Администрирование Альт',
|
|
70
|
+
'alt-platform-practic': 'Альт Платформа Практик',
|
|
71
|
+
'freeipa-p10': 'FreeIPA (p10)',
|
|
72
|
+
'freeipa-p11': 'FreeIPA (p11)',
|
|
73
|
+
'Nets-Laboratories': 'Лабораторные работы',
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
const productName = (d: string) =>
|
|
@@ -75,10 +87,14 @@ const contentPath = computed(() => {
|
|
|
75
87
|
return base.length > 1 && p.startsWith(base) ? p.slice(base.length - 1) : p
|
|
76
88
|
})
|
|
77
89
|
|
|
78
|
-
// Show
|
|
90
|
+
// Show ONLY on the distro landing (path is exactly the distro root, no
|
|
91
|
+
// segment). The old heuristic `!/^\d+\.\d+/.test(parts[0])` mis-fired for
|
|
92
|
+
// pN version dirs (p10/p11): every p11 content page looked like a landing,
|
|
93
|
+
// so the products sidebar rendered on top of the doc sidebar (two
|
|
94
|
+
// sidebars on alt-admin etc.). The landing is unambiguously parts.length===0.
|
|
79
95
|
const isLandingPage = computed(() => {
|
|
80
96
|
const parts = contentPath.value.split('/').filter(Boolean)
|
|
81
|
-
return parts.length === 0
|
|
97
|
+
return parts.length === 0
|
|
82
98
|
})
|
|
83
99
|
|
|
84
100
|
// Current distro is encoded in the base in per-distro mode
|
|
@@ -92,7 +108,7 @@ interface SidebarGroup { title: string; distros: string[] }
|
|
|
92
108
|
const groups = computed((): SidebarGroup[] => {
|
|
93
109
|
const allDistros = Object.keys(versionsData.distros)
|
|
94
110
|
const sections = versionsData.sections ?? []
|
|
95
|
-
const sectionedSet = new Set(sections.flatMap(
|
|
111
|
+
const sectionedSet = new Set(sections.flatMap(sectionDistros))
|
|
96
112
|
|
|
97
113
|
const unsectioned = allDistros.filter(d => !sectionedSet.has(d))
|
|
98
114
|
const regular = unsectioned.filter(d => !d.endsWith('-e2k'))
|
|
@@ -105,7 +121,7 @@ const groups = computed((): SidebarGroup[] => {
|
|
|
105
121
|
}
|
|
106
122
|
|
|
107
123
|
for (const section of sections) {
|
|
108
|
-
const distros = section.
|
|
124
|
+
const distros = sectionDistros(section).filter((d: string) => allDistros.includes(d))
|
|
109
125
|
if (distros.length > 0) {
|
|
110
126
|
result.push({ title: section.name, distros })
|
|
111
127
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -19,17 +19,42 @@ import ADInlineImage from "./components/ADInlineImage.vue";
|
|
|
19
19
|
import ADAssetLink from "./components/ADAssetLink.vue";
|
|
20
20
|
import ADNavBarSearch from "./components/ADNavBarSearch.vue";
|
|
21
21
|
import ExportButton from "@ampernic/vitepress-plugin-export/components/ExportButton.vue";
|
|
22
|
+
import Breadcrumbs from "@ampernic/vitepress-plugin-breadcrumbs/components/Breadcrumbs.vue";
|
|
23
|
+
import { productName } from "./productNames.mjs";
|
|
22
24
|
import "./styles/theme.css";
|
|
23
25
|
import "./styles/custom.css";
|
|
24
26
|
import "./styles/icons.css";
|
|
25
27
|
import "./styles/print.css";
|
|
28
|
+
function breadcrumbsHome(ctx) {
|
|
29
|
+
if (!ctx.distro) return false;
|
|
30
|
+
const name = productName(ctx.distro);
|
|
31
|
+
const text = ctx.version && /^\d/.test(ctx.version) ? `${name} ${ctx.version}` : name;
|
|
32
|
+
return { text, link: ctx.landing };
|
|
33
|
+
}
|
|
34
|
+
function breadcrumbsPrefix(ctx) {
|
|
35
|
+
const arr = [{ text: "\u0413\u043B\u0430\u0432\u043D\u0430\u044F", link: "/" }];
|
|
36
|
+
if (ctx.distro && ctx.version && /^\d/.test(ctx.version)) {
|
|
37
|
+
arr.push({ text: productName(ctx.distro), link: `/${ctx.distro}/` });
|
|
38
|
+
}
|
|
39
|
+
return arr;
|
|
40
|
+
}
|
|
26
41
|
export const Theme = {
|
|
27
42
|
Layout: () => h(DefaultTheme.Layout, null, {
|
|
28
43
|
"nav-bar-content-before": () => h(ADNavBarSearch),
|
|
29
44
|
"nav-bar-content-after": () => h(NolebaseEnhancedReadabilitiesMenu),
|
|
30
45
|
"nav-screen-content-after": () => h(NolebaseEnhancedReadabilitiesScreenMenu),
|
|
31
46
|
"sidebar-nav-before": () => h(ADProductsSidebar),
|
|
32
|
-
|
|
47
|
+
// Dynamic breadcrumbs above the page content (standalone package).
|
|
48
|
+
// `home` resolver adds a root crumb linking back to the document
|
|
49
|
+
// landing so the full path up to the index is always reachable.
|
|
50
|
+
"doc-before": () => h(Breadcrumbs, {
|
|
51
|
+
home: breadcrumbsHome,
|
|
52
|
+
prefix: breadcrumbsPrefix,
|
|
53
|
+
showOnHome: true,
|
|
54
|
+
hideSingle: false
|
|
55
|
+
}),
|
|
56
|
+
// Above the outline ("Оглавление"), per request.
|
|
57
|
+
"aside-outline-before": () => h(ExportButton)
|
|
33
58
|
}),
|
|
34
59
|
enhanceApp({ app, router, siteData }) {
|
|
35
60
|
installCrossSiteRouter(router, siteData);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const PRODUCT_NAMES = {
|
|
2
|
+
"alt-domain": "\u0410\u043B\u044C\u0442 \u0414\u043E\u043C\u0435\u043D",
|
|
3
|
+
"alt-education": "\u0410\u043B\u044C\u0442 \u041E\u0431\u0440\u0430\u0437\u043E\u0432\u0430\u043D\u0438\u0435",
|
|
4
|
+
"alt-education-e2k": "\u0410\u043B\u044C\u0442 \u041E\u0431\u0440\u0430\u0437\u043E\u0432\u0430\u043D\u0438\u0435 \u0434\u043B\u044F \u042D\u043B\u044C\u0431\u0440\u0443\u0441",
|
|
5
|
+
"alt-server": "\u0410\u043B\u044C\u0442 \u0421\u0435\u0440\u0432\u0435\u0440",
|
|
6
|
+
"alt-server-e2k": "\u0410\u043B\u044C\u0442 \u0421\u0435\u0440\u0432\u0435\u0440 \u0434\u043B\u044F \u042D\u043B\u044C\u0431\u0440\u0443\u0441",
|
|
7
|
+
"alt-server-v": "\u0410\u043B\u044C\u0442 \u0421\u0435\u0440\u0432\u0435\u0440 \u0412\u0438\u0440\u0442\u0443\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u0438",
|
|
8
|
+
"alt-workstation": "\u0410\u043B\u044C\u0442 \u0420\u0430\u0431\u043E\u0447\u0430\u044F \u0441\u0442\u0430\u043D\u0446\u0438\u044F",
|
|
9
|
+
"alt-workstation-e2k": "\u0410\u043B\u044C\u0442 \u0420\u0430\u0431\u043E\u0447\u0430\u044F \u0441\u0442\u0430\u043D\u0446\u0438\u044F \u0434\u043B\u044F \u042D\u043B\u044C\u0431\u0440\u0443\u0441",
|
|
10
|
+
"alt-kworkstation": "\u0410\u043B\u044C\u0442 \u0420\u0430\u0431\u043E\u0447\u0430\u044F \u0441\u0442\u0430\u043D\u0446\u0438\u044F K",
|
|
11
|
+
"alt-platform": "\u0410\u043B\u044C\u0442 \u041F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u0430",
|
|
12
|
+
"alt-mobile": "\u0410\u043B\u044C\u0442 \u041C\u043E\u0431\u0438\u043B\u044C\u043D\u044B\u0439",
|
|
13
|
+
"alt-virtualisation-one": "\u0410\u043B\u044C\u0442 \u0412\u0438\u0440\u0442\u0443\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u044F ONE",
|
|
14
|
+
"alt-virtualization-pve": "\u0410\u043B\u044C\u0442 \u0412\u0438\u0440\u0442\u0443\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u044F PVE",
|
|
15
|
+
"simply-linux": "\u0421\u0438\u043C\u043F\u043B\u0438 \u041B\u0438\u043D\u0443\u043A\u0441",
|
|
16
|
+
"simply-linux-e2k": "\u0421\u0438\u043C\u043F\u043B\u0438 \u041B\u0438\u043D\u0443\u043A\u0441 \u0434\u043B\u044F \u042D\u043B\u044C\u0431\u0440\u0443\u0441",
|
|
17
|
+
"group-policy": "\u0413\u0440\u0443\u043F\u043F\u043E\u0432\u044B\u0435 \u043F\u043E\u043B\u0438\u0442\u0438\u043A\u0438",
|
|
18
|
+
"alt-domain-p10": "\u0410\u043B\u044C\u0442 \u0414\u043E\u043C\u0435\u043D (p10)",
|
|
19
|
+
"alt-admin": "\u0410\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 \u0410\u043B\u044C\u0442",
|
|
20
|
+
"alt-platform-practic": "\u0410\u043B\u044C\u0442 \u041F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u0430 \u041F\u0440\u0430\u043A\u0442\u0438\u043A",
|
|
21
|
+
"freeipa-p10": "FreeIPA (p10)",
|
|
22
|
+
"freeipa-p11": "FreeIPA (p11)",
|
|
23
|
+
"Nets-Laboratories": "\u041B\u0430\u0431\u043E\u0440\u0430\u0442\u043E\u0440\u043D\u044B\u0435 \u0440\u0430\u0431\u043E\u0442\u044B"
|
|
24
|
+
};
|
|
25
|
+
export function productName(slug) {
|
|
26
|
+
return PRODUCT_NAMES[slug] ?? slug.split("-").map(
|
|
27
|
+
(w) => w === "alt" ? "ALT" : w === "e2k" ? "E2K" : w.charAt(0).toUpperCase() + w.slice(1)
|
|
28
|
+
).join(" ");
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ampernic/vitepress-theme-alt-docs",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.24",
|
|
4
4
|
"description": "Shared VitePress theme for ALT Linux documentation",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"author": "Ampernic",
|
|
@@ -27,17 +27,18 @@
|
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"vitepress": "^1.0.0",
|
|
29
29
|
"vue": "^3.0.0",
|
|
30
|
-
"@ampernic/vitepress-plugin-export": "^0.1.
|
|
30
|
+
"@ampernic/vitepress-plugin-export": "^0.1.39"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@alt-gnome/markdown-it-custom-containers": "^1.0.0",
|
|
34
34
|
"@nolebase/vitepress-plugin-enhanced-readabilities": "^2.14.0",
|
|
35
35
|
"markdown-it-kbd": "^1.0.0",
|
|
36
36
|
"vitepress-plugin-tabs": "^0.6.0",
|
|
37
|
+
"@ampernic/vitepress-plugin-alt-docs-versioning": "0.1.10",
|
|
38
|
+
"@ampernic/vitepress-plugin-breadcrumbs": "0.1.0",
|
|
37
39
|
"@ampernic/vitepress-plugin-cross-site-router": "0.1.2",
|
|
38
|
-
"@ampernic/vitepress-plugin-
|
|
39
|
-
"@ampernic/vitepress-plugin-pagefind": "0.1.
|
|
40
|
-
"@ampernic/vitepress-plugin-html-image": "0.1.2"
|
|
40
|
+
"@ampernic/vitepress-plugin-html-image": "0.1.2",
|
|
41
|
+
"@ampernic/vitepress-plugin-pagefind": "0.1.9"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
44
|
"builtin-modules": "^3.3.0",
|