diff --git a/Cargo.lock b/Cargo.lock
index 221b5b2..d2ce868 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -540,6 +540,7 @@ dependencies = [
"comline-codegen-rust",
"comline-codegen-typescript",
"comline-core",
+ "comline-doc-html",
"comline-doc-markdown",
"comline-runtime-conformance",
"eyre",
@@ -563,7 +564,7 @@ dependencies = [
[[package]]
name = "comline-codegen"
version = "0.1.0"
-source = "git+https://github.com/ComlineProject/generation?rev=7b51264b216ef4c5e2afbe36897a5b35dafe7e06#7b51264b216ef4c5e2afbe36897a5b35dafe7e06"
+source = "git+https://github.com/ComlineProject/generation?rev=58ff61b4a72a2bcdba6685809e615ffb614e1d8e#58ff61b4a72a2bcdba6685809e615ffb614e1d8e"
dependencies = [
"comline-core",
"eyre",
@@ -577,7 +578,7 @@ dependencies = [
[[package]]
name = "comline-codegen-rust"
version = "0.1.0"
-source = "git+https://github.com/ComlineProject/comline-rust?rev=bef9a74c028d7a44b4dc13ed677d300e061b2147#bef9a74c028d7a44b4dc13ed677d300e061b2147"
+source = "git+https://github.com/ComlineProject/comline-rust?rev=52e0eadf1c424f9486ee97d75d74cf59bbc1f191#52e0eadf1c424f9486ee97d75d74cf59bbc1f191"
dependencies = [
"comline-codegen",
"comline-core",
@@ -587,7 +588,7 @@ dependencies = [
[[package]]
name = "comline-codegen-typescript"
version = "0.1.0"
-source = "git+https://github.com/ComlineProject/comline-typescript?rev=47b54cc75b05bc52586d431d26ed4def316cf0c4#47b54cc75b05bc52586d431d26ed4def316cf0c4"
+source = "git+https://github.com/ComlineProject/comline-typescript?rev=932edaad1fd0a0dba47f8fff132149e03c0340dc#932edaad1fd0a0dba47f8fff132149e03c0340dc"
dependencies = [
"comline-codegen",
"comline-core",
@@ -628,13 +629,23 @@ name = "comline-core-stdlib"
version = "0.1.0"
source = "git+https://github.com/ComlineProject/core?rev=076cae0c3a0639b0c083b61a94f9d4913e853b3f#076cae0c3a0639b0c083b61a94f9d4913e853b3f"
+[[package]]
+name = "comline-doc-html"
+version = "0.1.0"
+source = "git+https://github.com/ComlineProject/generation?rev=58ff61b4a72a2bcdba6685809e615ffb614e1d8e#58ff61b4a72a2bcdba6685809e615ffb614e1d8e"
+dependencies = [
+ "comline-codegen",
+ "eyre",
+ "pulldown-cmark",
+ "serde_json",
+]
+
[[package]]
name = "comline-doc-markdown"
version = "0.1.0"
-source = "git+https://github.com/ComlineProject/generation?rev=7b51264b216ef4c5e2afbe36897a5b35dafe7e06#7b51264b216ef4c5e2afbe36897a5b35dafe7e06"
+source = "git+https://github.com/ComlineProject/generation?rev=58ff61b4a72a2bcdba6685809e615ffb614e1d8e#58ff61b4a72a2bcdba6685809e615ffb614e1d8e"
dependencies = [
"comline-codegen",
- "comline-core",
"eyre",
"serde",
"serde_json",
@@ -2051,6 +2062,24 @@ dependencies = [
"cc",
]
+[[package]]
+name = "pulldown-cmark"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e"
+dependencies = [
+ "bitflags 2.13.1",
+ "memchr",
+ "pulldown-cmark-escape",
+ "unicase",
+]
+
+[[package]]
+name = "pulldown-cmark-escape"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
+
[[package]]
name = "pulley-interpreter"
version = "49.0.3"
@@ -2972,6 +3001,12 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
+[[package]]
+name = "unicase"
+version = "2.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "357cc3acc6a036009fd6c973ed009037c732d60d0b4f6c673e9041497482a28f"
+
[[package]]
name = "unicode-ident"
version = "1.0.27"
diff --git a/Cargo.toml b/Cargo.toml
index 7c0494c..8ba85bf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -38,12 +38,14 @@ comline-core = { git = "https://github.com/ComlineProject/core", rev = "076cae0c
# `comline-codegen`'s types, so the rev below must be byte-identical to the
# one *they* pin - Cargo only unifies a git dependency across identical rev
# strings, and two copies of `GenRequest` are two incompatible types.
-comline-codegen = { git = "https://github.com/ComlineProject/generation", rev = "7b51264b216ef4c5e2afbe36897a5b35dafe7e06" }
-# The official Markdown documentation renderer (`comline doc`), linked in
-# like the official generators. Same generation rev as `comline-codegen`.
-comline-doc-markdown = { git = "https://github.com/ComlineProject/generation", rev = "7b51264b216ef4c5e2afbe36897a5b35dafe7e06" }
-comline-codegen-rust = { git = "https://github.com/ComlineProject/comline-rust", rev = "bef9a74c028d7a44b4dc13ed677d300e061b2147", optional = true }
-comline-codegen-typescript = { git = "https://github.com/ComlineProject/comline-typescript", rev = "47b54cc75b05bc52586d431d26ed4def316cf0c4", optional = true }
+comline-codegen = { git = "https://github.com/ComlineProject/generation", rev = "58ff61b4a72a2bcdba6685809e615ffb614e1d8e" }
+# The official Markdown and HTML documentation renderers (`comline doc`),
+# linked in like the official generators. Same generation rev as
+# `comline-codegen`.
+comline-doc-markdown = { git = "https://github.com/ComlineProject/generation", rev = "58ff61b4a72a2bcdba6685809e615ffb614e1d8e" }
+comline-doc-html = { git = "https://github.com/ComlineProject/generation", rev = "58ff61b4a72a2bcdba6685809e615ffb614e1d8e" }
+comline-codegen-rust = { git = "https://github.com/ComlineProject/comline-rust", rev = "52e0eadf1c424f9486ee97d75d74cf59bbc1f191", optional = true }
+comline-codegen-typescript = { git = "https://github.com/ComlineProject/comline-typescript", rev = "932edaad1fd0a0dba47f8fff132149e03c0340dc", optional = true }
# `comline conformance`: the conformance runner (corpus loading, judging,
# profile proofs) and its case format, a public spec. Pinned by git rev.
comline-runtime-conformance = { git = "https://github.com/ComlineProject/runtime", rev = "6f8f73a247f0aa4ac8b7041b2fdc4b02bce0e0d6" }
diff --git a/docs/cli.md b/docs/cli.md
index 9d3cbaa..81f06d5 100644
--- a/docs/cli.md
+++ b/docs/cli.md
@@ -449,7 +449,7 @@ argument matches no stored version (the error lists the versions that exist).
### `comline doc`
```
-comline doc [--out
] [--version ] [--changelog-from ] [--format markdown|json]
+comline doc [--out ] [--version ] [--changelog-from ] [--format markdown|html|json]
```
Write the package's documentation. Nothing is written to `.comline/`.
@@ -460,6 +460,14 @@ Write the package's documentation. Nothing is written to `.comline/`.
every unit with its `///` docs, fields, arguments and each protocol's wire
summary, `changelog.md` with `--changelog-from`, and `nav.yml`, a `nav` for
mkdocs or zensical.
+- **`html`** writes a self-contained static site, rendered by the official HTML
+ renderer, also linked in: `index.html`, one page per module
+ (`types/user.html`), `changelog.html` with `--changelog-from`, `style.css`
+ and `search.js`. It has the same content as the Markdown pages, plus a
+ sidebar of modules and units, a search box over the units (the index is
+ inlined in `search.js`), and light and dark themes that follow the OS
+ setting. Nothing loads from the network and every link is relative, so
+ `index.html` opens straight from disk or from any static host.
- **`json`** writes the documentation model itself, `model.json`, in the shape
of core's `schemas/doc-model.json`.
@@ -468,7 +476,7 @@ Write the package's documentation. Nothing is written to `.comline/`.
| `--out ` | `[doc] out`, else `docs/api` | where to write, relative to the project |
| `--version ` | the working tree | document a built version (a version string, a commit hash, or `HEAD`) from its frozen IR, `//!` headers included |
| `--changelog-from ` | `[doc] changelog_from` | add what changed from built version `` to the documented one |
-| `--format ` | `[doc] format`, else `markdown` | `markdown`, `json`, or another id the `[doc] renderer` offers |
+| `--format ` | `[doc] format`, else `markdown` | `markdown`, `html`, `json`, or another id the `[doc] renderer` offers |
A built version keeps no source, so with `--version` its protocols have no wire
summary. A version built before headers were stored has none.
@@ -497,6 +505,7 @@ changelog_from = "0.1.0"
comline doc
comline doc --out site/api --changelog-from 0.1.0
comline doc --version 0.2.0
+comline doc --format html --out site
comline doc --format json
```
diff --git a/src/cli.rs b/src/cli.rs
index 671ad0f..e09b2e1 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -112,8 +112,10 @@ version string, a commit hash or `HEAD`), which is documented from its frozen \
IR, `//!` headers included. A built version keeps no source, so its protocols \
have no wire summary.
-`--format json` writes the documentation model itself (`model.json`), for \
-other tools. `comline.toml`'s `[doc]` table sets the defaults: `out` \
+`--format html` writes a self-contained static site instead: `index.html`, \
+one page per module, `changelog.html`, a stylesheet and a search script, all \
+linked relatively, so `index.html` opens straight from disk. `--format json` \
+writes the documentation model itself (`model.json`), for other tools. `comline.toml`'s `[doc]` table sets the defaults: `out` \
(`docs/api`), `format` (`markdown`), `renderer` (an external renderer, run \
like an external generator), `links` (dependency docs URLs) and \
`changelog_from`.
@@ -122,6 +124,7 @@ Examples:
comline doc
comline doc --out site/api --changelog-from 0.1.0
comline doc --version 0.2.0
+ comline doc --format html --out site
comline doc --format json")]
Doc {
/// Output directory; default from `[doc] out`, else `docs/api`
@@ -136,7 +139,7 @@ Examples:
#[arg(long, value_name = "VERSION")]
changelog_from: Option,
- /// `markdown` (pages) or `json` (the model); default from `[doc] format`
+ /// `markdown` (pages), `html` (a static site) or `json` (the model); default from `[doc] format`
#[arg(long, value_name = "FORMAT")]
format: Option,
},
diff --git a/src/commands/doc.rs b/src/commands/doc.rs
index ae40a6f..d0ca6b8 100644
--- a/src/commands/doc.rs
+++ b/src/commands/doc.rs
@@ -4,8 +4,8 @@
//! compiled working tree, or from a built version's frozen IR and `//!`
//! headers with `--version`. `--changelog-from` adds what changed since an
//! earlier built version. `--format json` writes the model itself; any other
-//! format is a renderer's id, `markdown` being the official one, linked in
-//! like the official generators. `[doc] renderer` in `comline.toml` names an
+//! format is a renderer's id: `markdown` and `html` are the official ones,
+//! linked in like the official generators. `[doc] renderer` in `comline.toml` names an
//! external renderer instead, run exactly like an external generator
//! ([`crate::external`]: the same sandbox, limits and path checks).
//!
@@ -39,6 +39,7 @@ pub struct Flags {
pub(crate) fn renderer_registry() -> Registry {
let mut registry = Registry::new();
comline_doc_markdown::register(&mut registry);
+ comline_doc_html::register(&mut registry);
registry
}
diff --git a/tests/cli/doc.rs b/tests/cli/doc.rs
index 4f74d8f..3825b36 100644
--- a/tests/cli/doc.rs
+++ b/tests/cli/doc.rs
@@ -137,10 +137,73 @@ fn an_unknown_format_names_what_is_offered() {
comline_cmd()
.current_dir(&shop)
- .args(["doc", "--format", "html"])
+ .args(["doc", "--format", "pdf"])
.assert()
.failure()
- .stderr(predicate::str::contains(
- "doesn't render `html`; it offers `markdown`",
- ));
+ .stderr(predicate::str::contains("doesn't render `pdf`; it offers"))
+ .stderr(predicate::str::contains("`html`"))
+ .stderr(predicate::str::contains("`markdown`"));
+}
+
+#[test]
+fn html_writes_a_self_contained_site() {
+ let temp = tempfile::tempdir().unwrap();
+ let shop = temp.path().join("shop");
+ package(&shop, "//! A shop.\n\n", API);
+ comline_cmd()
+ .current_dir(&shop)
+ .arg("build")
+ .assert()
+ .success();
+
+ comline_cmd()
+ .current_dir(&shop)
+ .args([
+ "doc",
+ "--format",
+ "html",
+ "--out",
+ "site",
+ "--changelog-from",
+ "0.1.0-dev.1",
+ ])
+ .assert()
+ .success();
+
+ let out = shop.join("site");
+ let index = read(&out.join("index.html"));
+ assert!(index.starts_with(""), "{index}");
+ assert!(index.contains("
shop
\n
A shop.
"), "{index}");
+ assert!(index.contains("api"));
+ let api = read(&out.join("api.html"));
+ assert!(
+ api.contains("