summaryrefslogtreecommitdiffhomepage
path: root/dlang/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'dlang/README.md')
-rw-r--r--dlang/README.md85
1 files changed, 85 insertions, 0 deletions
diff --git a/dlang/README.md b/dlang/README.md
new file mode 100644
index 0000000..e3a41b6
--- /dev/null
+++ b/dlang/README.md
@@ -0,0 +1,85 @@
+# ocda-write, in D
+
+Sample writers over the abstraction:
+
+ ocda-write --text|--md|--html|--epub|--typst <file> [lang]
+ ocda-write --md <file> [lang] [--image-prefix <path>]
+
+writes a document out, from any serialisation of its abstraction.
+
+## Modules
+
+| | |
+|---|---|
+| `write.text` | the model -> spine's plain text, byte for byte |
+| `write.html` | the model -> one self-contained, valid html5 file |
+| `write.epub` | the model -> an epub3, one file per segment |
+| `write.markdown` | the model -> CommonMark, object numbers and all |
+| `write.typst` | the model -> typst markup, for a pdf |
+| `write.zip` | writing a zip, stored only, with no timestamps |
+| `write.rgx` | the internal markup, as regular expressions |
+| `main` | the program: which format, which file, which language |
+
+`write.text` takes an `OcdaDocument` and returns a string. It is given no
+file, no path and no option: a writer is a function from the model to bytes,
+and everything it needs is in the model.
+
+## Build and run
+
+```sh
+nix build --override-input ocda-lib path:../../sisudoc-ocda-lib
+./result/bin/ocda-write --text <doc>.ssp
+./result/bin/ocda-write --html <doc>.ocda.db de
+./result/bin/ocda-write --html <doc>.sisupod
+./result/bin/ocda-write --md <doc>.ssp
+./result/bin/ocda-write --epub <doc>.ocda.db en --out <doc>.epub
+./result/bin/ocda-write --typst <doc>.ocda.db en --out out/<doc>.typ
+typst compile --root out out/<doc>.typ out/<doc>.pdf
+```
+
+`--epub` writes a zip, so it takes `--out` rather than stdout. `--typst` goes
+to stdout too, but with `--out` it also writes the `image/` directory the
+`.typ` names.
+
+`nix build .#ocda-write-dmd` builds with dmd instead of ldc.
+
+The library's modules are compiled alongside these rather than linked as a
+separate product; for five modules a second build step buys nothing.
+
+## The checks
+
+`--text` and `--md` are checked against the html writer's objects, word for
+word, and against each other language's writer, byte for byte: **36 of 36 on
+every count.** Byte identity with `spine --text` was the first oracle and is
+no longer the target; see the repository README.
+
+`--html` is checked harder still: it parses, every `href="#x"`
+resolves, no id appears twice, no heading falls outside `h1`..`h6`, and the
+objects' visible text equals spine's scroll html exactly. **36 of 36 on each,
+and byte identical to the Gleam writer.** See the repository README for what
+it does differently from spine and why.
+
+`--epub` is judged by `epubcheck`, and `--typst` by typst: a link to a label
+that does not exist is a compile error, so a silent compile means every
+internal link in the document resolves. **36 of 36 on each, and byte
+identical to the Gleam writer.**
+
+## Where it is faithful rather than sensible
+
+The *text* writer reproduces spine's output exactly, which means reproducing
+what would not be chosen from scratch. The comments say so at each point.
+The three worth knowing before reading the code:
+
+- **the table layout strips trailing whitespace from the whole accumulated
+ table after every cell**, not once per row, so a row ending in an empty
+ cell loses the newline before it;
+- **a column's width is the widest cell in bytes and the padding is counted
+ in codepoints**, so a cell holding `©` is padded one place further than one
+ holding `c`;
+- **the section sequence is spine's `scroll` sequence**, not its `text` one:
+ head, toc, body, then each trailing section *that has more than one
+ object*, and no `tail` unless an html or epub output was also asked for.
+
+The *html* writer takes none of these as given. What it takes from the model
+and what it declines to take from spine is set out in its own comments, at
+the point where each choice is made.