From ad3b986d89d9b0e38da1b9fd4ae1db8dea67268f Mon Sep 17 00:00:00 2001 From: Naeel Date: Sat, 18 Jul 2026 09:50:37 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9=20=D0=B4?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D0=B9=D0=BD=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8=20=E2=80=94=20=D1=88?= =?UTF-8?q?=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD,=20=D0=B3=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D1=80=D0=B0=D1=82=D0=BE=D1=80,=20CSS,=20md=5Fin=5Fhtml,=20?= =?UTF-8?q?=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8F=205.1.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TOOLS/config/test/profile.env | 2 +- .../internal/writers/writers.go | 24 ++- docs/30_registry/assets/extra.css | 174 +++++++++++------- docs/help/design-stage1-plan.md | 35 ++++ docs/help/resource-page-template.md | 96 ++++++++++ mkdocs.yml | 1 + 6 files changed, 253 insertions(+), 79 deletions(-) create mode 100644 docs/help/design-stage1-plan.md create mode 100644 docs/help/resource-page-template.md diff --git a/TOOLS/config/test/profile.env b/TOOLS/config/test/profile.env index ca6a3cf..008f4c6 100644 --- a/TOOLS/config/test/profile.env +++ b/TOOLS/config/test/profile.env @@ -3,7 +3,7 @@ NUBES_API_ENDPOINT="https://lk-api-gateway-test.ngcloud.ru/api/v1/svc" TOKEN_FILE="secrets/test.token" # Version -VERSION="5.2.0" +VERSION="5.1.2" # Docs generation — ONLY from docs_gen// (never from docs/) DOCS_GEN_DIR="provider/docs_gen/test" diff --git a/TOOLS/docs-generator/internal/writers/writers.go b/TOOLS/docs-generator/internal/writers/writers.go index ab7b4a6..4d891fd 100644 --- a/TOOLS/docs-generator/internal/writers/writers.go +++ b/TOOLS/docs-generator/internal/writers/writers.go @@ -21,15 +21,21 @@ var CloudOutputByServiceID = map[int]types.CloudOutputSnapshot{} // ResourceDocs генерирует полный набор .md файлов для одного сервиса. func ResourceDocs(docsDir string, spec types.ServiceSpec, version string, apiEndpoint string, providerSource string) { base := spec.Name - nav := fmt.Sprintf("[Manual](%s.md) | [Create params](%s_params_create.md) | [Modify params](%s_params_modify.md) | [Output params](%s_outputs.md) | [Operations](%s_ops.md) | [Example](%s_example.md)", base, base, base, base, base, base) - WriteFile(filepath.Join(docsDir, base+".md"), buildManualPage(spec, nav)) - WriteFile(filepath.Join(docsDir, base+"_example.md"), buildExamplePage(spec, nav, version, apiEndpoint, providerSource)) - WriteFile(filepath.Join(docsDir, base+"_params_create.md"), buildCreateParamsPage(spec, nav)) - WriteFile(filepath.Join(docsDir, base+"_params_modify.md"), buildModifyParamsPage(spec, nav)) - WriteFile(filepath.Join(docsDir, base+"_outputs.md"), buildOutputsPage(spec, nav)) - WriteFile(filepath.Join(docsDir, base+"_ops.md"), buildOpsPage(spec, nav, docsDir)) - WriteFile(filepath.Join(docsDir, base+"_params.md"), buildParamsLandingPage(spec, nav)) + navManual := fmt.Sprintf("**Manual** · [Create params](%s_params_create.md) · [Modify params](%s_params_modify.md) · [Output params](%s_outputs.md) · [Operations](%s_ops.md) · [Example](%s_example.md)", base, base, base, base, base) + navCreate := fmt.Sprintf("[Manual](%s.md) · **Create params** · [Modify params](%s_params_modify.md) · [Output params](%s_outputs.md) · [Operations](%s_ops.md) · [Example](%s_example.md)", base, base, base, base, base) + navModify := fmt.Sprintf("[Manual](%s.md) · [Create params](%s_params_create.md) · **Modify params** · [Output params](%s_outputs.md) · [Operations](%s_ops.md) · [Example](%s_example.md)", base, base, base, base, base) + navOutputs := fmt.Sprintf("[Manual](%s.md) · [Create params](%s_params_create.md) · [Modify params](%s_params_modify.md) · **Output params** · [Operations](%s_ops.md) · [Example](%s_example.md)", base, base, base, base, base) + navOps := fmt.Sprintf("[Manual](%s.md) · [Create params](%s_params_create.md) · [Modify params](%s_params_modify.md) · [Output params](%s_outputs.md) · **Operations** · [Example](%s_example.md)", base, base, base, base, base) + navExample := fmt.Sprintf("[Manual](%s.md) · [Create params](%s_params_create.md) · [Modify params](%s_params_modify.md) · [Output params](%s_outputs.md) · [Operations](%s_ops.md) · **Example**", base, base, base, base, base) + + WriteFile(filepath.Join(docsDir, base+".md"), buildManualPage(spec, navManual)) + WriteFile(filepath.Join(docsDir, base+"_example.md"), buildExamplePage(spec, navExample, version, apiEndpoint, providerSource)) + WriteFile(filepath.Join(docsDir, base+"_params_create.md"), buildCreateParamsPage(spec, navCreate)) + WriteFile(filepath.Join(docsDir, base+"_params_modify.md"), buildModifyParamsPage(spec, navModify)) + WriteFile(filepath.Join(docsDir, base+"_outputs.md"), buildOutputsPage(spec, navOutputs)) + WriteFile(filepath.Join(docsDir, base+"_ops.md"), buildOpsPage(spec, navOps, docsDir)) + WriteFile(filepath.Join(docsDir, base+"_params.md"), buildParamsLandingPage(spec, navManual)) for _, srName := range CollectSubresources(spec) { srBase := fmt.Sprintf("%s_%s", base, Slug(srName)) @@ -122,7 +128,7 @@ func buildHeader(spec types.ServiceSpec, nav string) string { if name == "" { name = spec.Name } - return fmt.Sprintf("# Resource nubes_%s\n\nService ID: `%d`\n\nService Name: %s\n\n%s\n\n", spec.Name, spec.ServiceID, name, nav) + return fmt.Sprintf("# Resource nubes_%s · Service ID: %d · Service Name: %s\n\n%s\n\n", spec.Name, spec.ServiceID, name, nav) } func buildManualPage(spec types.ServiceSpec, nav string) string { diff --git a/docs/30_registry/assets/extra.css b/docs/30_registry/assets/extra.css index 6b0d4cf..3c1ea11 100644 --- a/docs/30_registry/assets/extra.css +++ b/docs/30_registry/assets/extra.css @@ -47,146 +47,181 @@ padding-bottom: 0.3rem; } -/* Column sizing for resource tables */ -/* Widths based on real YAML data analysis, see docs/help/table-column-widths-analysis.md */ -.resource-table { +.md-typeset .man-content { + font-size: 0.62rem; + line-height: 1.4; +} + +/* Resource title + tabs: compact */ +.md-typeset .md-content__inner > h1:first-child { + font-size: 0.77rem; + line-height: 1.2; +} + +.md-typeset .md-content__inner > h1:first-child + p { + font-size: 0.65rem; +} + +/* ---- ALL TABLE RULES — prefixed .md-typeset for MkDocs specificity ---- */ +.md-typeset .resource-table { width: 100%; - table-layout: fixed; + table-layout: auto; border-collapse: collapse; font-size: 0.82rem; line-height: 1.5; } -.resource-table th, -.resource-table td { +.md-typeset .resource-table th, +.md-typeset .resource-table td { padding: 0.3rem 0.4rem; vertical-align: top; border-bottom: 1px solid rgba(0, 0, 0, 0.12); font-size: 0.82rem; } -.resource-table thead th { +.md-typeset .resource-table thead th { + position: sticky; + top: 0; + z-index: 2; + background: #fff; font-weight: 700; -} - -/* ID column: useless to user, barely visible */ -.resource-table th:nth-child(1), -.resource-table td:nth-child(1) { - width: 2%; - text-align: center; + font-size: 0.72rem; white-space: nowrap; - font-size: 0.58rem; - color: #999; } -/* ---- MAIN TABLE: Code(18%) Type(5%) Default(auto) Descr(45%) Constr(30%) ---- */ +.md-typeset .resource-table tbody tr:nth-child(even) { + background: #fafafa; +} -.resource-table:not(.resource-table-nested) th:nth-child(2), -.resource-table:not(.resource-table-nested) td:nth-child(2) { - width: 18%; +/* ID column: HIDDEN */ +.md-typeset .resource-table th:nth-child(1), +.md-typeset .resource-table td:nth-child(1) { + display: none; +} + +/* ---- MAIN TABLE ---- */ +.md-typeset .resource-table:not(.resource-table-nested) th:nth-child(2), +.md-typeset .resource-table:not(.resource-table-nested) td:nth-child(2) { + width: 25%; + min-width: 16ch; white-space: normal; overflow-wrap: anywhere; } -.resource-table:not(.resource-table-nested) td:nth-child(2) code { +.md-typeset .resource-table:not(.resource-table-nested) td:nth-child(2) code { font-weight: 700; font-size: 0.82rem; } -.resource-table:not(.resource-table-nested) th:nth-child(3), -.resource-table:not(.resource-table-nested) td:nth-child(3) { +.md-typeset .resource-table:not(.resource-table-nested) th:nth-child(3), +.md-typeset .resource-table:not(.resource-table-nested) td:nth-child(3) { width: 5%; white-space: nowrap; font-size: 0.63rem; } -.resource-table:not(.resource-table-nested) th:nth-last-child(2), -.resource-table:not(.resource-table-nested) td:nth-last-child(2) { - width: 45%; +.md-typeset .resource-table:not(.resource-table-nested) th:nth-last-child(2), +.md-typeset .resource-table:not(.resource-table-nested) td:nth-last-child(2) { white-space: normal; overflow-wrap: anywhere; font-size: 0.63rem; color: #777; } - -.resource-table:not(.resource-table-nested) th:nth-last-child(1), -.resource-table:not(.resource-table-nested) td:nth-last-child(1) { - width: 30%; - white-space: normal; - overflow-wrap: anywhere; - word-break: break-all; - font-size: 0.72rem; +.md-typeset .resource-table:not(.resource-table-nested) td:nth-last-child(2) { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; } -/* ---- NESTED TABLE: Code(16%) Type(5%) Req(4%) Def(6%) Descr(36%) Constr(31%) ---- */ -.resource-table-nested { +.md-typeset .resource-table:not(.resource-table-nested) th:nth-last-child(1), +.md-typeset .resource-table:not(.resource-table-nested) td:nth-last-child(1) { + width: 20%; + white-space: normal; + overflow-wrap: anywhere; + font-family: ui-monospace, "Cascadia Code", "Fira Code", monospace; + font-size: 0.62rem; +} + +/* ---- NESTED TABLE ---- */ +.md-typeset .resource-table-nested { width: 100%; table-layout: fixed; } -.resource-table-nested th, -.resource-table-nested td { +.md-typeset .resource-table-nested th, +.md-typeset .resource-table-nested td { white-space: normal; overflow-wrap: anywhere; - word-break: break-word; font-size: 0.72rem; padding: 0.25rem 0.3rem; } -.resource-table-nested th:nth-child(2), -.resource-table-nested td:nth-child(2) { - width: 16%; +.md-typeset .resource-table-nested th:nth-child(2), +.md-typeset .resource-table-nested td:nth-child(2) { + width: 19%; + min-width: 16ch; } -.resource-table-nested td:nth-child(2) code { +.md-typeset .resource-table-nested td:nth-child(2) code { font-weight: 700; font-size: 0.72rem; } -.resource-table-nested th:nth-child(3), -.resource-table-nested td:nth-child(3) { - width: 5%; - white-space: nowrap; - font-size: 0.63rem; -} - -/* Required column: green ✓ instead of text "yes" */ -.resource-table-nested th:nth-child(4), -.resource-table-nested td:nth-child(4) { - width: 5%; +.md-typeset .resource-table-nested th:nth-child(4), +.md-typeset .resource-table-nested td:nth-child(4) { + width: 3%; text-align: center; white-space: nowrap; } -.resource-table-nested td:nth-child(4) strong { - display: none; +.md-typeset .resource-table-nested td:nth-child(4):not(:empty) { + font-size: 0; } -.resource-table-nested td:nth-child(4):has(strong)::before { - content: "✓"; - color: #27ae60; +.md-typeset .resource-table-nested td:nth-child(4):not(:empty)::before { + content: "★"; + color: #e74c3c; font-weight: 700; - font-size: 0.9rem; + font-size: 0.8rem; } -.resource-table-nested th:nth-child(5), -.resource-table-nested td:nth-child(5) { +.md-typeset .resource-table-nested th:nth-child(3), +.md-typeset .resource-table-nested td:nth-child(3) { + width: 5%; + white-space: nowrap; + font-size: 0.63rem; +} + +.md-typeset .resource-table-nested th:nth-child(5), +.md-typeset .resource-table-nested td:nth-child(5) { width: 6%; white-space: nowrap; color: #2c6f8c; + font-size: 0.72rem; + text-align: center; } -.resource-table-nested th:nth-child(6), -.resource-table-nested td:nth-child(6) { - width: 35%; +.md-typeset .resource-table-nested th:nth-child(6), +.md-typeset .resource-table-nested td:nth-child(6) { + width: 37%; font-size: 0.63rem; color: #777; + word-break: break-word; +} +.md-typeset .resource-table-nested td:nth-child(6) { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; } -.resource-table-nested th:nth-child(7), -.resource-table-nested td:nth-child(7) { - width: 31%; - word-break: break-all; +.md-typeset .resource-table-nested th:nth-child(7), +.md-typeset .resource-table-nested td:nth-child(7) { + width: 30%; + font-family: ui-monospace, "Cascadia Code", "Fira Code", monospace; + font-size: 0.62rem; + word-break: break-word; } .resource-table th:nth-child(7), @@ -512,3 +547,4 @@ body[data-md-url*="_instruction"] .md-typeset h3 { text-align: left; white-space: normal; } +/* v20260718-1015 */ diff --git a/docs/help/design-stage1-plan.md b/docs/help/design-stage1-plan.md new file mode 100644 index 0000000..73808bb --- /dev/null +++ b/docs/help/design-stage1-plan.md @@ -0,0 +1,35 @@ +# План редизайна таблиц документации (Этап 1 — CSS) + +> На основе рекомендаций Соннета. Только CSS, без правок генератора. + +## Что делаем + +| # | Изменение | CSS | +|---|---|---| +| 1 | Убрать ID | `display: none` на `th:nth-child(1)`, `td:nth-child(1)` | +| 2 | ★ вместо колонки Required | Скрыть `td:nth-child(4)` в nested, `::before` на Code для required строк | +| 3 | Monospace для Constraints | `font-family: monospace`, `overflow-wrap: anywhere` | +| 4 | Sticky thead | `position: sticky; top: 0` | +| 5 | line-clamp(2) Description | `-webkit-line-clamp: 2`, `overflow: hidden` | +| 6 | Zebra striping | `tr:nth-child(even) { background: #fafafa }` | +| 7 | Новые ширины колонок | Пересчёт после удаления ID и Required | + +## Новые ширины + +**Основная таблица (4 колонки, без ID):** +Code(22%) | Type(6%) | Description(42%) | Constraints(30%) + +**Основная с Default (5 колонок):** +Code(22%) | Type(5%) | Default(10%) | Description(33%) | Constraints(30%) + +**Nested (5 колонок, без ID и Required):** +★Code(22%) | Type(5%) | Default(10%) | Description(33%) | Constraints(30%) + +## Порядок действий + +1. Обновить `extra.css` +2. Скопировать в `generated/test/docs/30_registry/assets/` +3. Пересобрать `site_test` через Docker +4. Перезапустить HTTP-сервер +5. Проверить в браузере +6. Закоммитить через ВМ diff --git a/docs/help/resource-page-template.md b/docs/help/resource-page-template.md new file mode 100644 index 0000000..78f741e --- /dev/null +++ b/docs/help/resource-page-template.md @@ -0,0 +1,96 @@ +# Шаблон страницы ресурса (документация) + +> Актуально на 2026-07-18. Применять ко всем сервисам. + +## Структура страницы + +```markdown +# Resource nubes_SERVICE · Service ID: N · Service Name: DISPLAY_NAME + +**Manual** · [Create params](SERVICE_params_create.md) · [Modify params](SERVICE_params_modify.md) · [Output params](SERVICE_outputs.md) · [Operations](SERVICE_ops.md) · [Example](SERVICE_example.md) +``` + +**Правила:** +- Заголовок — ОДНА строка, разделители `·` +- Табы — активная вкладка `**жирным**`, разделители `·` +- SERVICE = имя ресурса из YAML (`spec.Name`), DISPLAY_NAME = `spec.ServiceDisplayName` + +## MAN + +```markdown +## MAN + +
+ +# Инструкция ... + +... + +
+``` + +- Весь MAN-контент внутри `
` +- Шрифт: 0.62rem (CSS: `.md-typeset .man-content`) +- Требует `md_in_html` в `mkdocs.yml` + +## Таблицы параметров + +### Основная (Create/Modify params) + +5 колонок (ID скрыт): Code | Type | (Default) | Description | Constraints + +```html + + +``` + +### Nested (map-fixed/array-map-fixed) + +7 колонок: ID | Code | Type | Required | Default | Description | Constraints +ID скрыт, Required — ★ для непустых ячеек. + +```html +
IDCodeTypeDescriptionConstraints
+ +``` + +## CSS (глобальный, `docs/30_registry/assets/extra.css`) + +| Элемент | Правило | +|---|---| +| ID колонка | `display: none` | +| Required | `td:not(:empty)::before { content: "★"; color: #e74c3c; }` | +| Code | 25% (main), 19% (nested), жирный | +| Type | 5%, 0.63rem | +| Default | 6% (nested), синий `#2c6f8c` | +| Description | line-clamp(2) на `td`, мелкий серый | +| Constraints | monospace 0.62rem, `word-break: break-word` | +| thead | sticky, nowrap, 0.72rem | +| tbody | zebra `tr:nth-child(even) { #fafafa }` | +| MAN | `.man-content { font-size: 0.62rem; }` | +| Заголовок h1 | 0.77rem | +| Табы p | 0.65rem | +| **Важно** | Все селекторы с префиксом `.md-typeset` | + +## mkdocs.yml + +Добавить в `markdown_extensions`: +```yaml +markdown_extensions: + - md_in_html +``` + +## Генератор (`TOOLS/docs-generator/internal/writers/writers.go`) + +Функции для правки: +- `buildHeader()` — заголовок + табы (одна строка, `·`, активная жирным) +- `buildManualPage()` — MAN в `
` +- `renderParamTable()` — классы таблиц +- `renderModifyTable()` — модифай без лишних колонок если пустые + +## Порядок генерации + +1. Правим `writers.go` +2. `cd TOOLS/docs-generator && go build -o ../bin/docs-generator .` +3. `./02_generate_resources_and_docs_v2.sh --profile TOOLS/config/test` +4. `mkdocs build` или `./04_build_and_publish_docs.sh` diff --git a/mkdocs.yml b/mkdocs.yml index 9e1bc60..c0850a4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -36,6 +36,7 @@ extra_javascript: - 30_registry/javascripts/fix-slash.js markdown_extensions: + - md_in_html - admonition - attr_list - toc:
IDCodeTypeRequiredDefaultDescriptionConstraints