krz/orgo

Lightning fast org-mode static site generator. fast go org-mode static-site-generator

Commit 70dc5827f4

70dc5827f43c0191692808873a7abfe825950f79

parent: ef9a625b5d

Verified · cmc

cmc <hello@cleberg.net> · 2026-08-30 06:53 UTC

audit: an unlisted keyword is pass-through, not a blind spot (#2)

The census legend said `???` marks "a name the implementation does not
recognize at all". On orgo's own docs it marked `LEDE`, which the shipped docs
template reads as `page.keywords.lede`, `themes/docs.css` styles, and
`docs/guide/02-configuration.org` documents.

Reaching templates as `page.keywords.<name>` is the designed behaviour, so
every keyword name works and none is a blind spot; `???` on one was a statement
about orgo's source, not about the corpus. Which keywords have dedicated
handling is still worth reporting, so the distinction stays and the marker
changes: `—` for pass-through, `???` reserved for drawers and link schemes,
where an unlisted name has no such fallback.

`is_known` becomes `marker`, which returns the report's marker directly. The
marker column is now a consistent four columns wide — `??? ` was one wider than
the blank it replaced, so flagged rows sat a character right of the rest.

Closes #2

Layout: unified · split

docs/guide/09-auditing.org +9 −3
@@ -31,8 +31,9 @@ IN special block 1 1 blog/2026-03-03-auditing
3131coverage: 9002 in-scope use(s) (100.0%), 0 out-of-scope (0.0%)
3232
3333KEYWORDS
34 SLUG 180 180 blog/2018-11-28-aes-encryption.org:4
35 TITLE 180 180 blog/2018-11-28-aes-encryption.org:2
34 SLUG 180 180 blog/2018-11-28-aes-encryption.org:4
35 TITLE 180 180 blog/2018-11-28-aes-encryption.org:2
36— LEDE 14 14 blog/2018-11-28-aes-encryption.org:3
3637...
3738#+END_EXAMPLE
3839
@@ -41,7 +42,12 @@ KEYWORDS
4142- The *coverage* line is the number to look at first.
4243- =???= marks a name orgo does not recognise at all. That is the blind-spot signal —
4344 not "known unsupported", but unknown — and this corpus has none. Block names never
44 carry it: an unrecognised one is still a special block, and still renders.
45 carry it: an unrecognised one is still a special block, and still renders. Keyword
46 names never carry it either — see below.
47- =—= marks a keyword with no dedicated handling. It is not a gap: the keyword reaches
48 your layout as ={{ page.keywords.<name> }}=, which is the designed behaviour, so the
49 marker tells you which of your keywords orgo reads by name and which rely on that
50 pass-through.
4551
4652Four censuses follow the construct table: every distinct =#+KEYWORD:=, block type,
4753drawer name and link scheme in the corpus. A =???= in any of them is worth a look.
fixtures/audit-keywords.org added +5
@@ -0,0 +1,5 @@
1#+TITLE: Keyword census
2#+LEDE: A keyword the shipped docs template reads.
3#+PROJECT_STATUS: A keyword nothing reads by name.
4
5Body text.
src/audit.rs +34 −18
@@ -71,9 +71,9 @@ pub struct Audit {
7171 pub link_schemes: BTreeMap<String, Tally>,
7272}
7373
74/// Names the implementation understands, so the census can flag everything else. These
75/// are the *recognized* sets, not the supported ones: `INCLUDE` is recognized (it is
76/// deliberately inert) while an unlisted keyword is a genuine blind spot.
74/// Names the implementation reads by name, so the census can mark everything else. These
75/// are the *recognized* sets, not the supported ones: `INCLUDE` is recognized and
76/// deliberately inert.
7777const KNOWN_KEYWORDS: &[&str] = &[
7878 "TITLE", "AUTHOR", "DATE", "EMAIL", "LANGUAGE", "OPTIONS", "FILETAGS", "DESCRIPTION",
7979 "KEYWORDS", "CAPTION", "NAME", "ATTR_HTML", "RESULTS", "TBLFM", "INCLUDE", "TODO",
@@ -97,20 +97,36 @@ const KNOWN_SCHEMES: &[&str] = &[
9797 "relative",
9898];
9999
100/// The census markers. A name with dedicated handling carries none; `PASS_THROUGH` says
101/// nothing reads the name but it works anyway; `UNKNOWN` is the blind-spot signal.
102const HANDLED: &str = "";
103const PASS_THROUGH: &str = "\u{2014}";
104const UNKNOWN: &str = "???";
105
100106impl Audit {
101 /// Is this name one the implementation recognizes?
102 pub fn is_known(kind: Census, name: &str) -> bool {
103 let known = match kind {
104 Census::Keyword => KNOWN_KEYWORDS,
107 /// How the report marks a census name: the recognized set to look the name up in,
108 /// and what an unlisted name means for that census.
109 pub fn marker(kind: Census, name: &str) -> &'static str {
110 let (known, unlisted) = match kind {
111 // An unlisted keyword is not a blind spot. Reaching templates as
112 // `page.keywords.<name>` is the designed behaviour, so every keyword name
113 // works; what the census reports is which ones have dedicated handling.
114 // `LEDE`, read by the shipped docs theme's template, was the case that made
115 // this concrete: `???` on it was a claim about orgo's source, not a gap.
116 Census::Keyword => (KNOWN_KEYWORDS, PASS_THROUGH),
105117 // Every block name renders, and renders as org renders it: the names in
106118 // `block_construct` through dedicated handling, every other name as a special
107119 // block — a div carrying the name, holding parsed org, which is exactly what
108120 // org's exporter emits. No block name is a blind spot.
109 Census::Block => return true,
110 Census::Drawer => KNOWN_DRAWERS,
111 Census::Scheme => KNOWN_SCHEMES,
121 Census::Block => return HANDLED,
122 Census::Drawer => (KNOWN_DRAWERS, UNKNOWN),
123 Census::Scheme => (KNOWN_SCHEMES, UNKNOWN),
112124 };
113 known.iter().any(|k| k.eq_ignore_ascii_case(name))
125 if known.iter().any(|k| k.eq_ignore_ascii_case(name)) {
126 HANDLED
127 } else {
128 unlisted
129 }
114130 }
115131}
116132
@@ -644,13 +660,9 @@ pub fn report(audit: &Audit) -> String {
644660 names.sort_by(|a, b| b.1.occurrences.cmp(&a.1.occurrences).then(a.0.cmp(b.0)));
645661 out.push_str(&format!("\n{title}\n"));
646662 for (name, tally) in names {
647 let flag = if Audit::is_known(kind, name) {
648 " "
649 } else {
650 "??? "
651 };
652663 out.push_str(&format!(
653 "{flag}{:<32} {:>8} {:>7} {}\n",
664 "{:<4}{:<32} {:>8} {:>7} {}\n",
665 Audit::marker(kind, name),
654666 name,
655667 tally.occurrences,
656668 tally.files,
@@ -658,6 +670,10 @@ pub fn report(audit: &Audit) -> String {
658670 ));
659671 }
660672 }
661 out.push_str("\n`???` marks a name the implementation does not recognize at all.\n");
673 out.push_str(
674 "\n`???` marks a name the implementation does not recognize at all.\n\
675 `\u{2014}` marks a keyword with no dedicated handling; it reaches templates \
676 as `page.keywords.<name>`.\n",
677 );
662678 out
663679}
tests/constructs.rs +17
@@ -859,3 +859,20 @@ fn audit_ignores_constructs_inside_verbatim() {
859859 );
860860 }
861861}
862
863/// An unlisted keyword is not a blind spot: reaching templates as `page.keywords.<name>`
864/// is the designed behaviour, so it is marked as pass-through rather than `???`, which
865/// claims orgo does not recognise the name at all.
866#[test]
867fn audit_marks_unhandled_keywords_as_pass_through() {
868 let report = audit_fixture("audit-keywords.org");
869 for name in ["LEDE", "PROJECT_STATUS"] {
870 let line = report.lines().find(|l| l.contains(name)).expect("the keyword is censused");
871 assert!(
872 line.starts_with('\u{2014}'),
873 "a keyword that reaches templates must not read as a blind spot:\n{line}"
874 );
875 }
876 let flagged: Vec<&str> = report.lines().filter(|l| l.starts_with("???")).collect();
877 assert!(flagged.is_empty(), "no keyword name is unrecognised: {flagged:?}");
878}