diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | checks/simple-mdbook/.gitignore | 1 | ||||
-rw-r--r-- | checks/simple-mdbook/book.toml | 6 | ||||
-rw-r--r-- | checks/simple-mdbook/src/SUMMARY.md | 5 | ||||
-rw-r--r-- | checks/simple-mdbook/src/chapter_1.md | 1 | ||||
-rw-r--r-- | checks/simple-mdbook/src/chapter_2-1.md | 1 | ||||
-rw-r--r-- | checks/simple-mdbook/src/chapter_2.md | 1 | ||||
-rw-r--r-- | doc-options-md.nix | 52 | ||||
-rw-r--r-- | flake.lock | 27 | ||||
-rw-r--r-- | flake.nix | 104 | ||||
-rw-r--r-- | manpage.nix | 136 | ||||
-rw-r--r-- | mdbook.nix | 45 |
12 files changed, 381 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..750baeb --- /dev/null +++ b/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | result | ||
2 | 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 @@ | |||
1 | [book] | ||
2 | authors = ["Minijackson"] | ||
3 | language = "en" | ||
4 | multilingual = false | ||
5 | src = "src" | ||
6 | 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 @@ | |||
1 | # Summary | ||
2 | |||
3 | - [Chapter 1](./chapter_1.md) | ||
4 | - [Chapter 2](./chapter_2.md) | ||
5 | - [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 @@ | |||
1 | { outputAttrPath, optionsAttrPath, optionsInternal ? true, }: | ||
2 | |||
3 | { lib, options, pkgs, ... }: | ||
4 | |||
5 | with lib; | ||
6 | |||
7 | let | ||
8 | visibleOptionDocs = filter (opt: opt.visible && !opt.internal) (optionAttrSetToDocList options); | ||
9 | |||
10 | toValue = value: | ||
11 | if value ? _type && value._type == "literalExpression" then value.text | ||
12 | else generators.toPretty { } value; | ||
13 | |||
14 | toMarkdown = option: | ||
15 | '' | ||
16 | ## `${option.name}` | ||
17 | |||
18 | ${option.description} | ||
19 | |||
20 | ${optionalString (option ? default) '' | ||
21 | **Default value**: | ||
22 | |||
23 | ```nix | ||
24 | ${toValue option.default} | ||
25 | ``` | ||
26 | ''} | ||
27 | |||
28 | **Type**: ${option.type}${optionalString option.readOnly " (read only)"} | ||
29 | |||
30 | ${optionalString (option ? example) '' | ||
31 | **Example**: | ||
32 | |||
33 | ```nix | ||
34 | ${toValue option.example} | ||
35 | ``` | ||
36 | ''} | ||
37 | |||
38 | Declared in: | ||
39 | |||
40 | ${concatStringsSep "\n" (map (decl: "- ${decl}") option.declarations)} | ||
41 | |||
42 | ''; | ||
43 | |||
44 | # TODO: rewrite "Declared in" so that it points to GitHub repository | ||
45 | |||
46 | options-md = concatStringsSep "\n" (map toMarkdown visibleOptionDocs); | ||
47 | in | ||
48 | { | ||
49 | config = setAttrByPath outputAttrPath { | ||
50 | doc-options-md = pkgs.writeText "options.md" options-md; | ||
51 | }; | ||
52 | } | ||
diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..842821c --- /dev/null +++ b/flake.lock | |||
@@ -0,0 +1,27 @@ | |||
1 | { | ||
2 | "nodes": { | ||
3 | "nixpkgs": { | ||
4 | "locked": { | ||
5 | "lastModified": 1636196544, | ||
6 | "narHash": "sha256-15s56Yu3vF8Na4yx4HkNc3997WZltOIB2CT1sOiCKKM=", | ||
7 | "owner": "NixOS", | ||
8 | "repo": "nixpkgs", | ||
9 | "rev": "ce48bcdde86eef5780a60bea55b9bc9dbd8248cd", | ||
10 | "type": "github" | ||
11 | }, | ||
12 | "original": { | ||
13 | "owner": "NixOS", | ||
14 | "ref": "nixos-21.05", | ||
15 | "repo": "nixpkgs", | ||
16 | "type": "github" | ||
17 | } | ||
18 | }, | ||
19 | "root": { | ||
20 | "inputs": { | ||
21 | "nixpkgs": "nixpkgs" | ||
22 | } | ||
23 | } | ||
24 | }, | ||
25 | "root": "root", | ||
26 | "version": 7 | ||
27 | } | ||
diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..2826989 --- /dev/null +++ b/flake.nix | |||
@@ -0,0 +1,104 @@ | |||
1 | { | ||
2 | description = "Generate documentation for your own projects using the NixOS module system"; | ||
3 | |||
4 | inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.05"; | ||
5 | |||
6 | outputs = { self, nixpkgs }: | ||
7 | let pkgs = nixpkgs.legacyPackages.x86_64-linux; | ||
8 | in | ||
9 | { | ||
10 | |||
11 | lib.modules = { | ||
12 | doc-options-md = import ./doc-options-md.nix; | ||
13 | mdbook = import ./mdbook.nix; | ||
14 | manpage = import ./manpage.nix; | ||
15 | }; | ||
16 | |||
17 | checks.x86_64-linux = | ||
18 | let | ||
19 | evalModules = modules: pkgs.lib.evalModules { | ||
20 | modules = [ | ||
21 | ({ config._module.args = { inherit pkgs; }; }) | ||
22 | ] ++ modules; | ||
23 | }; | ||
24 | simpleModule = with pkgs.lib; { | ||
25 | options.my.simple.module.outputs = mkOption { | ||
26 | type = with types; attrsOf package; | ||
27 | default = { }; | ||
28 | description = '' | ||
29 | Output products of my simple module system. | ||
30 | ''; | ||
31 | }; | ||
32 | }; | ||
33 | params = { | ||
34 | outputAttrPath = [ "my" "simple" "module" "outputs" ]; | ||
35 | optionsAttrPath = [ "my" "simple" "module" "doc" ]; | ||
36 | optionsInternal = false; | ||
37 | }; | ||
38 | |||
39 | simple-manpage = { | ||
40 | name = "my simple module system"; | ||
41 | shortDescription = "A sample module system"; | ||
42 | }; | ||
43 | |||
44 | advanced-manpage = { | ||
45 | name = "my simple module system"; | ||
46 | section = 5; | ||
47 | shortDescription = "A sample module system"; | ||
48 | description = '' | ||
49 | This is a very advanced module system, for advanced people. | ||
50 | ''; | ||
51 | |||
52 | textBefore = '' | ||
53 | # A SECTION BEFORE | ||
54 | |||
55 | This is a section before the options. | ||
56 | ''; | ||
57 | |||
58 | textAfter = '' | ||
59 | # A SECTION AFTER | ||
60 | |||
61 | This is a section after the options. | ||
62 | ''; | ||
63 | }; | ||
64 | in | ||
65 | { | ||
66 | simple-doc-options-md = (evalModules [ | ||
67 | simpleModule | ||
68 | (self.lib.modules.doc-options-md params) | ||
69 | ]).config.my.simple.module.outputs.doc-options-md; | ||
70 | |||
71 | simple-manpage = (evalModules [ | ||
72 | simpleModule | ||
73 | (self.lib.modules.doc-options-md params) | ||
74 | (self.lib.modules.manpage params) | ||
75 | { | ||
76 | my.simple.module.doc.manpage = simple-manpage; | ||
77 | } | ||
78 | ]).config.my.simple.module.outputs.manpage; | ||
79 | |||
80 | advanced-manpage = (evalModules [ | ||
81 | simpleModule | ||
82 | (self.lib.modules.doc-options-md params) | ||
83 | (self.lib.modules.manpage params) | ||
84 | { | ||
85 | my.simple.module.doc.manpage = advanced-manpage; | ||
86 | } | ||
87 | ]).config.my.simple.module.outputs.manpage; | ||
88 | |||
89 | simple-mdbook = (evalModules [ | ||
90 | simpleModule | ||
91 | (self.lib.modules.doc-options-md params) | ||
92 | (self.lib.modules.mdbook params) | ||
93 | { | ||
94 | my.simple.module.doc.mdbook.src = ./checks/simple-mdbook; | ||
95 | } | ||
96 | ]).config.my.simple.module.outputs.mdbook; | ||
97 | |||
98 | }; | ||
99 | |||
100 | devShell.x86_64-linux = pkgs.mkShell { | ||
101 | nativeBuildInputs = with pkgs; [ mdbook pandoc ]; | ||
102 | }; | ||
103 | }; | ||
104 | } | ||
diff --git a/manpage.nix b/manpage.nix new file mode 100644 index 0000000..bea6b25 --- /dev/null +++ b/manpage.nix | |||
@@ -0,0 +1,136 @@ | |||
1 | { outputAttrPath, optionsAttrPath, optionsInternal ? true, }: | ||
2 | |||
3 | { config, lib, pkgs, ... }: | ||
4 | |||
5 | with lib; | ||
6 | |||
7 | let | ||
8 | cfg = getAttrFromPath (optionsAttrPath ++ [ "manpage" ]) config; | ||
9 | in | ||
10 | { | ||
11 | options = setAttrByPath optionsAttrPath { | ||
12 | manpage = { | ||
13 | name = mkOption { | ||
14 | type = types.str; | ||
15 | description = '' | ||
16 | Name of the generated manpage. | ||
17 | ''; | ||
18 | internal = optionsInternal; | ||
19 | }; | ||
20 | |||
21 | shortDescription = mkOption { | ||
22 | type = types.str; | ||
23 | description = '' | ||
24 | A short description of the generated manpage. | ||
25 | ''; | ||
26 | internal = optionsInternal; | ||
27 | }; | ||
28 | |||
29 | description = mkOption { | ||
30 | type = with types; nullOr lines; | ||
31 | description = '' | ||
32 | A long description of the generated manpage. | ||
33 | ''; | ||
34 | default = null; | ||
35 | internal = optionsInternal; | ||
36 | }; | ||
37 | |||
38 | section = mkOption { | ||
39 | type = types.int; | ||
40 | default = 5; | ||
41 | description = '' | ||
42 | The section number for the generated manpage. | ||
43 | |||
44 | The table below shows the section numbers of the manual followed by the types of pages they contain. | ||
45 | |||
46 | 1. Executable programs or shell commands | ||
47 | 2. System calls (functions provided by the kernel) | ||
48 | 3. Library calls (functions within program libraries) | ||
49 | 4. Special files (usually found in /dev) | ||
50 | 5. File formats and conventions, e.g. /etc/passwd | ||
51 | 6. Games | ||
52 | 7. Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7) | ||
53 | 8. System administration commands (usually only for root) | ||
54 | 9. Kernel routines [Non standard] | ||
55 | ''; | ||
56 | internal = optionsInternal; | ||
57 | }; | ||
58 | |||
59 | file = mkOption { | ||
60 | type = types.str; | ||
61 | description = '' | ||
62 | The file containing the generated manpage. | ||
63 | ''; | ||
64 | default = "${strings.sanitizeDerivationName cfg.name}.${toString cfg.section}"; | ||
65 | defaultText = "\${lib.strings.sanitizeDerivationName cfg.name}.\${toString cfg.section}"; | ||
66 | internal = optionsInternal; | ||
67 | }; | ||
68 | |||
69 | title = mkOption { | ||
70 | type = types.str; | ||
71 | default = "${toUpper (strings.sanitizeDerivationName cfg.name)}(${toString cfg.section})"; | ||
72 | defaultText = "\${toUpper cfg.name}(\${toString cfg.section})"; | ||
73 | description = '' | ||
74 | Title of the generated manpage. | ||
75 | ''; | ||
76 | internal = optionsInternal; | ||
77 | }; | ||
78 | |||
79 | textBefore = mkOption { | ||
80 | type = types.lines; | ||
81 | description = '' | ||
82 | Some text to insert before the list of options. | ||
83 | ''; | ||
84 | default = ""; | ||
85 | internal = optionsInternal; | ||
86 | }; | ||
87 | |||
88 | textAfter = mkOption { | ||
89 | type = types.lines; | ||
90 | description = '' | ||
91 | Some text to insert after the list of options. | ||
92 | ''; | ||
93 | default = ""; | ||
94 | internal = optionsInternal; | ||
95 | }; | ||
96 | |||
97 | }; | ||
98 | }; | ||
99 | |||
100 | config = setAttrByPath outputAttrPath { | ||
101 | manpage = pkgs.runCommand cfg.file | ||
102 | { | ||
103 | src = pkgs.writeText "${cfg.file}.md" '' | ||
104 | % ${cfg.title} | ||
105 | |||
106 | # NAME | ||
107 | |||
108 | ${cfg.name} - ${cfg.shortDescription} | ||
109 | |||
110 | |||
111 | ${optionalString (cfg.description != null) '' | ||
112 | # DESCRIPTION | ||
113 | |||
114 | ${cfg.description} | ||
115 | ''} | ||
116 | |||
117 | |||
118 | ${cfg.textBefore} | ||
119 | |||
120 | |||
121 | # OPTIONS | ||
122 | |||
123 | You can use the following options: | ||
124 | |||
125 | ${readFile (getAttrFromPath (outputAttrPath ++ ["doc-options-md"]) config)} | ||
126 | |||
127 | |||
128 | ${cfg.textAfter} | ||
129 | ''; | ||
130 | |||
131 | nativeBuildInputs = [ pkgs.pandoc ]; | ||
132 | } '' | ||
133 | pandoc "$src" --from=markdown --to=man --standalone --output="$out" | ||
134 | ''; | ||
135 | }; | ||
136 | } | ||
diff --git a/mdbook.nix b/mdbook.nix new file mode 100644 index 0000000..d336042 --- /dev/null +++ b/mdbook.nix | |||
@@ -0,0 +1,45 @@ | |||
1 | { outputAttrPath, optionsAttrPath, optionsInternal ? true, }: | ||
2 | |||
3 | { config, lib, pkgs, ... }: | ||
4 | |||
5 | with lib; | ||
6 | |||
7 | let | ||
8 | cfg = getAttrFromPath (optionsAttrPath ++ [ "mdbook" ]) config; | ||
9 | in | ||
10 | { | ||
11 | options = setAttrByPath optionsAttrPath { | ||
12 | mdbook = { | ||
13 | src = mkOption { | ||
14 | type = with types; either path package; | ||
15 | description = '' | ||
16 | Root directory of mdbook sources to compile. | ||
17 | ''; | ||
18 | internal = optionsInternal; | ||
19 | }; | ||
20 | }; | ||
21 | }; | ||
22 | |||
23 | config = setAttrByPath outputAttrPath { | ||
24 | # TODO: make pandoc pre-processor | ||
25 | mdbook = pkgs.runCommand "mdbook" | ||
26 | { | ||
27 | src = cfg.src; | ||
28 | nativeBuildInputs = with pkgs; [ mdbook ]; | ||
29 | } '' | ||
30 | unpackFile "$src" | ||
31 | chmod -R u+w . | ||
32 | cd */ | ||
33 | |||
34 | mkdir theme | ||
35 | cp ${pkgs.documentation-highlighter}/highlight.pack.js theme/highlight.js | ||
36 | cp ${pkgs.documentation-highlighter}/mono-blue.css theme/highlight.css | ||
37 | |||
38 | cp "${getAttrFromPath (outputAttrPath ++ ["doc-options-md"]) config}" src/options.md | ||
39 | |||
40 | mdbook build | ||
41 | |||
42 | cp -r book "$out" | ||
43 | ''; | ||
44 | }; | ||
45 | } | ||