Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c0f94d4ea7 |
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "docs",
|
"name": "docs",
|
||||||
"version": "0.6.4-link",
|
"version": "0.6.5-main",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "docs",
|
"name": "docs",
|
||||||
"version": "0.6.4-link",
|
"version": "0.6.5-main",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@beeline/design-tokens": "^1.31.6",
|
"@beeline/design-tokens": "^1.31.6",
|
||||||
|
|||||||
+236
-236
@@ -2,7 +2,7 @@ import { defineConfig } from 'vitepress'
|
|||||||
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
|
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
|
||||||
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
||||||
import { overrideComponents } from './override-components'
|
import { overrideComponents } from './override-components'
|
||||||
import { resolve } from 'path'
|
import { resolve } from 'node:path'
|
||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
|
|
||||||
const gitlab = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
const gitlab = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
@@ -41,240 +41,7 @@ const gitlab = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|||||||
`
|
`
|
||||||
|
|
||||||
const new_version = process.env?.VITE_NEW_VERSION;
|
const new_version = process.env?.VITE_NEW_VERSION;
|
||||||
|
console.log({ base: typeof new_version !== 'undefined' ? '/' : '/docs/' })
|
||||||
const sidebarConfig = {
|
|
||||||
'/platform/': [
|
|
||||||
{
|
|
||||||
text: 'Платформа Beeline Cloud', link: '/platform/index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Обзор', link: '/platform/about.md'},
|
|
||||||
{text: 'Техническая поддержка', link: '/platform/support/support-overview.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'/start/': [
|
|
||||||
{
|
|
||||||
text: 'Начало работы в Beeline Cloud', link: '/start/index.md',
|
|
||||||
},
|
|
||||||
{text: 'Начать работу', link: '/start/getting-started.md'},
|
|
||||||
{text: 'Бесплатный период', link: '/start/trial.md'},
|
|
||||||
{text: 'Платное использование', link: '/start/organization.md'},
|
|
||||||
],
|
|
||||||
// '/billing/': [
|
|
||||||
|
|
||||||
// ],
|
|
||||||
'/backups/': [
|
|
||||||
{
|
|
||||||
text: 'Резервное копирование', link: '/backups/index.md',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Обзор сервиса', link: '/backups/about.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Квоты и лимиты', link: '/backups/backup-quatos.md'},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{text: 'Резервное копирование виртуальных машин Beeline Cloud', link: '/backups/backup-internal-infra.md'},
|
|
||||||
{text: 'Резервное копирование собственной инфраструктуры в Beeline Cloud', link: '/backups/backup-external-infra.md'},
|
|
||||||
{text: 'Каталог резервных копий', link: '/backups/view-backups.md'},
|
|
||||||
|
|
||||||
],
|
|
||||||
'/vdc/': [
|
|
||||||
{
|
|
||||||
text: 'Виртуальные дата-центры на VMware', link: '/vdc/index.md',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Обзор сервиса', link: '/vdc/vdc-overview.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'О сервисе', link: '/vdc/vdc-about.md' },
|
|
||||||
{ text: 'Техническое описание', link: '/vdc/vdc-tech.md' },
|
|
||||||
{ text: 'Квоты и лимиты', link: '/vdc/vdc-quatos.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Быстрый старт', link: '/vdc/vdc-getting-started.md'
|
|
||||||
},
|
|
||||||
|
|
||||||
{ text: 'Виртуальные дата-центры', link: '/vdc/vdc-how-to/vdc-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Создание дата-центра', link: '/vdc/vdc-how-to/vdc-create.md' },
|
|
||||||
{ text: 'Вход в дата-центр', link: '/vdc/vdc-how-to/vdc-enter.md' },
|
|
||||||
{ text: 'Управление дата-центром', link: '/vdc/vdc-how-to/vdc-manage.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Виртуальные машины', link: '/vdc/vdc-how-to/vm/vm-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Создание ВМ', link: '/vdc/vdc-how-to/vm/create-vm.md'},
|
|
||||||
{text: 'Создание vApp', link: '/vdc/vdc-how-to/vm/create-vapp.md'},
|
|
||||||
{text: 'Управление состоянием ВМ', link: '/vdc/vdc-how-to/vm/manage-vm.md'},
|
|
||||||
{text: 'Клонирование ВМ', link: '/vdc/vdc-how-to/vm/clone-vm.md'},
|
|
||||||
{text: 'Изменение конфигурации ВМ', link: '/vdc/vdc-how-to/vm/edit-vm.md'},
|
|
||||||
{text: 'Удаление ВМ', link: '/vdc/vdc-how-to/vm/delete-vm.md'},
|
|
||||||
{text: 'Группы размещения', link: '/vdc/vdc-how-to/vm/create-affinity-rules.md'},
|
|
||||||
{text: 'Снимки ВМ', link: '/vdc/vdc-how-to/vm/create-snapshot.md'},
|
|
||||||
{text: 'VMware Tools', link: '/vdc/vdc-how-to/vm/vmware-tools.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Диски', link: '/vdc/vdc-how-to/disks/disks-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Обзор', link: '/vdc/vdc-how-to/disks/about.md'},
|
|
||||||
{text: 'Создание диска', link: '/vdc/vdc-how-to/disks/create-disk.md'},
|
|
||||||
{text: 'Проверка состояния диска', link: '/vdc/vdc-how-to/disks/view-disk.md'},
|
|
||||||
{text: 'Управление выделенными дисками', link: '/vdc/vdc-how-to/disks/attach-disk.md'},
|
|
||||||
{text: 'Изменение политики хранения дисков ВМ', link: '/vdc/vdc-how-to/disks/change-storage-policy-of-vm.md'},
|
|
||||||
{text: 'Редактирование параметров диска', link: '/vdc/vdc-how-to/disks/edit-disk.md'},
|
|
||||||
{text: 'Удаление диска', link: '/vdc/vdc-how-to/disks/delete-disk.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Сети', link: '/vdc/vdc-how-to/networks/networks-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Обзор', link: '/vdc/vdc-how-to/networks/about.md'},
|
|
||||||
{text: 'Настройка доступа к ВМ из интернета', link: '/vdc/vdc-how-to/networks/allow-external-connections-to-vm.md'},
|
|
||||||
{text: 'Подключение ВМ в vApp к сети', link: '/vdc/vdc-how-to/networks/connect-vapp-to-network.md'},
|
|
||||||
{text: 'Подключение ВМ к интернету', link: '/vdc/vdc-how-to/networks/connect-vm-to-network.md'},
|
|
||||||
{text: 'Создание сети в организации и подключение к Edge Gateway', link: '/vdc/vdc-how-to/networks/create-network.md'},
|
|
||||||
{text: 'Подключение сети к Edge Gateway', link: '/vdc/vdc-how-to/networks/connect-to-edge-gateway.md'},
|
|
||||||
{text: 'Создание Pre-Shared Key', link: '/vdc/vdc-how-to/networks/create-psk.md'},
|
|
||||||
{ text: 'Настройка site-to-site подключения с помощью IPSec', link: '/vdc/vdc-how-to/networks/how-to-setup-ipsec-vpn.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Настройка ASAv', link: '/vdc/vdc-how-to/networks/ipsec/asav.md'},
|
|
||||||
{text: 'Настройка CSR 1000v', link: '/vdc/vdc-how-to/networks/ipsec/csr1000v.md'},
|
|
||||||
{text: 'Настройка Fortigate', link: '/vdc/vdc-how-to/networks/ipsec/fortigate.md'},
|
|
||||||
{text: 'Проверить сетевую связанность', link: '/vdc/vdc-how-to/networks/ipsec/check-vpn-status.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Пользователи и роли', link: '/vdc/vdc-how-to/users/users-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Ролевая модель', link: '/vdc/vdc-how-to/users/roles.md'},
|
|
||||||
{text: 'Создание пользователя', link: '/vdc/vdc-how-to/users/add-user.md'},
|
|
||||||
{text: 'Изменение пароля пользователя', link: '/vdc/vdc-how-to/users/change-users-password.md'},
|
|
||||||
{text: 'Настройка квот', link: '/vdc/vdc-how-to/users/quotas.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Двухфакторная аутентификация', link: '/vdc/vdc-how-to/vdc-2fa.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Подключение 2FA', link: '/vdc/vdc-how-to/vdc-2fa-start.md'},
|
|
||||||
{text: 'Управление 2FA', link: '/vdc/vdc-how-to/vdc-2fa-manage.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
// { text: 'Тарификация', link: '/vdc/vdc-tarif.md' },
|
|
||||||
'/compute/': [
|
|
||||||
{
|
|
||||||
text: 'Виртуальные машины', link: '/compute/index.md',
|
|
||||||
},
|
|
||||||
{ text: 'Обзор сервиса', link: '/compute/compute-overview-index.md' ,
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Техническое описание', link: '/compute/compute-overview.md' },
|
|
||||||
{ text: 'Квоты и лимиты', link: '/compute/compute-quatos.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{text: 'Быстрый старт', link: '/compute/compute-getting-started.md', excludeFromIndex: true },
|
|
||||||
{ text: 'Виртуальные машины', link: '/compute/compute-how-to/compute-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Создание ВМ', link: '/compute/compute-how-to/compute-servers-create.md' },
|
|
||||||
{ text: 'Создание ВМ джамп-хоста', link: '/compute/compute-how-to/compute-servers-jump-create.md' },
|
|
||||||
{ text: 'Подключение к ВМ', link: '/compute/compute-how-to/compute-connect-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Подключение по SSH по внешнему IP-адресу с помощью ключевой пары', link: '/compute/compute-how-to/compute-connect-public.md'},
|
|
||||||
{ text: 'Подключение по SSH по внутреннему IP-адресу с помощью ключевой пары', link: '/compute/compute-how-to/compute-connect-inside.md' },
|
|
||||||
{ text: 'Подключение по SSH по логину и паролю', link: '/compute/compute-how-to/compute-connect-pwd.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ text: 'Управление ВМ', link: '/compute/compute-how-to/compute-servers-manage.md' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Диски', link: '/compute/compute-how-to/compute-disks/compute-disk-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Обзор', link: '/compute/compute-how-to/compute-disks/compute-disk-about.md' },
|
|
||||||
{ text: 'Создание диска', link: '/compute/compute-how-to/compute-disks/compute-disk-create.md' },
|
|
||||||
{ text: 'Управление дисками', link: '/compute/compute-how-to/compute-disks/compute-disk-manage.md' },
|
|
||||||
{ text: 'Удаление диска', link: '/compute/compute-how-to/compute-disks/compute-disk-del.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ text: 'IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Обзор', link: '/compute/compute-how-to/compute-ip/compute-ip-about.md' },
|
|
||||||
{ text: 'Просмотр IP-адресов', link: '/compute/compute-how-to/compute-ip/compute-ip-view.md' },
|
|
||||||
{ text: 'Создание IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-create.md' },
|
|
||||||
{ text: 'Управление IP-адресами', link: '/compute/compute-how-to/compute-ip/compute-ip-manager.md' },
|
|
||||||
{ text: 'Удаление IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-del.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ text: 'Группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Обзор', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-about.md'},
|
|
||||||
{ text: 'Создание группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-create.md'},
|
|
||||||
{ text: 'Управление группами размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-manager.md' },
|
|
||||||
{ text: 'Удаление группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-del.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ text: 'Сети', link: '/compute/compute-how-to/compute-network/compute-network-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Настройка site-to-site VPN с помощью VyOS', link: '/compute/compute-how-to/compute-network/compute-vpn-vyos.md' },
|
|
||||||
{ text: 'Подключение ВМ закрытого контура к интернету', link: '/compute/compute-how-to/compute-network/compute-network-inside.md' },
|
|
||||||
],
|
|
||||||
excludeFromIndex: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'/admin/': [
|
|
||||||
{
|
|
||||||
text: 'Администрирование', link: '/admin/index.md',
|
|
||||||
},
|
|
||||||
{text: 'Управление ключевыми парами', link: '/admin/ssh.md'},
|
|
||||||
],
|
|
||||||
'/vdi/': [
|
|
||||||
{
|
|
||||||
text: 'Виртуальные рабочие столы', link: '/vdi/index.md',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Обзор сервиса', link: '/vdi/vdi-overview.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'О сервисе', link: '/vdi/vdi-about.md' },
|
|
||||||
{ text: 'Техническое описание', link: '/vdi/vdi-tech.md' },
|
|
||||||
{ text: 'Квоты и лимиты', link: '/vdi/vdi-quatos.md' },
|
|
||||||
{ text: 'Тарификация', link: '/vdi/vdi-tarif.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Заказ виртуальных рабочих столов', link: '/vdi/vdi-how-to/vdi-create.md'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Настройка сервиса', link: '/vdi/vdi-how-to/vdi-nastroika.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Настройка интеграции с Active Directory', link: '/vdi/vdi-how-to/vdi-connect-to-ad.md' },
|
|
||||||
{ text: 'Настройка сети', link: '/vdi/vdi-how-to/vdi-interconnect.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// text: 'Gold-образ', link: '/vdi/vdi-how-to/vdi-gold.md'
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
text: 'Подключение к виртуальному рабочему месту', link: '/vdi/vdi-how-to/vdi-connect.md'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://vitepress.dev/reference/site-config
|
// https://vitepress.dev/reference/site-config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@@ -373,7 +140,240 @@ export default defineConfig({
|
|||||||
outline: {
|
outline: {
|
||||||
label: 'Содержание'
|
label: 'Содержание'
|
||||||
},
|
},
|
||||||
sidebar: sidebarConfig,
|
sidebar: {
|
||||||
|
'/platform/': [
|
||||||
|
{
|
||||||
|
text: 'Платформа Beeline Cloud', link: '/platform/index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Обзор', link: '/platform/about.md'},
|
||||||
|
{text: 'Техническая поддержка', link: '/platform/support/support-overview.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'/start/': [
|
||||||
|
{
|
||||||
|
text: 'Начало работы в Beeline Cloud', link: '/start/index.md',
|
||||||
|
},
|
||||||
|
{text: 'Начать работу', link: '/start/getting-started.md'},
|
||||||
|
{text: 'Бесплатный период', link: '/start/trial.md'},
|
||||||
|
{text: 'Платное использование', link: '/start/organization.md'},
|
||||||
|
],
|
||||||
|
// '/billing/': [
|
||||||
|
|
||||||
|
// ],
|
||||||
|
'/backups/': [
|
||||||
|
{
|
||||||
|
text: 'Резервное копирование', link: '/backups/index.md',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Обзор сервиса', link: '/backups/backups-overview.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'О сервисе', link: '/backups/about.md'},
|
||||||
|
{text: 'Квоты и лимиты', link: '/backups/backup-quatos.md'},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{text: 'Резервное копирование виртуальных машин Beeline Cloud', link: '/backups/backup-internal-infra.md'},
|
||||||
|
{text: 'Резервное копирование собственной инфраструктуры в Beeline Cloud', link: '/backups/backup-external-infra.md'},
|
||||||
|
{text: 'Каталог резервных копий', link: '/backups/view-backups.md'},
|
||||||
|
|
||||||
|
],
|
||||||
|
'/vdc/': [
|
||||||
|
{
|
||||||
|
text: 'Виртуальные дата-центры на VMware', link: '/vdc/index.md',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Обзор сервиса', link: '/vdc/vdc-overview.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'О сервисе', link: '/vdc/vdc-about.md' },
|
||||||
|
{ text: 'Техническое описание', link: '/vdc/vdc-tech.md' },
|
||||||
|
{ text: 'Квоты и лимиты', link: '/vdc/vdc-quatos.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Быстрый старт', link: '/vdc/vdc-getting-started.md'
|
||||||
|
},
|
||||||
|
|
||||||
|
{ text: 'Виртуальные дата-центры', link: '/vdc/vdc-how-to/vdc-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Создание дата-центра', link: '/vdc/vdc-how-to/vdc-create.md' },
|
||||||
|
{ text: 'Вход в дата-центр', link: '/vdc/vdc-how-to/vdc-enter.md' },
|
||||||
|
{ text: 'Управление дата-центром', link: '/vdc/vdc-how-to/vdc-manage.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Виртуальные машины', link: '/vdc/vdc-how-to/vm/vm-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Создание ВМ', link: '/vdc/vdc-how-to/vm/create-vm.md'},
|
||||||
|
{text: 'Создание vApp', link: '/vdc/vdc-how-to/vm/create-vapp.md'},
|
||||||
|
{text: 'Управление состоянием ВМ', link: '/vdc/vdc-how-to/vm/manage-vm.md'},
|
||||||
|
{text: 'Клонирование ВМ', link: '/vdc/vdc-how-to/vm/clone-vm.md'},
|
||||||
|
{text: 'Изменение конфигурации ВМ', link: '/vdc/vdc-how-to/vm/edit-vm.md'},
|
||||||
|
{text: 'Удаление ВМ', link: '/vdc/vdc-how-to/vm/delete-vm.md'},
|
||||||
|
{text: 'Группы размещения', link: '/vdc/vdc-how-to/vm/create-affinity-rules.md'},
|
||||||
|
{text: 'Снимки ВМ', link: '/vdc/vdc-how-to/vm/create-snapshot.md'},
|
||||||
|
{text: 'VMware Tools', link: '/vdc/vdc-how-to/vm/vmware-tools.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Диски', link: '/vdc/vdc-how-to/disks/disks-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Обзор', link: '/vdc/vdc-how-to/disks/about.md'},
|
||||||
|
{text: 'Создание диска', link: '/vdc/vdc-how-to/disks/create-disk.md'},
|
||||||
|
{text: 'Проверка состояния диска', link: '/vdc/vdc-how-to/disks/view-disk.md'},
|
||||||
|
{text: 'Управление выделенными дисками', link: '/vdc/vdc-how-to/disks/attach-disk.md'},
|
||||||
|
{text: 'Изменение политики хранения дисков ВМ', link: '/vdc/vdc-how-to/disks/change-storage-policy-of-vm.md'},
|
||||||
|
{text: 'Редактирование параметров диска', link: '/vdc/vdc-how-to/disks/edit-disk.md'},
|
||||||
|
{text: 'Удаление диска', link: '/vdc/vdc-how-to/disks/delete-disk.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Сети', link: '/vdc/vdc-how-to/networks/networks-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Обзор', link: '/vdc/vdc-how-to/networks/about.md'},
|
||||||
|
{text: 'Настройка доступа к ВМ из интернета', link: '/vdc/vdc-how-to/networks/allow-external-connections-to-vm.md'},
|
||||||
|
{text: 'Подключение ВМ в vApp к сети', link: '/vdc/vdc-how-to/networks/connect-vapp-to-network.md'},
|
||||||
|
{text: 'Подключение ВМ к интернету', link: '/vdc/vdc-how-to/networks/connect-vm-to-network.md'},
|
||||||
|
{text: 'Создание сети в организации и подключение к Edge Gateway', link: '/vdc/vdc-how-to/networks/create-network.md'},
|
||||||
|
{text: 'Подключение сети к Edge Gateway', link: '/vdc/vdc-how-to/networks/connect-to-edge-gateway.md'},
|
||||||
|
{text: 'Создание Pre-Shared Key', link: '/vdc/vdc-how-to/networks/create-psk.md'},
|
||||||
|
{ text: 'Настройка site-to-site подключения с помощью IPSec', link: '/vdc/vdc-how-to/networks/how-to-setup-ipsec-vpn.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Настройка IPSec VPN', link: '/vdc/vdc-how-to/networks/ipsec/setup-ipsec-vpn.md'},
|
||||||
|
{text: 'Настройка ASAv', link: '/vdc/vdc-how-to/networks/ipsec/asav.md'},
|
||||||
|
{text: 'Настройка CSR 1000v', link: '/vdc/vdc-how-to/networks/ipsec/csr1000v.md'},
|
||||||
|
{text: 'Настройка Fortigate', link: '/vdc/vdc-how-to/networks/ipsec/fortigate.md'},
|
||||||
|
{text: 'Проверить сетевую связанность', link: '/vdc/vdc-how-to/networks/ipsec/check-vpn-status.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Пользователи и роли', link: '/vdc/vdc-how-to/users/users-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Ролевая модель', link: '/vdc/vdc-how-to/users/roles.md'},
|
||||||
|
{text: 'Создание пользователя', link: '/vdc/vdc-how-to/users/add-user.md'},
|
||||||
|
{text: 'Изменение пароля пользователя', link: '/vdc/vdc-how-to/users/change-users-password.md'},
|
||||||
|
{text: 'Настройка квот', link: '/vdc/vdc-how-to/users/quotas.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Двухфакторная аутентификация', link: '/vdc/vdc-how-to/vdc-2fa.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Подключение 2FA', link: '/vdc/vdc-how-to/vdc-2fa-start.md'},
|
||||||
|
{text: 'Управление 2FA', link: '/vdc/vdc-how-to/vdc-2fa-manage.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
// { text: 'Тарификация', link: '/vdc/vdc-tarif.md' },
|
||||||
|
'/compute/': [
|
||||||
|
{
|
||||||
|
text: 'Виртуальные машины', link: '/compute/index.md',
|
||||||
|
},
|
||||||
|
{ text: 'Обзор сервиса', link: '/compute/compute-overview-index.md' ,
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Техническое описание', link: '/compute/compute-overview.md' },
|
||||||
|
{ text: 'Квоты и лимиты', link: '/compute/compute-quatos.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{text: 'Быстрый старт', link: '/compute/compute-getting-started.md'},
|
||||||
|
{ text: 'Виртуальные машины', link: '/compute/compute-how-to/compute-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Создание ВМ', link: '/compute/compute-how-to/compute-servers-create.md' },
|
||||||
|
{ text: 'Создание ВМ джамп-хоста', link: '/compute/compute-how-to/compute-servers-jump-create.md' },
|
||||||
|
{ text: 'Подключение к ВМ', link: '/compute/compute-how-to/compute-connect-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Подключение по SSH по внешнему IP-адресу с помощью ключевой пары', link: '/compute/compute-how-to/compute-connect-public.md'},
|
||||||
|
{ text: 'Подключение по SSH по внутреннему IP-адресу с помощью ключевой пары', link: '/compute/compute-how-to/compute-connect-inside.md' },
|
||||||
|
{ text: 'Подключение по SSH по логину и паролю', link: '/compute/compute-how-to/compute-connect-pwd.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ text: 'Управление ВМ', link: '/compute/compute-how-to/compute-servers-manage.md' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Диски', link: '/compute/compute-how-to/compute-disks/compute-disk-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Обзор', link: '/compute/compute-how-to/compute-disks/compute-disk-about.md' },
|
||||||
|
{ text: 'Создание диска', link: '/compute/compute-how-to/compute-disks/compute-disk-create.md' },
|
||||||
|
{ text: 'Управление дисками', link: '/compute/compute-how-to/compute-disks/compute-disk-manage.md' },
|
||||||
|
{ text: 'Удаление диска', link: '/compute/compute-how-to/compute-disks/compute-disk-del.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ text: 'IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Обзор', link: '/compute/compute-how-to/compute-ip/compute-ip-about.md' },
|
||||||
|
{ text: 'Просмотр IP-адресов', link: '/compute/compute-how-to/compute-ip/compute-ip-view.md' },
|
||||||
|
{ text: 'Создание IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-create.md' },
|
||||||
|
{ text: 'Управление IP-адресами', link: '/compute/compute-how-to/compute-ip/compute-ip-manager.md' },
|
||||||
|
{ text: 'Удаление IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-del.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ text: 'Группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Обзор', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-about.md'},
|
||||||
|
{ text: 'Создание группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-create.md'},
|
||||||
|
{ text: 'Управление группами размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-manager.md' },
|
||||||
|
{ text: 'Удаление группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-del.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ text: 'Сети', link: '/compute/compute-how-to/compute-network/compute-network-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Настройка site-to-site VPN с помощью VyOS', link: '/compute/compute-how-to/compute-network/compute-vpn-vyos.md' },
|
||||||
|
{ text: 'Подключение ВМ закрытого контура к интернету', link: '/compute/compute-how-to/compute-network/compute-network-inside.md' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'/admin/': [
|
||||||
|
{
|
||||||
|
text: 'Администрирование', link: '/admin/index.md',
|
||||||
|
},
|
||||||
|
{text: 'Управление ключевыми парами', link: '/admin/ssh.md'},
|
||||||
|
],
|
||||||
|
'/vdi/': [
|
||||||
|
{
|
||||||
|
text: 'Виртуальные рабочие столы', link: '/vdi/index.md',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Обзор сервиса', link: '/vdi/vdi-overview.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'О сервисе', link: '/vdi/vdi-about.md' },
|
||||||
|
{ text: 'Техническое описание', link: '/vdi/vdi-tech.md' },
|
||||||
|
{ text: 'Квоты и лимиты', link: '/vdi/vdi-quatos.md' },
|
||||||
|
{ text: 'Тарификация', link: '/vdi/vdi-tarif.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Заказ виртуальных рабочих столов', link: '/vdi/vdi-how-to/vdi-create.md'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Настройка сервиса', link: '/vdi/vdi-how-to/vdi-nastroika.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Настройка интеграции с Active Directory', link: '/vdi/vdi-how-to/vdi-connect-to-ad.md' },
|
||||||
|
{ text: 'Настройка сети', link: '/vdi/vdi-how-to/vdi-interconnect.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// text: 'Gold-образ', link: '/vdi/vdi-how-to/vdi-gold.md'
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
text: 'Подключение к виртуальному рабочему месту', link: '/vdi/vdi-how-to/vdi-connect.md'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
import type { Plugin } from 'vite'
|
|
||||||
import type { SidebarItem } from './utils/types'
|
|
||||||
import { processAllFiles } from './hook/process-files'
|
|
||||||
|
|
||||||
export const autoSectionLinksPlugin = (
|
|
||||||
srcDir: string,
|
|
||||||
sidebarConfig: Record<string, SidebarItem[]>
|
|
||||||
): Plugin => ({
|
|
||||||
name: 'auto-section-links',
|
|
||||||
buildStart: () => {
|
|
||||||
processAllFiles(srcDir, sidebarConfig)
|
|
||||||
},
|
|
||||||
configureServer: () => {
|
|
||||||
processAllFiles(srcDir, sidebarConfig)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export const INDEX_FILE = 'index.md'
|
|
||||||
export const INDEX_FILE_PATTERN = /-index\.md$|index\.md$/
|
|
||||||
export const FRONTMATTER_REGEX = /^---\s*\n([\s\S]*?)\n---/
|
|
||||||
export const SECTION_LINK_KEYS = ['title', 'link', 'description'] as const
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import { existsSync } from 'fs'
|
|
||||||
import { relative, resolve } from 'path'
|
|
||||||
import type { SidebarItem } from '../utils/types'
|
|
||||||
import { findMarkdownFiles } from '../utils/file-finder'
|
|
||||||
import { processIndexFile, processPageWithItems } from '../utils/file-processor'
|
|
||||||
import { INDEX_FILE, INDEX_FILE_PATTERN } from '../constants'
|
|
||||||
|
|
||||||
export const processAllFiles = (
|
|
||||||
srcDir: string,
|
|
||||||
sidebarConfig: Record<string, SidebarItem[]>
|
|
||||||
) => {
|
|
||||||
const srcPath = resolve(srcDir)
|
|
||||||
|
|
||||||
for (const [folderPath, items] of Object.entries(sidebarConfig)) {
|
|
||||||
const normalizedFolder = folderPath.replace(/^\/+|\/+$/g, '')
|
|
||||||
const folderFullPath = resolve(srcPath, normalizedFolder)
|
|
||||||
|
|
||||||
if (!existsSync(folderFullPath)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const mdFiles = findMarkdownFiles(folderFullPath)
|
|
||||||
|
|
||||||
for (const filePath of mdFiles) {
|
|
||||||
const fileName = filePath.split(/[/\\]/).pop() || ''
|
|
||||||
const relativePath = relative(srcPath, filePath).replace(/\\/g, '/')
|
|
||||||
const normalizedPath = relativePath.startsWith('/') ? relativePath : `/${relativePath}`
|
|
||||||
|
|
||||||
if (fileName === INDEX_FILE) {
|
|
||||||
processIndexFile(filePath, items, srcPath)
|
|
||||||
} else if (INDEX_FILE_PATTERN.test(fileName) && fileName !== INDEX_FILE) {
|
|
||||||
processPageWithItems(filePath, items, srcPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import { readFileSync, existsSync } from 'fs'
|
|
||||||
import { resolve } from 'path'
|
|
||||||
import { parseFrontmatter } from './frontmatter'
|
|
||||||
|
|
||||||
export const getPageDescription = (filePath: string, srcDir: string) => {
|
|
||||||
try {
|
|
||||||
const fullPath = resolve(srcDir, filePath.replace(/^\//, ''))
|
|
||||||
if (!existsSync(fullPath)) return undefined
|
|
||||||
|
|
||||||
const fileContent = readFileSync(fullPath, 'utf-8')
|
|
||||||
const { frontmatter } = parseFrontmatter(fileContent)
|
|
||||||
|
|
||||||
return frontmatter.description as string | undefined
|
|
||||||
} catch {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import { readdirSync, statSync } from 'fs'
|
|
||||||
import { join } from 'path'
|
|
||||||
|
|
||||||
export const findMarkdownFiles = (dir: string) => {
|
|
||||||
const files: string[] = []
|
|
||||||
|
|
||||||
try {
|
|
||||||
const entries = readdirSync(dir)
|
|
||||||
|
|
||||||
for (const entry of entries) {
|
|
||||||
const fullPath = join(dir, entry)
|
|
||||||
const stat = statSync(fullPath)
|
|
||||||
|
|
||||||
if (stat.isDirectory()) {
|
|
||||||
files.push(...findMarkdownFiles(fullPath))
|
|
||||||
} else if (entry.endsWith('.md')) {
|
|
||||||
files.push(fullPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
}
|
|
||||||
|
|
||||||
return files
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
import { readFileSync, writeFileSync, existsSync } from 'fs'
|
|
||||||
import { relative, resolve } from 'path'
|
|
||||||
import type { SidebarItem } from './types'
|
|
||||||
import { parseFrontmatter, stringifyFrontmatter } from './frontmatter'
|
|
||||||
import { mergeSectionLinks, extractTopLevelLinks, extractItemsForPage } from './links'
|
|
||||||
import { normalizeLink } from './path-utils'
|
|
||||||
import { SectionLinkListItem } from '../../theme/components/SectionLinkList/SectionLinkList.types'
|
|
||||||
|
|
||||||
const removeDuplicates = (links: SectionLinkListItem[]) => {
|
|
||||||
const result: SectionLinkListItem[] = []
|
|
||||||
const seenLinks = new Set<string>()
|
|
||||||
|
|
||||||
for (const link of links) {
|
|
||||||
if (link.link) {
|
|
||||||
const normalized = normalizeLink(link.link)
|
|
||||||
if (!seenLinks.has(normalized)) {
|
|
||||||
seenLinks.add(normalized)
|
|
||||||
result.push(link)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
const hasChanges = (
|
|
||||||
existingLinks: SectionLinkListItem[],
|
|
||||||
mergedLinks: SectionLinkListItem[]
|
|
||||||
) => {
|
|
||||||
if (existingLinks.length !== mergedLinks.length) return true
|
|
||||||
|
|
||||||
const existingSet = new Set(
|
|
||||||
existingLinks
|
|
||||||
.filter(link => link.link)
|
|
||||||
.map(link => `${normalizeLink(link.link!)}|${link.title}`)
|
|
||||||
)
|
|
||||||
|
|
||||||
const mergedSet = new Set(
|
|
||||||
mergedLinks
|
|
||||||
.filter(link => link.link)
|
|
||||||
.map(link => `${normalizeLink(link.link!)}|${link.title}`)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (existingSet.size !== mergedSet.size) return true
|
|
||||||
|
|
||||||
for (const item of existingSet) {
|
|
||||||
if (!mergedSet.has(item)) return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
export const processIndexFile = (
|
|
||||||
filePath: string,
|
|
||||||
sidebarItems: SidebarItem[],
|
|
||||||
srcDir: string
|
|
||||||
) => {
|
|
||||||
if (!existsSync(filePath)) return false
|
|
||||||
|
|
||||||
try {
|
|
||||||
const fileContent = readFileSync(filePath, 'utf-8')
|
|
||||||
const { frontmatter, content } = parseFrontmatter(fileContent)
|
|
||||||
|
|
||||||
const relativePath = relative(srcDir, filePath).replace(/\\/g, '/')
|
|
||||||
const normalizedPath = relativePath.startsWith('/') ? relativePath : `/${relativePath}`
|
|
||||||
|
|
||||||
const existingLinks = removeDuplicates(
|
|
||||||
Array.isArray(frontmatter.section_links) ? [...frontmatter.section_links] : []
|
|
||||||
)
|
|
||||||
const newLinks = extractTopLevelLinks(sidebarItems, normalizedPath, srcDir)
|
|
||||||
|
|
||||||
if (!newLinks.length) return false
|
|
||||||
|
|
||||||
const mergedLinks = removeDuplicates(mergeSectionLinks(existingLinks, newLinks))
|
|
||||||
|
|
||||||
if (!hasChanges(existingLinks, mergedLinks)) return false
|
|
||||||
|
|
||||||
frontmatter.section_links = mergedLinks
|
|
||||||
writeFileSync(filePath, stringifyFrontmatter(frontmatter, content), 'utf-8')
|
|
||||||
return true
|
|
||||||
} catch {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const processPageWithItems = (
|
|
||||||
filePath: string,
|
|
||||||
sidebarItems: SidebarItem[],
|
|
||||||
srcDir: string
|
|
||||||
) => {
|
|
||||||
if (!existsSync(filePath)) return false
|
|
||||||
|
|
||||||
try {
|
|
||||||
const fileContent = readFileSync(filePath, 'utf-8')
|
|
||||||
const { frontmatter, content } = parseFrontmatter(fileContent)
|
|
||||||
|
|
||||||
const relativePath = relative(srcDir, filePath).replace(/\\/g, '/')
|
|
||||||
const normalizedPath = relativePath.startsWith('/') ? relativePath : `/${relativePath}`
|
|
||||||
|
|
||||||
const existingLinks = removeDuplicates(
|
|
||||||
Array.isArray(frontmatter.section_links) ? [...frontmatter.section_links] : []
|
|
||||||
)
|
|
||||||
const newLinks = extractItemsForPage(sidebarItems, normalizedPath, srcDir)
|
|
||||||
|
|
||||||
const mergedLinks = newLinks.length > 0
|
|
||||||
? removeDuplicates(mergeSectionLinks(existingLinks, newLinks))
|
|
||||||
: []
|
|
||||||
|
|
||||||
if (!hasChanges(existingLinks, mergedLinks)) return false
|
|
||||||
|
|
||||||
frontmatter.section_links = mergedLinks
|
|
||||||
writeFileSync(filePath, stringifyFrontmatter(frontmatter, content), 'utf-8')
|
|
||||||
return true
|
|
||||||
} catch {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
import type { Frontmatter } from './types'
|
|
||||||
import { SECTION_LINK_KEYS, FRONTMATTER_REGEX } from '../constants'
|
|
||||||
import { SectionLinkListItem } from '../../theme/components/SectionLinkList/SectionLinkList.types'
|
|
||||||
|
|
||||||
export const parseFrontmatter = (content: string) => {
|
|
||||||
const frontmatterMatch = content.match(FRONTMATTER_REGEX)
|
|
||||||
if (!frontmatterMatch) {
|
|
||||||
const cleanContent = content.replace(/^---[\s\S]*?---\s*\n*/g, '').trim()
|
|
||||||
return { frontmatter: {}, content: cleanContent || content }
|
|
||||||
}
|
|
||||||
|
|
||||||
const [, frontmatterText] = frontmatterMatch
|
|
||||||
const frontmatterEnd = frontmatterMatch[0].length
|
|
||||||
let cleanContent = content.slice(frontmatterEnd)
|
|
||||||
cleanContent = cleanContent.replace(/^---[\s\S]*?---\s*\n*/g, '').trim()
|
|
||||||
if (!cleanContent) {
|
|
||||||
cleanContent = content.slice(frontmatterEnd).replace(/^---[\s\S]*?---\s*\n*/g, '').trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
const frontmatter: Frontmatter = {}
|
|
||||||
const lines = frontmatterText.split('\n')
|
|
||||||
let currentKey: string | undefined
|
|
||||||
let currentValue: SectionLinkListItem[] = []
|
|
||||||
let currentItem: Record<string, string> | undefined
|
|
||||||
let inArray = false
|
|
||||||
|
|
||||||
for (const line of lines) {
|
|
||||||
const trimmed = line.trim()
|
|
||||||
if (trimmed && !trimmed.startsWith('#')) {
|
|
||||||
const lineIndent = line.match(/^(\s*)/)?.[1]?.length ?? 0
|
|
||||||
|
|
||||||
if (lineIndent === 0 && trimmed.includes(':')) {
|
|
||||||
if (inArray && currentKey) {
|
|
||||||
frontmatter[currentKey] = currentValue
|
|
||||||
currentValue = []
|
|
||||||
inArray = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const colonMatch = trimmed.match(/^([^:]+):\s*(.*)$/)
|
|
||||||
if (colonMatch) {
|
|
||||||
const [, key, value] = colonMatch
|
|
||||||
currentKey = key.trim()
|
|
||||||
const trimmedValue = value.trim()
|
|
||||||
|
|
||||||
if (trimmedValue === '') {
|
|
||||||
inArray = true
|
|
||||||
currentValue = []
|
|
||||||
} else {
|
|
||||||
frontmatter[currentKey] = trimmedValue.replace(/^["']|["']$/g, '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (lineIndent === 2 && trimmed.startsWith('- ')) {
|
|
||||||
if (!inArray && currentKey) {
|
|
||||||
inArray = true
|
|
||||||
currentValue = []
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentItem && currentItem.title && currentItem.link !== undefined) {
|
|
||||||
const link: SectionLinkListItem = {
|
|
||||||
title: currentItem.title,
|
|
||||||
link: currentItem.link,
|
|
||||||
description: currentItem.description
|
|
||||||
}
|
|
||||||
if (!currentValue.some(item => item.link === link.link)) {
|
|
||||||
currentValue.push(link)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const itemText = trimmed.slice(2).trim()
|
|
||||||
if (itemText.includes(':')) {
|
|
||||||
currentItem = {}
|
|
||||||
const parts = itemText.split(',').map(p => p.trim())
|
|
||||||
for (const part of parts) {
|
|
||||||
const colonMatch = part.match(/^(\w+):\s*(.+)$/)
|
|
||||||
if (colonMatch) {
|
|
||||||
const [, key, value] = colonMatch
|
|
||||||
if (SECTION_LINK_KEYS.includes(key as typeof SECTION_LINK_KEYS[number])) {
|
|
||||||
currentItem[key] = value.replace(/^["']|["']$/g, '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
currentValue.push({ title: itemText, link: '' })
|
|
||||||
}
|
|
||||||
} else if (lineIndent >= 4 && currentItem && trimmed.includes(':')) {
|
|
||||||
const colonIndex = trimmed.indexOf(':')
|
|
||||||
if (colonIndex !== -1) {
|
|
||||||
const key = trimmed.substring(0, colonIndex).trim()
|
|
||||||
const value = trimmed.substring(colonIndex + 1).trim()
|
|
||||||
if (SECTION_LINK_KEYS.includes(key as typeof SECTION_LINK_KEYS[number])) {
|
|
||||||
currentItem[key] = value === '' ? '' : value.replace(/^["']|["']$/g, '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentItem && inArray && currentItem.title && currentItem.link !== undefined) {
|
|
||||||
const link: SectionLinkListItem = {
|
|
||||||
title: currentItem.title,
|
|
||||||
link: currentItem.link,
|
|
||||||
description: currentItem.description
|
|
||||||
}
|
|
||||||
if (!currentValue.some(item => item.link === link.link)) {
|
|
||||||
currentValue.push(link)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (inArray && currentKey) {
|
|
||||||
frontmatter[currentKey] = currentValue
|
|
||||||
}
|
|
||||||
|
|
||||||
return { frontmatter, content: cleanContent || content }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const stringifyFrontmatter = (frontmatter: Frontmatter, content: string) => {
|
|
||||||
const lines: string[] = []
|
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(frontmatter)) {
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
lines.push(`${key}:`)
|
|
||||||
for (const item of value) {
|
|
||||||
if (typeof item === 'object' && item) {
|
|
||||||
const link = item as SectionLinkListItem
|
|
||||||
lines.push(` - title: ${link.title ?? ''}`)
|
|
||||||
if (link.link) lines.push(` link: ${link.link}`)
|
|
||||||
if ('description' in link && link.description !== undefined && link.description !== null && String(link.description).trim() !== '') {
|
|
||||||
lines.push(` description: ${String(link.description)}`)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lines.push(` - ${item}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (value) {
|
|
||||||
const strValue = String(value)
|
|
||||||
const needsQuotes = strValue.includes(':') || (strValue.includes(' ') && !strValue.startsWith('"')) || strValue === ''
|
|
||||||
const escaped = strValue.replace(/"/g, '\\"')
|
|
||||||
lines.push(`${key}: ${needsQuotes ? `"${escaped}"` : strValue}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return `---\n${lines.join('\n')}\n---\n\n${content}`
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
import type { SidebarItem } from './types'
|
|
||||||
import { getPageDescription } from './descriptions'
|
|
||||||
import { normalizeLink } from './path-utils'
|
|
||||||
import { SectionLinkListItem } from '../../theme/components/SectionLinkList/SectionLinkList.types'
|
|
||||||
|
|
||||||
export const mergeSectionLinks = (
|
|
||||||
existingLinks: SectionLinkListItem[],
|
|
||||||
newLinks: SectionLinkListItem[]
|
|
||||||
) => {
|
|
||||||
const existingLinksMap = new Map<string, SectionLinkListItem>()
|
|
||||||
const result: SectionLinkListItem[] = []
|
|
||||||
const processedLinks = new Set<string>()
|
|
||||||
|
|
||||||
for (const existingLink of existingLinks) {
|
|
||||||
if (existingLink.link) {
|
|
||||||
const normalizedLink = normalizeLink(existingLink.link)
|
|
||||||
if (!existingLinksMap.has(normalizedLink)) {
|
|
||||||
existingLinksMap.set(normalizedLink, existingLink)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const newLink of newLinks) {
|
|
||||||
if (newLink.link) {
|
|
||||||
const normalizedLink = normalizeLink(newLink.link)
|
|
||||||
|
|
||||||
if (!processedLinks.has(normalizedLink)) {
|
|
||||||
processedLinks.add(normalizedLink)
|
|
||||||
|
|
||||||
if (existingLinksMap.has(normalizedLink)) {
|
|
||||||
const existingLink = existingLinksMap.get(normalizedLink)!
|
|
||||||
result.push({ ...existingLink, title: newLink.title })
|
|
||||||
} else {
|
|
||||||
result.push(newLink)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
export const extractTopLevelLinks = (
|
|
||||||
items: SidebarItem[],
|
|
||||||
currentIndexPath: string,
|
|
||||||
srcDir: string
|
|
||||||
) => {
|
|
||||||
const links: SectionLinkListItem[] = []
|
|
||||||
const normalizedCurrentPath = normalizeLink(currentIndexPath)
|
|
||||||
|
|
||||||
for (const item of items) {
|
|
||||||
if ('excludeFromIndex' in item && item.excludeFromIndex) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.link) {
|
|
||||||
const normalizedItemPath = normalizeLink(item.link)
|
|
||||||
if (normalizedItemPath === normalizedCurrentPath) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
links.push({
|
|
||||||
title: item.text || '',
|
|
||||||
link: item.link,
|
|
||||||
description: getPageDescription(item.link, srcDir)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
|
|
||||||
const findItemsRecursive = (
|
|
||||||
itemsList: SidebarItem[],
|
|
||||||
pagePath: string,
|
|
||||||
srcDir: string
|
|
||||||
): SectionLinkListItem[] => {
|
|
||||||
const normalizedPagePath = normalizeLink(pagePath)
|
|
||||||
const links: SectionLinkListItem[] = []
|
|
||||||
|
|
||||||
for (const item of itemsList) {
|
|
||||||
if (item.link) {
|
|
||||||
const normalizedItemPath = normalizeLink(item.link)
|
|
||||||
|
|
||||||
if (normalizedItemPath === normalizedPagePath && item.items && Array.isArray(item.items) && item.items.length > 0) {
|
|
||||||
for (const subItem of item.items) {
|
|
||||||
if ('excludeFromIndex' in subItem && subItem.excludeFromIndex) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subItem.link) {
|
|
||||||
links.push({
|
|
||||||
title: subItem.text || '',
|
|
||||||
link: subItem.link,
|
|
||||||
description: getPageDescription(subItem.link, srcDir)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.items && Array.isArray(item.items)) {
|
|
||||||
const found = findItemsRecursive(item.items, pagePath, srcDir)
|
|
||||||
if (found.length > 0) {
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return links
|
|
||||||
}
|
|
||||||
|
|
||||||
export const extractItemsForPage = (
|
|
||||||
items: SidebarItem[],
|
|
||||||
pagePath: string,
|
|
||||||
srcDir: string
|
|
||||||
) => findItemsRecursive(items, pagePath, srcDir)
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
export const normalizeLink = (link: string): string =>
|
|
||||||
!link ? '' : link
|
|
||||||
.replace(/^\/+/, '')
|
|
||||||
.replace(/\.md$/, '')
|
|
||||||
.replace(/\\/g, '/')
|
|
||||||
.trim()
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import { SectionLinkListItem } from "../../theme/components/SectionLinkList/SectionLinkList.types"
|
|
||||||
|
|
||||||
export type SidebarItem = {
|
|
||||||
text: string
|
|
||||||
link?: string
|
|
||||||
items?: SidebarItem[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Frontmatter = {
|
|
||||||
section_links?: SectionLinkListItem[]
|
|
||||||
[key: string]: string | number | boolean | string[] | SectionLinkListItem[] | undefined
|
|
||||||
}
|
|
||||||
@@ -2,8 +2,6 @@ export type SectionLinkListItem = {
|
|||||||
title: string,
|
title: string,
|
||||||
link: string,
|
link: string,
|
||||||
description?: string
|
description?: string
|
||||||
collapsed?: boolean
|
|
||||||
excludeFromIndex?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SectionLinkListProps = {
|
export type SectionLinkListProps = {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ section_links:
|
|||||||
link: /compute/compute-how-to/compute-connect-inside.md
|
link: /compute/compute-how-to/compute-connect-inside.md
|
||||||
description: Подключиться к виртуальной машине по SSH с помощью ключевой пары по внутреннему IP-адресу через джамп-хост
|
description: Подключиться к виртуальной машине по SSH с помощью ключевой пары по внутреннему IP-адресу через джамп-хост
|
||||||
- title: Подключение по SSH по логину и паролю
|
- title: Подключение по SSH по логину и паролю
|
||||||
link: /compute/compute-how-to/compute-connect-pwd.md
|
link: /compute/compute-how-to/compute-connect-inside.md
|
||||||
description: Подключиться к виртуальной машине по SSH с помощью логина и пароля
|
description: Подключиться к виртуальной машине по SSH с помощью логина и пароля
|
||||||
---
|
---
|
||||||
|
|
||||||
# Подключение к ВМ
|
# Подключение к ВМ
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ section_links:
|
|||||||
description: Резервирование, назначение IP-адреса виртуальной машине, удаление IP-адресов
|
description: Резервирование, назначение IP-адреса виртуальной машине, удаление IP-адресов
|
||||||
- title: Группы размещения
|
- title: Группы размещения
|
||||||
link: /compute/compute-how-to/compute-affinity.md
|
link: /compute/compute-how-to/compute-affinity.md
|
||||||
description: Создание правил размещения виртуальных машин на физических хостах, управление группами размещения
|
description: Создание правил размещения виртуальных машин на физических хостах, управление группами размещения
|
||||||
---
|
---
|
||||||
|
|
||||||
# Виртуальные машины
|
# Виртуальные машины
|
||||||
|
|
||||||
Сервис **Виртуальные машины** предоставляет пользователям виртуальные машины.
|
Сервис **Виртуальные машины** предоставляет пользователям виртуальные машины.
|
||||||
|
|||||||
+12
-6
@@ -113,22 +113,28 @@ services:
|
|||||||
- title: Защита веб-приложений (WAF)
|
- title: Защита веб-приложений (WAF)
|
||||||
description: В работе
|
description: В работе
|
||||||
icon: security
|
icon: security
|
||||||
- title: Защита серверов и рабочих мест
|
- title: Защита серверов и рабочих станций (EPP)
|
||||||
description: В работе
|
description: В работе
|
||||||
icon: security
|
icon: security
|
||||||
- title: Защита устройств пользователей
|
- title: Управление мобильными устройствами (MDM)
|
||||||
description: В работе
|
description: В работе
|
||||||
icon: security
|
icon: security
|
||||||
- title: Сканер уязвимостей
|
- title: Сканер уязвимостей (VS)
|
||||||
description: В работе
|
description: В работе
|
||||||
icon: security
|
icon: security
|
||||||
- title: Курсы кибербезопасности
|
- title: Обучение основам киберграмотности (SA)
|
||||||
description: В работе
|
description: В работе
|
||||||
icon: security
|
icon: security
|
||||||
- title: Многофакторная аутентификация
|
- title: Многофакторная аутентификация (MFA)
|
||||||
description: В работе
|
description: В работе
|
||||||
icon: security
|
icon: security
|
||||||
- title: Фильтрация почтового трафика
|
- title: Защита электронной почты (SEG)
|
||||||
|
description: В работе
|
||||||
|
icon: security
|
||||||
|
- title: Защита от DDoS
|
||||||
|
description: В работе
|
||||||
|
icon: security
|
||||||
|
- title: ГОСТ VPN
|
||||||
description: В работе
|
description: В работе
|
||||||
icon: security
|
icon: security
|
||||||
- title: Виртуальное рабочее место
|
- title: Виртуальное рабочее место
|
||||||
|
|||||||
Reference in New Issue
Block a user