ssh git@grit.deadkey.org man

Commit b70d686 h

Pat Ambrosio · 26-09-05 10:21

Take the parser's escape-by-default contract

Changes: 3 files +16 -9

Changes (Side-by-Side)

share/jenny/lib/markdown.awk +1 -1

1 Subproject commit 8cd72df31b3ae05a98735b419311da6274329401
1 Subproject commit e518a9122b6d709032ecfd669f2446fdad7a36c9

test/regressions.sh +9 -3

md_render() {
770 printf '%s\n' "$1" | "$AWK" -f "$JENNY_SHARE_DIR/lib/markdown.awk/markdown.awk" 770 printf '%s\n' "$1" | "$AWK" -f "$JENNY_SHARE_DIR/lib/markdown.awk/markdown.awk"
771 } 771 }
772 772
773 # Raw HTML is escaped unless the caller asks for passthrough. The tests that
774 # examine how markdown interacts with real tags need the tags to survive.
775 md_unsafe() {
776 printf '%s\n' "$1" | "$AWK" -v UNSAFE_HTML=1 -f "$JENNY_SHARE_DIR/lib/markdown.awk/markdown.awk"
777 }
778
773 it "a two-space child nests inside its parent" 779 it "a two-space child nests inside its parent"
774 out=$(md_render '- a 780 out=$(md_render '- a
775 - b 781 - b
suite "underscores in inline HTML"
845 it "an underscore that is a tag's whole content is literal" 851 it "an underscore that is a tag's whole content is literal"
846 # <span class="us">_</span> writes a visible underscore. It opened an <em> 852 # <span class="us">_</span> writes a visible underscore. It opened an <em>
847 # that swallowed the markup after it. 853 # that swallowed the markup after it.
848 assert_contains "$(md_render 'x <span class="us">_</span> y')" '<span class="us">_</span>'
854 assert_contains "$(md_unsafe 'x <span class="us">_</span> y')" '<span class="us">_</span>'
849 855
850 it "two such underscores do not pair across their tags" 856 it "two such underscores do not pair across their tags"
851 # They emitted mis-nested "<b><em></b> ... <b></em></b>". 857 # They emitted mis-nested "<b><em></b> ... <b></em></b>".
852 pair=$(md_render 'A <b>_</b> and <b>_</b> here.')
858 pair=$(md_unsafe 'A <b>_</b> and <b>_</b> here.')
853 assert_contains "$pair" '<b>_</b> and <b>_</b>' 859 assert_contains "$pair" '<b>_</b> and <b>_</b>'
854 assert_not_contains "$pair" '<em>' 860 assert_not_contains "$pair" '<em>'
855 861
it "bold still works"
860 assert_contains "$(md_render 'Real __bold__ here.')" '<strong>bold</strong>' 866 assert_contains "$(md_render 'Real __bold__ here.')" '<strong>bold</strong>'
861 867
862 it "emphasis spanning a tag still works" 868 it "emphasis spanning a tag still works"
863 assert_contains "$(md_render 'A _em <b>x</b> more_ end.')" '<em>em <b>x</b> more</em>'
869 assert_contains "$(md_unsafe 'A _em <b>x</b> more_ end.')" '<em>em <b>x</b> more</em>'
864 870
865 it "intraword underscores are still literal" 871 it "intraword underscores are still literal"
866 assert_contains "$(md_render 'Use node_modules and snake_case_name.')" 'node_modules and snake_case_name' 872 assert_contains "$(md_render 'Use node_modules and snake_case_name.')" 'node_modules and snake_case_name'

test/units.sh +6 -5

After.')" "<p>After.</p>"
651 it "a pipe in prose is not a table" 651 it "a pipe in prose is not a table"
652 assert_not_contains "$(md 'a | b in ordinary prose')" "<table>" 652 assert_not_contains "$(md 'a | b in ordinary prose')" "<table>"
653 653
654 # Markdown deliberately allows inline HTML, in cells as in prose.
655 # multimarkdown 6.6.0 emits <th> <b>x</b> </th> for this, and jenny's own
656 # prose handling passes raw HTML through too, so a cell must not differ.
657 it "raw html in a cell passes through, as in prose"
654 # A cell must handle raw HTML exactly as prose does. That used to mean both
655 # passed it through; it now means both escape it unless the caller asks for
656 # passthrough with UNSAFE_HTML=1. What matters is that a cell is not a hole in
657 # whichever rule is in force.
658 it "raw html in a cell is escaped, as in prose"
658 assert_contains "$(md '| <b>x</b> | 659 assert_contains "$(md '| <b>x</b> |
659 |---| 660 |---|
660 | a |')" "<b>x</b>"
661 | a |')" "&lt;b&gt;x&lt;/b&gt;"
661 662
662 it "a table inside a fence is literal" 663 it "a table inside a fence is literal"
663 assert_contains "$(md '``` 664 assert_contains "$(md '```

Raw

commit b70d686e1e58f5abc33df834b07d71a10aa1cd1c
Author: Pat Ambrosio <cp.ambrosio@gmail.com>
Date:   Sat Sep 5 10:21:34 2026 +0800

    Take the parser's escape-by-default contract
    
    Raw HTML is escaped now unless the caller asks for passthrough, so the
    four tests here that assert passthrough had to say which contract they
    are testing.
    
    The table-cell test keeps its point: a cell must handle raw HTML exactly
    as prose does. That used to mean both passed it through and now means
    both escape it, and what it guards is that a cell is not a hole in
    whichever rule is in force.
    
    The three inline-HTML tests examine how underscores interact with real
    tags -- an underscore that is a tag's whole content, two that must not
    pair across their tags, emphasis spanning one. That is only observable
    while the tags survive, so they ask for passthrough explicitly.
    
    jenny itself passes no flag, so pages are built with the safe reading.
    Nothing on the site relied on passthrough: rebuilt, no escaped tags
    appear anywhere in the output.

diff --git a/share/jenny/lib/markdown.awk b/share/jenny/lib/markdown.awk
index 8cd72df..e518a91 160000
--- a/share/jenny/lib/markdown.awk
+++ b/share/jenny/lib/markdown.awk
@@ -1 +1 @@
-Subproject commit 8cd72df31b3ae05a98735b419311da6274329401
+Subproject commit e518a9122b6d709032ecfd669f2446fdad7a36c9
diff --git a/test/regressions.sh b/test/regressions.sh
index 8db745f..e63a470 100755
--- a/test/regressions.sh
+++ b/test/regressions.sh
@@ -770,6 +770,12 @@ md_render() {
   printf '%s\n' "$1" | "$AWK" -f "$JENNY_SHARE_DIR/lib/markdown.awk/markdown.awk"
 }
 
+# Raw HTML is escaped unless the caller asks for passthrough. The tests that
+# examine how markdown interacts with real tags need the tags to survive.
+md_unsafe() {
+  printf '%s\n' "$1" | "$AWK" -v UNSAFE_HTML=1 -f "$JENNY_SHARE_DIR/lib/markdown.awk/markdown.awk"
+}
+
 it "a two-space child nests inside its parent"
 out=$(md_render '- a
   - b
@@ -845,11 +851,11 @@ suite "underscores in inline HTML"
 it "an underscore that is a tag's whole content is literal"
 # <span class="us">_</span> writes a visible underscore. It opened an <em>
 # that swallowed the markup after it.
-assert_contains "$(md_render 'x <span class="us">_</span> y')" '<span class="us">_</span>'
+assert_contains "$(md_unsafe 'x <span class="us">_</span> y')" '<span class="us">_</span>'
 
 it "two such underscores do not pair across their tags"
 # They emitted mis-nested "<b><em></b> ... <b></em></b>".
-pair=$(md_render 'A <b>_</b> and <b>_</b> here.')
+pair=$(md_unsafe 'A <b>_</b> and <b>_</b> here.')
 assert_contains "$pair" '<b>_</b> and <b>_</b>'
 assert_not_contains "$pair" '<em>'
 
@@ -860,7 +866,7 @@ it "bold still works"
 assert_contains "$(md_render 'Real __bold__ here.')" '<strong>bold</strong>'
 
 it "emphasis spanning a tag still works"
-assert_contains "$(md_render 'A _em <b>x</b> more_ end.')" '<em>em <b>x</b> more</em>'
+assert_contains "$(md_unsafe 'A _em <b>x</b> more_ end.')" '<em>em <b>x</b> more</em>'
 
 it "intraword underscores are still literal"
 assert_contains "$(md_render 'Use node_modules and snake_case_name.')" 'node_modules and snake_case_name'
diff --git a/test/units.sh b/test/units.sh
index d73a960..6111c95 100755
--- a/test/units.sh
+++ b/test/units.sh
@@ -651,13 +651,14 @@ After.')" "<p>After.</p>"
 it "a pipe in prose is not a table"
 assert_not_contains "$(md 'a | b in ordinary prose')" "<table>"
 
-# Markdown deliberately allows inline HTML, in cells as in prose.
-# multimarkdown 6.6.0 emits <th> <b>x</b> </th> for this, and jenny's own
-# prose handling passes raw HTML through too, so a cell must not differ.
-it "raw html in a cell passes through, as in prose"
+# A cell must handle raw HTML exactly as prose does. That used to mean both
+# passed it through; it now means both escape it unless the caller asks for
+# passthrough with UNSAFE_HTML=1. What matters is that a cell is not a hole in
+# whichever rule is in force.
+it "raw html in a cell is escaped, as in prose"
 assert_contains "$(md '| <b>x</b> |
 |---|
-| a |')" "<b>x</b>"
+| a |')" "&lt;b&gt;x&lt;/b&gt;"
 
 it "a table inside a fence is literal"
 assert_contains "$(md '```