diff --git a/.github/scripts/generate-nix-options-docs.py b/.github/scripts/generate-nix-options-docs.py index 23cd3b90..6f5d35bd 100755 --- a/.github/scripts/generate-nix-options-docs.py +++ b/.github/scripts/generate-nix-options-docs.py @@ -1,80 +1,112 @@ #!/usr/bin/env python3 """ -Converts NixOS options JSON into clean, table-formatted Markdown. +Converts NixOS options JSON into clean Markdown documentation. """ import json import sys import re +SECTIONS = [ + { + "title": "NixOS", + "subtitle": "**System-level options via `programs.mango`.**", + }, + { + "title": "Home Manager", + "subtitle": "**Configure mangowm declaratively via `wayland.windowManager.mango`.**", + }, +] + +HEADER = ( + "---\n" + "title: Nix Module Options\n" + "description: NixOS and Home Manager configuration options for mangowm.\n" + "---\n\n" + "> **Note:** This document is automatically generated from the Nix module source code.\n\n" +) + def clean_description(desc: str) -> str: - """Removes Nix tags, fixes dangling periods, and formats blockquotes.""" + """Strips Nix inline markup tags, fixes dangling periods, and formats blockquotes.""" if not desc: return "*No description provided.*" - desc = re.sub(r'\{[a-zA-Z]+\}', '', desc).replace('\n.', '.') + # Strip Nix inline markup: {tag}`content` → `content`; bare tags → "" + desc = re.sub(r'\{(?:var|option|manpage|file|env|command|program)\}(`[^`]+`)', r'\1', desc) + desc = re.sub(r'\{(?:var|option|manpage|file|env|command|program)\}', '', desc) + # Remove period left on its own line after tag removal + desc = re.sub(r'\n\s*\.(\s|$)', r'.\1', desc) lines = desc.splitlines() cleaned = [] - in_note = False - + in_block = False + for line in lines: - if line.startswith("::: {.note"): - in_note = True - cleaned.append("> **Note:**\n>") + m = re.match(r':::\s*\{\.(\w+)\}', line) + if m: + block_type = m.group(1).capitalize() + in_block = True + cleaned.append(f"> **{block_type}:**\n>") elif line.startswith(":::"): - in_note = False + in_block = False else: - cleaned.append(f"> {line}" if in_note else line) + cleaned.append(f"> {line}" if in_block else line) return "\n".join(cleaned) -def format_default_value(default_data) -> str: - """Safely formats the default value, handling HTML escaping for tables.""" - if default_data is None: - return "*None*" +def format_value(val_data) -> str: + """Formats a value as inline code or a nix code block.""" + if val_data is None: + return None - val_text = default_data.get("text", "") if isinstance(default_data, dict) and default_data.get("_type") == "literalExpression" else str(default_data) - val_text = val_text.replace('|', '|') + if isinstance(val_data, dict) and val_data.get("_type") == "literalMD": + return val_data.get("text", "").strip() + elif isinstance(val_data, dict) and val_data.get("_type") == "literalExpression": + text = val_data.get("text", "").strip() + elif isinstance(val_data, bool): + text = "true" if val_data else "false" + elif val_data == {} or val_data == []: + text = "{ }" if val_data == {} else "[ ]" + else: + text = str(val_data).strip() - if '\n' in val_text: - safe_html = val_text.replace('<', '<').replace('>', '>').replace('\n', '
') - return f"{safe_html}" - - return f"`{val_text}`" + if '\n' in text: + return f"\n```nix\n{text}\n```" + return f"`{text}`" + +def write_section(out, data, title, subtitle): + out.write(f"## {title}\n\n{subtitle}\n\n") + for key, opt in sorted(data.items()): + if key.startswith("_module"): + continue + + desc = clean_description(opt.get("description", "")) + opt_type = str(opt.get("type", "unknown")) + default_val = format_value(opt.get("default")) + example_val = format_value(opt.get("example")) + + block = f"### `{key}`\n\n{desc}\n\n**Type:** `{opt_type}`\n\n" + if default_val is not None: + block += f"**Default:** {default_val}\n\n" + if example_val is not None: + block += f"**Example:** {example_val}\n\n" + block += "---\n\n" + out.write(block) def main(): if len(sys.argv) != 4: - sys.exit("Usage: format_docs.py ") + sys.exit("Usage: generate-nix-options-docs.py <nixos.json> <hm.json> <output.md>") - input_json, output_md, title = sys.argv[1:4] + nixos_json, hm_json, output_md = sys.argv[1:4] + inputs = [nixos_json, hm_json] - with open(input_json, 'r', encoding='utf-8') as f: - data = json.load(f) - - with open(output_md, 'a', encoding='utf-8') as out: - out.write(f"## {title}\n\n") - - for key, opt in sorted(data.items()): - if key.startswith("_module"): - continue - - desc = clean_description(opt.get("description", "")) - opt_type = str(opt.get("type", "unknown")).replace('|', '|') - default_val = format_default_value(opt.get("default")) - - markdown_block = ( - f"### `{key}`\n\n" - f"{desc}\n\n" - f"| Attribute | Value |\n" - f"| :--- | :--- |\n" - f"| **Type** | `{opt_type}` |\n" - f"| **Default** | {default_val} |\n\n" - f"---\n\n" - ) - out.write(markdown_block) - - print(f"Appended {title} to {output_md} successfully.") + with open(output_md, 'w', encoding='utf-8') as out: + out.write(HEADER) + for path, section in zip(inputs, SECTIONS): + with open(path, 'r', encoding='utf-8') as f: + data = json.load(f) + write_section(out, data, section["title"], section["subtitle"]) + print(f"Written {section['title']} section.") if __name__ == "__main__": main() diff --git a/.github/workflows/generate-nix-options-docs.yml b/.github/workflows/generate-nix-options-docs.yml index e5fd0df2..465146be 100644 --- a/.github/workflows/generate-nix-options-docs.yml +++ b/.github/workflows/generate-nix-options-docs.yml @@ -6,6 +6,7 @@ on: - 'nix/**-modules.nix' - 'nix/generate-options.nix' - 'flake.nix' + - '.github/scripts/generate-nix-options-docs.py' pull_request: paths: - 'nix/**-modules.nix' @@ -35,20 +36,10 @@ jobs: - name: Format to Markdown run: | - OUTPUT_FILE="docs/nix-options.md" - - cat << 'EOF' > $OUTPUT_FILE - --- - title: Nix Module Options - description: NixOS and Home Manager configuration options for mangowm. - --- - - > **Note:** This document is automatically generated from the Nix module source code. - - EOF - - python3 ./.github/scripts/generate-nix-options-docs.py result-nixos/share/doc/nixos/options.json $OUTPUT_FILE "NixOS Module Options" - python3 ./.github/scripts/generate-nix-options-docs.py result-hm/share/doc/nixos/options.json $OUTPUT_FILE "Home Manager Options" + python3 ./.github/scripts/generate-nix-options-docs.py \ + result-nixos/share/doc/nixos/options.json \ + result-hm/share/doc/nixos/options.json \ + docs/nix-options.md - name: Auto-commit changes uses: stefanzweifel/git-auto-commit-action@v5 diff --git a/nix/hm-modules.nix b/nix/hm-modules.nix index f00d9c68..f9a341a3 100644 --- a/nix/hm-modules.nix +++ b/nix/hm-modules.nix @@ -22,6 +22,7 @@ in enable = mkOption { type = types.bool; default = false; + description = "Whether to enable mangowm, a Wayland compositor based on dwl."; }; package = lib.mkOption { type = lib.types.package;