diff --git a/TOOLS/docs-generator/internal/writers/writers.go b/TOOLS/docs-generator/internal/writers/writers.go index 5cfe4de..6a6421a 100644 --- a/TOOLS/docs-generator/internal/writers/writers.go +++ b/TOOLS/docs-generator/internal/writers/writers.go @@ -29,19 +29,19 @@ func ResourceDocs(docsDir string, spec types.ServiceSpec, version string, apiEnd 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+".md"), buildManualPage(spec, navManual, version)) 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)) + WriteFile(filepath.Join(docsDir, base+"_params_create.md"), buildCreateParamsPage(spec, navCreate, version)) + WriteFile(filepath.Join(docsDir, base+"_params_modify.md"), buildModifyParamsPage(spec, navModify, version)) + WriteFile(filepath.Join(docsDir, base+"_outputs.md"), buildOutputsPage(spec, navOutputs, version)) + WriteFile(filepath.Join(docsDir, base+"_ops.md"), buildOpsPage(spec, navOps, version, docsDir)) + WriteFile(filepath.Join(docsDir, base+"_params.md"), buildParamsLandingPage(spec, navManual, version)) for _, srName := range CollectSubresources(spec) { srBase := fmt.Sprintf("%s_%s", base, Slug(srName)) srNav := fmt.Sprintf("[%s (основной)](%s.md) | [Operations](%s_ops.md) | [%s](%s.md) | [Example](%s_example.md)", spec.ServiceDisplayName, base, base, Capitalize(srName), srBase, srBase) - WriteFile(filepath.Join(docsDir, srBase+".md"), buildSubresourcePage(spec, srName, srNav)) + WriteFile(filepath.Join(docsDir, srBase+".md"), buildSubresourcePage(spec, srName, srNav, version)) WriteFile(filepath.Join(docsDir, srBase+"_example.md"), buildSubresourceExamplePage(spec, srName, srNav, version, apiEndpoint, providerSource)) } } @@ -69,18 +69,35 @@ func WriteFile(path, content string) { } } -// IndexMD генерирует index.md. +// IndexMD генерирует index.md с группировкой по категориям. func IndexMD(docsDir string, specs []types.ServiceSpec) { + catMap := map[string][]types.ServiceSpec{} + for _, s := range specs { + cat := serviceCategory(s.Name) + catMap[cat] = append(catMap[cat], s) + } + var b bytes.Buffer b.WriteString("# Ресурсы провайдера\n\n") - b.WriteString("| ID | Ресурс | Описание |\n") - b.WriteString("|-----|--------|----------|\n") - for _, spec := range specs { - resName := "nubes_" + spec.Name - link := fmt.Sprintf("[%s](%s.md)", resName, spec.Name) - descr := strings.ReplaceAll(spec.ServiceDisplayName, "|", "\\|") - b.WriteString(fmt.Sprintf("| %d | %s | %s |\n", spec.ServiceID, link, descr)) + + order := []string{"Базы данных", "Очереди", "Хранилище", "K8s", "VMware", "Приложения", "Сеть", "Другие"} + for _, cat := range order { + svcs := catMap[cat] + if len(svcs) == 0 { + continue + } + b.WriteString(fmt.Sprintf("## %s\n\n", cat)) + b.WriteString("| ID | Ресурс | Описание |\n") + b.WriteString("|-----|--------|----------|\n") + for _, spec := range svcs { + resName := "nubes_" + spec.Name + link := fmt.Sprintf("[%s](%s.md)", resName, spec.Name) + descr := strings.ReplaceAll(spec.ServiceDisplayName, "|", "\\|") + b.WriteString(fmt.Sprintf("| %d | %s | %s |\n", spec.ServiceID, link, descr)) + } + b.WriteString("\n") } + outPath := filepath.Join(docsDir, "index.md") if err := os.WriteFile(outPath, b.Bytes(), 0o644); err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to write index.md: %v\n", err) @@ -123,17 +140,17 @@ func FindSubresourceParams(ops []types.OperationSpec, srName, action string) []t // ===== internal helpers ===== -func buildHeader(spec types.ServiceSpec, nav string) string { +func buildHeader(spec types.ServiceSpec, nav string, version string) string { name := spec.ServiceDisplayName if name == "" { name = spec.Name } - return fmt.Sprintf("# Resource nubes_%s · Service ID: %d · Service Name: %s\n\n%s\n\n", spec.Name, spec.ServiceID, name, nav) + return fmt.Sprintf("# Resource nubes_%s · v%s · Service ID: %d · Service Name: %s\n\n%s\n\n", spec.Name, version, spec.ServiceID, name, nav) } -func buildManualPage(spec types.ServiceSpec, nav string) string { +func buildManualPage(spec types.ServiceSpec, nav string, version string) string { var b strings.Builder - b.WriteString(buildHeader(spec, nav)) + b.WriteString(buildHeader(spec, nav, version)) b.WriteString("## MAN\n\n") man := strings.TrimSpace(spec.ServiceMan) if man == "" { @@ -186,7 +203,7 @@ func htmlToMarkdown(s string) string { func buildExamplePage(spec types.ServiceSpec, nav string, version string, apiEndpoint string, providerSource string) string { var b strings.Builder - b.WriteString(buildHeader(spec, nav)) + b.WriteString(buildHeader(spec, nav, version)) b.WriteString(fmt.Sprintf("## Minimal example — only required parameters\n\n")) b.WriteString("```hcl\n") b.WriteString(minimalExampleBlock(spec, version, apiEndpoint, providerSource)) @@ -281,9 +298,9 @@ func minimalExampleBlock(spec types.ServiceSpec, version string, apiEndpoint str return b.String() } -func buildCreateParamsPage(spec types.ServiceSpec, nav string) string { +func buildCreateParamsPage(spec types.ServiceSpec, nav string, version string) string { var b strings.Builder - b.WriteString(buildHeader(spec, nav)) + b.WriteString(buildHeader(spec, nav, version)) b.WriteString("## Create params\n\n") createParams := FindParams(spec.Operations, "create") requiredParams, defaultParams := SplitParams(createParams) @@ -322,18 +339,18 @@ func buildCreateParamsPage(spec types.ServiceSpec, nav string) string { return b.String() } -func buildModifyParamsPage(spec types.ServiceSpec, nav string) string { +func buildModifyParamsPage(spec types.ServiceSpec, nav string, version string) string { var b strings.Builder - b.WriteString(buildHeader(spec, nav)) + b.WriteString(buildHeader(spec, nav, version)) b.WriteString("## Modify params\n\n") modifyParams := FindParams(spec.Operations, "modify") b.WriteString(renderModifyTable(modifyParams)) return b.String() } -func buildOutputsPage(spec types.ServiceSpec, nav string) string { +func buildOutputsPage(spec types.ServiceSpec, nav string, version string) string { var b strings.Builder - b.WriteString(buildHeader(spec, nav)) + b.WriteString(buildHeader(spec, nav, version)) b.WriteString("## Output params\n\n") if len(spec.Outputs.Params) == 0 { b.WriteString("None.\n") @@ -406,9 +423,9 @@ func containsString(values []string, target string) bool { return false } -func buildOpsPage(spec types.ServiceSpec, nav string, docsDir string) string { +func buildOpsPage(spec types.ServiceSpec, nav string, version string, docsDir string) string { var b strings.Builder - b.WriteString(buildHeader(spec, nav)) + b.WriteString(buildHeader(spec, nav, version)) b.WriteString("## Operations\n\n") for _, op := range spec.Operations { name := op.Name @@ -454,16 +471,16 @@ func buildOpsPage(spec types.ServiceSpec, nav string, docsDir string) string { return b.String() } -func buildParamsLandingPage(spec types.ServiceSpec, nav string) string { +func buildParamsLandingPage(spec types.ServiceSpec, nav string, version string) string { var b strings.Builder - b.WriteString(buildHeader(spec, nav)) + b.WriteString(buildHeader(spec, nav, version)) b.WriteString("## Parameters\n\n") b.WriteString(fmt.Sprintf("- [Create params](%s_params_create.md)\n", spec.Name)) b.WriteString(fmt.Sprintf("- [Modify params](%s_params_modify.md)\n", spec.Name)) return b.String() } -func buildSubresourcePage(spec types.ServiceSpec, srName string, nav string) string { +func buildSubresourcePage(spec types.ServiceSpec, srName string, nav string, version string) string { var b strings.Builder srResourceName := fmt.Sprintf("nubes_%s_%s", spec.Name, Slug(srName)) b.WriteString(fmt.Sprintf("# Resource %s\n\n", srResourceName)) diff --git a/TOOLS/scripts/04_build_and_publish_docs.sh b/TOOLS/scripts/04_build_and_publish_docs.sh index 3e89f4a..40cc1c9 100755 --- a/TOOLS/scripts/04_build_and_publish_docs.sh +++ b/TOOLS/scripts/04_build_and_publish_docs.sh @@ -158,9 +158,19 @@ load_s3cfg_registry() { TMP_CFG="${ROOT_DIR}/.mkdocs.tmp.yml" export ROOT_DIR + +# Copy 30_registry assets into docs dir so guides/nav work when docs_dir is external +if [[ -n "${MKDOCS_DOCS_DIR:-}" ]]; then + if [[ -d "${ROOT_DIR}/docs/30_registry" ]]; then + mkdir -p "${MKDOCS_DOCS_DIR}/30_registry" + cp -r "${ROOT_DIR}/docs/30_registry/"* "${MKDOCS_DOCS_DIR}/30_registry/" 2>/dev/null || true + fi +fi + python3 - <<'PY' import os import re +import yaml from pathlib import Path registry_host = os.environ["REGISTRY_HOST"] @@ -185,6 +195,23 @@ if docs_dir: else: text += f"\ndocs_dir: {docs_dir}\n" +# Inject resources_nav from _nav_fragment.yml into nav section +docs_dir_path = Path(docs_dir) if docs_dir else None +nav_fragment_path = docs_dir_path / "_nav_fragment.yml" if docs_dir_path else None +if nav_fragment_path and nav_fragment_path.exists(): + config = yaml.safe_load(text) + fragment = yaml.safe_load(nav_fragment_path.read_text(encoding="utf-8")) + resources_nav = fragment.get("resources_nav", []) + if resources_nav: + nav = config.get("nav", []) + for i, item in enumerate(nav): + if isinstance(item, dict) and "Ресурсы" in item: + # Replace "Ресурсы" children with generated categories + item["Ресурсы"] = resources_nav + break + config["nav"] = nav + text = yaml.dump(config, allow_unicode=True, default_flow_style=False, sort_keys=False) + (root_dir / ".mkdocs.tmp.yml").write_text(text, encoding="utf-8") PY diff --git a/docs/30_registry/assets/extra.css b/docs/30_registry/assets/extra.css index 9e5a219..da70810 100644 --- a/docs/30_registry/assets/extra.css +++ b/docs/30_registry/assets/extra.css @@ -18,11 +18,7 @@ line-height: 1.35; } -/* Resource pages: no sidebars, normal scrolling */ -.md-sidebar--primary { - display: none !important; -} - +/* Resource pages: right sidebar (TOC) hidden, left sidebar visible */ .md-sidebar--secondary { display: none !important; } @@ -48,7 +44,7 @@ } .md-typeset .man-content { - font-size: 0.62rem; + font-size: 0.78rem; line-height: 1.4; }