From c7026a993c4b837dcee39f669e1cc4123f4eb53d Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 8 Nov 2021 16:26:42 +0100 Subject: initial commit --- .gitignore | 2 + checks/simple-mdbook/.gitignore | 1 + checks/simple-mdbook/book.toml | 6 ++ checks/simple-mdbook/src/SUMMARY.md | 5 ++ checks/simple-mdbook/src/chapter_1.md | 1 + checks/simple-mdbook/src/chapter_2-1.md | 1 + checks/simple-mdbook/src/chapter_2.md | 1 + doc-options-md.nix | 52 ++++++++++++ flake.lock | 27 +++++++ flake.nix | 104 ++++++++++++++++++++++++ manpage.nix | 136 ++++++++++++++++++++++++++++++++ mdbook.nix | 45 +++++++++++ 12 files changed, 381 insertions(+) create mode 100644 .gitignore create mode 100644 checks/simple-mdbook/.gitignore create mode 100644 checks/simple-mdbook/book.toml create mode 100644 checks/simple-mdbook/src/SUMMARY.md create mode 100644 checks/simple-mdbook/src/chapter_1.md create mode 100644 checks/simple-mdbook/src/chapter_2-1.md create mode 100644 checks/simple-mdbook/src/chapter_2.md create mode 100644 doc-options-md.nix create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 manpage.nix create mode 100644 mdbook.nix diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..750baeb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +result +result-* diff --git a/checks/simple-mdbook/.gitignore b/checks/simple-mdbook/.gitignore new file mode 100644 index 0000000..7585238 --- /dev/null +++ b/checks/simple-mdbook/.gitignore @@ -0,0 +1 @@ +book diff --git a/checks/simple-mdbook/book.toml b/checks/simple-mdbook/book.toml new file mode 100644 index 0000000..425d511 --- /dev/null +++ b/checks/simple-mdbook/book.toml @@ -0,0 +1,6 @@ +[book] +authors = ["Minijackson"] +language = "en" +multilingual = false +src = "src" +title = "Simple MdBook" diff --git a/checks/simple-mdbook/src/SUMMARY.md b/checks/simple-mdbook/src/SUMMARY.md new file mode 100644 index 0000000..9cebd5b --- /dev/null +++ b/checks/simple-mdbook/src/SUMMARY.md @@ -0,0 +1,5 @@ +# Summary + +- [Chapter 1](./chapter_1.md) +- [Chapter 2](./chapter_2.md) + - [Chapter 2.2](./chapter_2-1.md) diff --git a/checks/simple-mdbook/src/chapter_1.md b/checks/simple-mdbook/src/chapter_1.md new file mode 100644 index 0000000..b743fda --- /dev/null +++ b/checks/simple-mdbook/src/chapter_1.md @@ -0,0 +1 @@ +# Chapter 1 diff --git a/checks/simple-mdbook/src/chapter_2-1.md b/checks/simple-mdbook/src/chapter_2-1.md new file mode 100644 index 0000000..b5cb2dc --- /dev/null +++ b/checks/simple-mdbook/src/chapter_2-1.md @@ -0,0 +1 @@ +# Chapter 2.2 diff --git a/checks/simple-mdbook/src/chapter_2.md b/checks/simple-mdbook/src/chapter_2.md new file mode 100644 index 0000000..7ebb596 --- /dev/null +++ b/checks/simple-mdbook/src/chapter_2.md @@ -0,0 +1 @@ +# Chapter 2 diff --git a/doc-options-md.nix b/doc-options-md.nix new file mode 100644 index 0000000..ea21746 --- /dev/null +++ b/doc-options-md.nix @@ -0,0 +1,52 @@ +{ outputAttrPath, optionsAttrPath, optionsInternal ? true, }: + +{ lib, options, pkgs, ... }: + +with lib; + +let + visibleOptionDocs = filter (opt: opt.visible && !opt.internal) (optionAttrSetToDocList options); + + toValue = value: + if value ? _type && value._type == "literalExpression" then value.text + else generators.toPretty { } value; + + toMarkdown = option: + '' + ## `${option.name}` + + ${option.description} + + ${optionalString (option ? default) '' + **Default value**: + + ```nix + ${toValue option.default} + ``` + ''} + + **Type**: ${option.type}${optionalString option.readOnly " (read only)"} + + ${optionalString (option ? example) '' + **Example**: + + ```nix + ${toValue option.example} + ``` + ''} + + Declared in: + + ${concatStringsSep "\n" (map (decl: "- ${decl}") option.declarations)} + + ''; + + # TODO: rewrite "Declared in" so that it points to GitHub repository + + options-md = concatStringsSep "\n" (map toMarkdown visibleOptionDocs); +in +{ + config = setAttrByPath outputAttrPath { + doc-options-md = pkgs.writeText "options.md" options-md; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..842821c --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1636196544, + "narHash": "sha256-15s56Yu3vF8Na4yx4HkNc3997WZltOIB2CT1sOiCKKM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ce48bcdde86eef5780a60bea55b9bc9dbd8248cd", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-21.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..2826989 --- /dev/null +++ b/flake.nix @@ -0,0 +1,104 @@ +{ + description = "Generate documentation for your own projects using the NixOS module system"; + + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.05"; + + outputs = { self, nixpkgs }: + let pkgs = nixpkgs.legacyPackages.x86_64-linux; + in + { + + lib.modules = { + doc-options-md = import ./doc-options-md.nix; + mdbook = import ./mdbook.nix; + manpage = import ./manpage.nix; + }; + + checks.x86_64-linux = + let + evalModules = modules: pkgs.lib.evalModules { + modules = [ + ({ config._module.args = { inherit pkgs; }; }) + ] ++ modules; + }; + simpleModule = with pkgs.lib; { + options.my.simple.module.outputs = mkOption { + type = with types; attrsOf package; + default = { }; + description = '' + Output products of my simple module system. + ''; + }; + }; + params = { + outputAttrPath = [ "my" "simple" "module" "outputs" ]; + optionsAttrPath = [ "my" "simple" "module" "doc" ]; + optionsInternal = false; + }; + + simple-manpage = { + name = "my simple module system"; + shortDescription = "A sample module system"; + }; + + advanced-manpage = { + name = "my simple module system"; + section = 5; + shortDescription = "A sample module system"; + description = '' + This is a very advanced module system, for advanced people. + ''; + + textBefore = '' + # A SECTION BEFORE + + This is a section before the options. + ''; + + textAfter = '' + # A SECTION AFTER + + This is a section after the options. + ''; + }; + in + { + simple-doc-options-md = (evalModules [ + simpleModule + (self.lib.modules.doc-options-md params) + ]).config.my.simple.module.outputs.doc-options-md; + + simple-manpage = (evalModules [ + simpleModule + (self.lib.modules.doc-options-md params) + (self.lib.modules.manpage params) + { + my.simple.module.doc.manpage = simple-manpage; + } + ]).config.my.simple.module.outputs.manpage; + + advanced-manpage = (evalModules [ + simpleModule + (self.lib.modules.doc-options-md params) + (self.lib.modules.manpage params) + { + my.simple.module.doc.manpage = advanced-manpage; + } + ]).config.my.simple.module.outputs.manpage; + + simple-mdbook = (evalModules [ + simpleModule + (self.lib.modules.doc-options-md params) + (self.lib.modules.mdbook params) + { + my.simple.module.doc.mdbook.src = ./checks/simple-mdbook; + } + ]).config.my.simple.module.outputs.mdbook; + + }; + + devShell.x86_64-linux = pkgs.mkShell { + nativeBuildInputs = with pkgs; [ mdbook pandoc ]; + }; + }; +} diff --git a/manpage.nix b/manpage.nix new file mode 100644 index 0000000..bea6b25 --- /dev/null +++ b/manpage.nix @@ -0,0 +1,136 @@ +{ outputAttrPath, optionsAttrPath, optionsInternal ? true, }: + +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = getAttrFromPath (optionsAttrPath ++ [ "manpage" ]) config; +in +{ + options = setAttrByPath optionsAttrPath { + manpage = { + name = mkOption { + type = types.str; + description = '' + Name of the generated manpage. + ''; + internal = optionsInternal; + }; + + shortDescription = mkOption { + type = types.str; + description = '' + A short description of the generated manpage. + ''; + internal = optionsInternal; + }; + + description = mkOption { + type = with types; nullOr lines; + description = '' + A long description of the generated manpage. + ''; + default = null; + internal = optionsInternal; + }; + + section = mkOption { + type = types.int; + default = 5; + description = '' + The section number for the generated manpage. + + The table below shows the section numbers of the manual followed by the types of pages they contain. + + 1. Executable programs or shell commands + 2. System calls (functions provided by the kernel) + 3. Library calls (functions within program libraries) + 4. Special files (usually found in /dev) + 5. File formats and conventions, e.g. /etc/passwd + 6. Games + 7. Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7) + 8. System administration commands (usually only for root) + 9. Kernel routines [Non standard] + ''; + internal = optionsInternal; + }; + + file = mkOption { + type = types.str; + description = '' + The file containing the generated manpage. + ''; + default = "${strings.sanitizeDerivationName cfg.name}.${toString cfg.section}"; + defaultText = "\${lib.strings.sanitizeDerivationName cfg.name}.\${toString cfg.section}"; + internal = optionsInternal; + }; + + title = mkOption { + type = types.str; + default = "${toUpper (strings.sanitizeDerivationName cfg.name)}(${toString cfg.section})"; + defaultText = "\${toUpper cfg.name}(\${toString cfg.section})"; + description = '' + Title of the generated manpage. + ''; + internal = optionsInternal; + }; + + textBefore = mkOption { + type = types.lines; + description = '' + Some text to insert before the list of options. + ''; + default = ""; + internal = optionsInternal; + }; + + textAfter = mkOption { + type = types.lines; + description = '' + Some text to insert after the list of options. + ''; + default = ""; + internal = optionsInternal; + }; + + }; + }; + + config = setAttrByPath outputAttrPath { + manpage = pkgs.runCommand cfg.file + { + src = pkgs.writeText "${cfg.file}.md" '' + % ${cfg.title} + + # NAME + + ${cfg.name} - ${cfg.shortDescription} + + + ${optionalString (cfg.description != null) '' + # DESCRIPTION + + ${cfg.description} + ''} + + + ${cfg.textBefore} + + + # OPTIONS + + You can use the following options: + + ${readFile (getAttrFromPath (outputAttrPath ++ ["doc-options-md"]) config)} + + + ${cfg.textAfter} + ''; + + nativeBuildInputs = [ pkgs.pandoc ]; + } '' + pandoc "$src" --from=markdown --to=man --standalone --output="$out" + ''; + }; +} diff --git a/mdbook.nix b/mdbook.nix new file mode 100644 index 0000000..d336042 --- /dev/null +++ b/mdbook.nix @@ -0,0 +1,45 @@ +{ outputAttrPath, optionsAttrPath, optionsInternal ? true, }: + +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = getAttrFromPath (optionsAttrPath ++ [ "mdbook" ]) config; +in +{ + options = setAttrByPath optionsAttrPath { + mdbook = { + src = mkOption { + type = with types; either path package; + description = '' + Root directory of mdbook sources to compile. + ''; + internal = optionsInternal; + }; + }; + }; + + config = setAttrByPath outputAttrPath { + # TODO: make pandoc pre-processor + mdbook = pkgs.runCommand "mdbook" + { + src = cfg.src; + nativeBuildInputs = with pkgs; [ mdbook ]; + } '' + unpackFile "$src" + chmod -R u+w . + cd */ + + mkdir theme + cp ${pkgs.documentation-highlighter}/highlight.pack.js theme/highlight.js + cp ${pkgs.documentation-highlighter}/mono-blue.css theme/highlight.css + + cp "${getAttrFromPath (outputAttrPath ++ ["doc-options-md"]) config}" src/options.md + + mdbook build + + cp -r book "$out" + ''; + }; +} -- cgit v1.2.3