]> git.plutz.net Git - cgilite/commitdiff
Markdown Bugfix: use correct HTML escaping for heading id's (instead of URL escaping)
authorPaul Hänsch <paul@plutz.net>
Tue, 4 Nov 2025 18:02:08 +0000 (19:02 +0100)
committerPaul Hänsch <paul@plutz.net>
Tue, 4 Nov 2025 18:02:08 +0000 (19:02 +0100)
markdown.awk
tests-markdown.sh

index 744bcbabfd5c2ba31036b0dc35387077a46e16ed..b079bbec1eedc306490d62beb336b11f5ce0cbdd 100755 (executable)
@@ -106,13 +106,13 @@ function HTML ( text ) {
   return text;
 }
 
-function URL ( text, sharp ) {
+function URL ( text ) {
   gsub( /&/,  "%26",  text );
   gsub( /"/,  "%22", text );
   gsub( /'/,  "%27", text );
   gsub( /`/,  "%60", text );
   gsub( /\?/,  "%3F", text );
-  if (sharp) gsub( /#/,  "%23", text );
+  gsub( /#/,  "%23", text );
   gsub( /\[/,  "%5B", text );
   gsub( /\]/,  "%5D", text );
   gsub( / /,  "%20", text );
@@ -383,7 +383,7 @@ function inline( line, LOCAL, len, text, code, href, guard, ret ) {
   return ret;
 }
 
-function headline( hlvl, htxt, attrib, LOCAL, sec, n, HL) {
+function headline( hlvl, htxt, attrib, LOCAL, sec, n, hid, hid2, HL) {
   # match(hstack, /([0-9]+( [0-9]+){5})$/); split( substr(hstack, RSTART),  HL);
   match(hstack, /([0-9]+( [0-9]+)( [0-9]+)( [0-9]+)( [0-9]+)( [0-9]+))$/); split( substr(hstack, RSTART),  HL);
 
@@ -392,7 +392,10 @@ function headline( hlvl, htxt, attrib, LOCAL, sec, n, HL) {
 
   hid = ""; for ( n = 2; n <= blvl; n++) { hid = hid BL[n] "/"; }
   hid = hid HL[1]; for ( n = 2; n <= hlvl; n++) { hid = hid "." HL[n] ; }
-  hid = hid ":" URL(htxt, 1);
+  hid = hid ":" HTML(htxt);  # anchor for TOC
+  # hid2 = ":" HTML(htxt);     # anchor for permalink
+  # while ( headings[hid2] ) { n = n ? 2 : n + 1; hid2 = ":" HTML(htxt) "/" n; }
+  # headings[hid2] = true;
 
   # sub(/([0-9]+( [0-9]+){5})$/, "", hstack);
   sub(/([0-9]+( [0-9]+)( [0-9]+)( [0-9]+)( [0-9]+)( [0-9]+))$/, "", hstack);
index 30442cc225fbbf9a4cc23e59d4db5a08933c3d97..3e033dde9ffbd28b7771ed83ef4e89deaabdffec 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-runtimes="gawk busybox mawk goawk"
+runtimes="${runtimes:-gawk busybox mawk goawk}"
 
 BR='
 '
@@ -219,45 +219,45 @@ assert '![Testbild *ARD*](Test Bild.jpg){tv ard function-check}' \
 # Headings
 assert 'Heading first Order
 ============' \
-'<section class="h1" id="1:Heading%20first%20Order"><h1>Heading first Order<a class="anchor" href="#1:Heading%20first%20Order"></a></h1>
+'<section class="h1" id="1:Heading first Order"><h1>Heading first Order<a class="anchor" href="#1:Heading first Order"></a></h1>
 </section>' \
 'Heading h1'
 
 assert 'Heading first Order {.foo #bar}
 ============' \
-'<section class="h1 foo bar" id="1:Heading%20first%20Order"><h1 class="foo bar">Heading first Order<a class="anchor" href="#1:Heading%20first%20Order"></a></h1>
+'<section class="h1 foo bar" id="1:Heading first Order"><h1 class="foo bar">Heading first Order<a class="anchor" href="#1:Heading first Order"></a></h1>
 </section>' \
 'Heading h1 + attributes'
 
 assert 'Heading second Order
 ------------' \
-'<section class="h2" id="0.1:Heading%20second%20Order"><h2>Heading second Order<a class="anchor" href="#0.1:Heading%20second%20Order"></a></h2>
+'<section class="h2" id="0.1:Heading second Order"><h2>Heading second Order<a class="anchor" href="#0.1:Heading second Order"></a></h2>
 </section>' \
 'Heading h2'
 
 assert 'Heading second Order {.foo #bar}
 ------------' \
-'<section class="h2 foo bar" id="0.1:Heading%20second%20Order"><h2 class="foo bar">Heading second Order<a class="anchor" href="#0.1:Heading%20second%20Order"></a></h2>
+'<section class="h2 foo bar" id="0.1:Heading second Order"><h2 class="foo bar">Heading second Order<a class="anchor" href="#0.1:Heading second Order"></a></h2>
 </section>' \
 'Heading h2 + attributes'
 
 assert '#### Heading four' \
-'<section class="h4" id="0.0.0.1:Heading%20four"><h4>Heading four<a class="anchor" href="#0.0.0.1:Heading%20four"></a></h4>
+'<section class="h4" id="0.0.0.1:Heading four"><h4>Heading four<a class="anchor" href="#0.0.0.1:Heading four"></a></h4>
 </section>' \
 'Heading arbitrary'
 
 assert '###Heading three ######' \
-'<section class="h3" id="0.0.1:Heading%20three"><h3>Heading three<a class="anchor" href="#0.0.1:Heading%20three"></a></h3>
+'<section class="h3" id="0.0.1:Heading three"><h3>Heading three<a class="anchor" href="#0.0.1:Heading three"></a></h3>
 </section>' \
 'Heading arbitrary'
 
 assert '### Heading three ## {foo bar}' \
-'<section class="h3 foo bar" id="0.0.1:Heading%20three"><h3 class="foo bar">Heading three<a class="anchor" href="#0.0.1:Heading%20three"></a></h3>
+'<section class="h3 foo bar" id="0.0.1:Heading three"><h3 class="foo bar">Heading three<a class="anchor" href="#0.0.1:Heading three"></a></h3>
 </section>' \
 'Heading arbitrary + attributes'
 
 assert '# Heading \# # {foo bar}' \
-'<section class="h1 foo bar" id="1:Heading%20%5C%23"><h1 class="foo bar">Heading #<a class="anchor" href="#1:Heading%20%5C%23"></a></h1>
+'<section class="h1 foo bar" id="1:Heading &#x5C;#"><h1 class="foo bar">Heading #<a class="anchor" href="#1:Heading &#x5C;#"></a></h1>
 </section>' \
 'Heading arbitrary + attributes'
 
@@ -397,9 +397,9 @@ sub bar
 ' \
 '<section class="h2" id="0.1:foo"><h2>foo<a class="anchor" href="#0.1:foo"></a></h2>
 </section><section class="h1" id="1:bar"><h1>bar<a class="anchor" href="#1:bar"></a></h1>
-<section class="h2" id="1.1:sub%20bar"><h2>sub bar<a class="anchor" href="#1.1:sub%20bar"></a></h2>
-<section class="h3" id="1.1.1:sub%20sub%20sub"><h3>sub sub sub<a class="anchor" href="#1.1.1:sub%20sub%20sub"></a></h3>
-</section></section><section class="h2 x" id="1.2:sub2%20bar"><h2 class="x">sub2 bar<a class="anchor" href="#1.2:sub2%20bar"></a></h2>
+<section class="h2" id="1.1:sub bar"><h2>sub bar<a class="anchor" href="#1.1:sub bar"></a></h2>
+<section class="h3" id="1.1.1:sub sub sub"><h3>sub sub sub<a class="anchor" href="#1.1.1:sub sub sub"></a></h3>
+</section></section><section class="h2 x" id="1.2:sub2 bar"><h2 class="x">sub2 bar<a class="anchor" href="#1.2:sub2 bar"></a></h2>
 </section></section>' \
 'Headline Nesting'
 
@@ -533,7 +533,7 @@ Tests
 -----
 [Link with Title](https://en.wikipedia.org/wiki/Markdown "Markdown in Wikipedia"), *emphasis*, **strong**, **strong containing *emphasis***, `inline code`, `` code with `backticks` ``. See more tests [here](./tests/).' \
 '<section class="h1" id="1:Markdown.awk"><h1>Markdown.awk<a class="anchor" href="#1:Markdown.awk"></a></h1>
-<section class="h2" id="1.1:Supported%20Features%20/%20TODO:"><h2>Supported Features / TODO:<a class="anchor" href="#1.1:Supported%20Features%20/%20TODO:"></a></h2>
+<section class="h2" id="1.1:Supported Features / TODO:"><h2>Supported Features / TODO:<a class="anchor" href="#1.1:Supported Features / TODO:"></a></h2>
 <ul>
 <li class="task done"><input type=checkbox disabled checked> done</li>
 <li class="task pending"><input type=checkbox disabled> todo</li>
@@ -541,7 +541,7 @@ Tests
 <li>?  unsure (whether to implement)</li>
 <li class="task partial"><input type=checkbox disabled> partial</li>
 </ul>
-<section class="h3" id="1.1.1:Basic%20Markdown%20-%20Block%20elements:"><h3>Basic Markdown - Block elements:<a class="anchor" href="#1.1.1:Basic%20Markdown%20-%20Block%20elements:"></a></h3>
+<section class="h3" id="1.1.1:Basic Markdown - Block elements:"><h3>Basic Markdown - Block elements:<a class="anchor" href="#1.1.1:Basic Markdown - Block elements:"></a></h3>
 <ul>
 <li class="task done"><input type=checkbox disabled checked><p> Paragraphs</p>
 <ul>
@@ -557,7 +557,7 @@ Tests
 <li class="task done"><input type=checkbox disabled checked> Horizontal rules</li>
 <li class="task done"><input type=checkbox disabled checked> Verbatim HTML block (disabled by default)</li>
 </ul>
-</section><section class="h3" id="1.1.2:Basic%20Markdown%20-%20Inline%20elements:"><h3>Basic Markdown - Inline elements:<a class="anchor" href="#1.1.2:Basic%20Markdown%20-%20Inline%20elements:"></a></h3>
+</section><section class="h3" id="1.1.2:Basic Markdown - Inline elements:"><h3>Basic Markdown - Inline elements:<a class="anchor" href="#1.1.2:Basic Markdown - Inline elements:"></a></h3>
 <ul>
 <li class="task done"><input type=checkbox disabled checked> Links</li>
 <li class="task done"><input type=checkbox disabled checked> Reference style links</li>
@@ -571,7 +571,7 @@ Tests
 </ul>
 <p>NOTE: Set the environment variable <code>MD_HTML=true</code> to enable verbatim HTML</p>
 
-</section><section class="h3" id="1.1.3:Extensions%20-%20Block%20elements:"><h3>Extensions - Block elements:<a class="anchor" href="#1.1.3:Extensions%20-%20Block%20elements:"></a></h3>
+</section><section class="h3" id="1.1.3:Extensions - Block elements:"><h3>Extensions - Block elements:<a class="anchor" href="#1.1.3:Extensions - Block elements:"></a></h3>
 <ul>
 <li class="task done"><input type=checkbox disabled checked> Automatic &lt;section&gt;-wrapping (custom)</li>
 <li><p> ?  Heading identifiers (php md, pandoc)</p>
@@ -610,7 +610,7 @@ Tests
 <li class="task done"><input type=checkbox disabled checked> Metadata blocks (custom)</li>
 <li class="task done"><input type=checkbox disabled checked> Fenced Divs (pandoc)</li>
 </ul>
-</section><section class="h3" id="1.1.4:Extensions%20-%20Inline%20elements:"><h3>Extensions - Inline elements:<a class="anchor" href="#1.1.4:Extensions%20-%20Inline%20elements:"></a></h3>
+</section><section class="h3" id="1.1.4:Extensions - Inline elements:"><h3>Extensions - Inline elements:<a class="anchor" href="#1.1.4:Extensions - Inline elements:"></a></h3>
 <ul>
 <li class="task done"><input type=checkbox disabled checked> Ignore embedded_underscores (php md, pandoc)</li>
 <li class="task done"><input type=checkbox disabled checked> <del>strikeout</del> (pandoc)</li>
@@ -718,15 +718,15 @@ Term 2
 
     1.  first list item
     2.  second list item' \
-'<section class="h1" id="1:Headline%20First%20Order"><h1>Headline First Order<a class="anchor" href="#1:Headline%20First%20Order"></a></h1>
-<section class="h2" id="1.1:Headline%20Second%20Order"><h2>Headline Second Order<a class="anchor" href="#1.1:Headline%20Second%20Order"></a></h2>
+'<section class="h1" id="1:Headline First Order"><h1>Headline First Order<a class="anchor" href="#1:Headline First Order"></a></h1>
+<section class="h2" id="1.1:Headline Second Order"><h2>Headline Second Order<a class="anchor" href="#1.1:Headline Second Order"></a></h2>
 <pre><code>Code Block
 with indentation</code></pre>
 <blockquote><section class="h2" id="1/0.1:Blockquote"><h2>Blockquote<a class="anchor" href="#1/0.1:Blockquote"></a></h2>
 <p>like in an email</p>
 </section></blockquote>
 
-<section class="h3" id="1.1.1:Headline%203rd%20order"><h3>Headline 3rd order<a class="anchor" href="#1.1.1:Headline%203rd%20order"></a></h3>
+<section class="h3" id="1.1.1:Headline 3rd order"><h3>Headline 3rd order<a class="anchor" href="#1.1.1:Headline 3rd order"></a></h3>
 <ul>
 <li>unordered List</li>
 </ul>
@@ -963,7 +963,7 @@ For additional examples, regarding permanent installation and configuration in w
 
 Syntax
 ------
-The wiki syntax is based on John Grubers [Markdown](https://daringfireball.net/projects/markdown/) with extensions borrowed from [Pandoc](https://pandoc.org/MANUAL%202.html#pandocs-markdown) and [PHP Markdown Extra](https://michelf.ca/projects/php-markdown/extra/). The Markdown parser is provided by [Cgilite](/software/cgilite/) and its full documentation can be looked at [here](/software/cgilite/markdown/).
+The wiki syntax is based on John Grubers [Markdown](https://daringfireball.net/projects/markdown/) with extensions borrowed from [Pandoc](https://pandoc.org/MANUAL 2.html#pandocs-markdown) and [PHP Markdown Extra](https://michelf.ca/projects/php-markdown/extra/). The Markdown parser is provided by [Cgilite](/software/cgilite/) and its full documentation can be looked at [here](/software/cgilite/markdown/).
 
 <<include --nolink /[wiki]/editorhelp/>>
 
@@ -1182,7 +1182,7 @@ visitors into handling GDPR &quot;consent&quot; forms.</p>
 <p>For additional examples, regarding permanent installation and configuration in webservers see <a href="installation/">installation/</a>.</p>
 
 </section><section class="h2" id="1.4:Syntax"><h2>Syntax<a class="anchor" href="#1.4:Syntax"></a></h2>
-<p>The wiki syntax is based on John Grubers <a href="https://daringfireball.net/projects/markdown/">Markdown</a> with extensions borrowed from <a href="https://pandoc.org/MANUAL%202.html#pandocs-markdown">Pandoc</a> and <a href="https://michelf.ca/projects/php-markdown/extra/">PHP Markdown Extra</a>. The Markdown parser is provided by <a href="/software/cgilite/">Cgilite</a> and its full documentation can be looked at <a href="/software/cgilite/markdown/">here</a>.</p>
+<p>The wiki syntax is based on John Grubers <a href="https://daringfireball.net/projects/markdown/">Markdown</a> with extensions borrowed from <a href="https://pandoc.org/MANUAL 2.html#pandocs-markdown">Pandoc</a> and <a href="https://michelf.ca/projects/php-markdown/extra/">PHP Markdown Extra</a>. The Markdown parser is provided by <a href="/software/cgilite/">Cgilite</a> and its full documentation can be looked at <a href="/software/cgilite/markdown/">here</a>.</p>
 
 <code class="macro">include --nolink /[wiki]/editorhelp/</code></section><section class="h2" id="1.5:Macros"><h2>Macros<a class="anchor" href="#1.5:Macros"></a></h2>
 <p>Also see &rarr; <a href="macros/">macros/</a></p>
@@ -1203,7 +1203,7 @@ visitors into handling GDPR &quot;consent&quot; forms.</p>
 
 <p>For an example, see the <a href="/[wiki]/">technical pages</a> for this wiki.</p>
 
-</section><section class="h2" id="1.7:Multiple%20Languages"><h2>Multiple Languages<a class="anchor" href="#1.7:Multiple%20Languages"></a></h2>
+</section><section class="h2" id="1.7:Multiple Languages"><h2>Multiple Languages<a class="anchor" href="#1.7:Multiple Languages"></a></h2>
 <p>To enable a multilingual setup you must set a default language in your configuration environment:</p>
 
 <pre><code>export LANGUAGE_DEFAULT=en</code></pre>
@@ -1215,12 +1215,12 @@ visitors into handling GDPR &quot;consent&quot; forms.</p>
 
 <p>Header, footer, and error pages will be included from their respective language version, as will all macro includes, etc. Should a page not exist in a given language, the default page will be displayed instead. However, included elements will still be taken from the respective language version, possibly mixing languages between the selected user language and the default.</p>
 
-<section class="h3" id="1.7.1:Constraints%20of%20the%20current%20implementation"><h3>Constraints of the current implementation<a class="anchor" href="#1.7.1:Constraints%20of%20the%20current%20implementation"></a></h3>
+<section class="h3" id="1.7.1:Constraints of the current implementation"><h3>Constraints of the current implementation<a class="anchor" href="#1.7.1:Constraints of the current implementation"></a></h3>
 <ul>
 <li>There can be only one default language, with no priority of different fallback languages</li>
 <li>Page URLs can currently not be translated. Doing so would require a model for manually assigning translated page names and would not be trivial to use.</li>
 </ul>
-</section></section><section class="h2" id="1.8:Developer%20Documentation"><h2>Developer Documentation<a class="anchor" href="#1.8:Developer%20Documentation"></a></h2>
+</section></section><section class="h2" id="1.8:Developer Documentation"><h2>Developer Documentation<a class="anchor" href="#1.8:Developer Documentation"></a></h2>
 <p>How to write:</p>
 <ul>
 <li><a href="dev-theming/">Themes</a></li>