krz/orgo

Lightning fast org-mode static site generator.

clone: git clone https://gitbay.org/krz/orgo.git

2eac492d17d6d5a1062e0cae8af31ad7c35dc76b

signed_unknown_key

author: Christian Cleberg <hello@cleberg.net> · 2026-08-23T05:13:13Z
committer: <noreply@github.com>

audit: entities are supported, not out of scope (#30)

`\alpha` renders as `&alpha;` in orgo exactly as in Emacs, from an entity table
generated out of org's own `org-entities`. The audit counted every use as
out-of-scope anyway, and `docs/guide/05-org-support.org` listed entities under
"Not supported, and what happens instead" as rendering to "Literal text" — while
the Supported section three tables above documented all 412 names, the
`\alphabet` boundary and `#+OPTIONS: e:nil`. The document contradicted itself.

`fixtures/audit-entities.org` joins the Emacs oracle, which reports 100%
agreement with 0 unexplained lines.

The out-of-scope fixture still reports 10 genuine gaps, so this narrows what the
audit calls a gap without blunting it.
 docs/guide/05-org-support.org |  1 -
 src/audit.rs                  |  4 +++-
 tests/constructs.rs           | 13 ++++++++++---
 tests/oracle.rs               |  1 +
 4 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/docs/guide/05-org-support.org b/docs/guide/05-org-support.org
index 70213a7..fb220a4 100644
--- a/docs/guide/05-org-support.org
+++ b/docs/guide/05-org-support.org
@@ -186,7 +186,6 @@ a build.
 | Macros ={{{name}}}=, radio targets | Literal text. |
 | Drawers other than =PROPERTIES= | Captured and dropped, including =LOGBOOK=. |
 | Non-HTML export blocks | Dropped entirely. |
-| Entities =\alpha= | Literal text. |
 | =#+TODO:= sequences | Not read; the default keyword set is used. |
 | Planning lines, =: = fixed-width | Render as ordinary paragraphs. |
 
diff --git a/src/audit.rs b/src/audit.rs
index 9981e35..1a0e34a 100644
--- a/src/audit.rs
+++ b/src/audit.rs
@@ -345,7 +345,9 @@ impl Audit {
             self.count(Scope::Out, "LaTeX fragment", at);
         }
         if entity_ref(line) {
-            self.count(Scope::Out, "entity (\\name)", at);
+            // Rendered, and rendered as org renders it: `\alpha` becomes `&alpha;` in
+            // both exporters. `fixtures/audit-entities.org` holds the oracle to that.
+            self.count(Scope::In, "entity (\\name)", at);
         }
         for (marker, name) in [
             ('*', "bold"),
diff --git a/tests/constructs.rs b/tests/constructs.rs
index 93bb1c8..88647ca 100644
--- a/tests/constructs.rs
+++ b/tests/constructs.rs
@@ -388,6 +388,7 @@ fn well_formed_fixtures_produce_no_diagnostics() {
         "timestamps.org",
         "images.org",
         "tblfm.org",
+        "audit-entities.org",
     ] {
         let document = parse_fixture(name);
         assert!(
@@ -792,13 +793,19 @@ fn audit_ignores_backslashes_that_are_not_entities() {
     );
 }
 
-/// A bare entity outside verbatim still counts.
+/// A bare entity outside verbatim still counts, and counts as supported: `\alpha`
+/// becomes `&alpha;` in orgo exactly as in Emacs, which the oracle checks on this same
+/// fixture. The 412 names come from org's own `org-entities`.
 #[test]
 fn audit_counts_real_entities() {
     let report = audit_fixture("audit-entities.org");
+    let line = report
+        .lines()
+        .find(|l| l.contains("entity (\\name)"))
+        .expect("a real entity is counted");
     assert!(
-        report.contains("entity (\\name)"),
-        "a real entity was not counted:\n{report}"
+        line.starts_with("IN "),
+        "an entity orgo renders exactly as Emacs does must not read as a gap:\n{line}"
     );
 }
 
diff --git a/tests/oracle.rs b/tests/oracle.rs
index fc0fbe6..dfce0bd 100644
--- a/tests/oracle.rs
+++ b/tests/oracle.rs
@@ -629,6 +629,7 @@ fn every_divergence_from_emacs_is_deliberate() {
         "images.org",
         "elements.org",
         "tblfm.org",
+        "audit-entities.org",
     ];
     let mut offenders = Vec::new();
     for fixture in fixtures {