go back and tweak the effing fenced code disaster area so that it will break fenced code out into its own div and consume html & footnotes at the top level.

This commit is contained in:
jessica parsons
2026-05-31 14:12:03 -07:00
parent ff09a191cd
commit 39be61ef2c
6 changed files with 105 additions and 98 deletions
+1
View File
@@ -22,6 +22,7 @@ Pptype(int typ)
switch (typ) { switch (typ) {
case WHITESPACE: return "whitespace"; case WHITESPACE: return "whitespace";
case CODE : return "code"; case CODE : return "code";
case FENCEDCODE: return "fenced code";
case QUOTE : return "quote"; case QUOTE : return "quote";
case MARKUP : return "markup"; case MARKUP : return "markup";
case HTML : return "html"; case HTML : return "html";
+5 -5
View File
@@ -1867,11 +1867,7 @@ printblock(Paragraph *pp, MMIOT *f)
Qstring(Begin[align], f); Qstring(Begin[align], f);
do { do {
if ( t->is_fenced ) { if ( S(t->text) ) {
text(f);
t = printfenced(t, f);
}
else if ( S(t->text) ) {
if ( t->next && S(t->text) > 2 if ( t->next && S(t->text) > 2
&& T(t->text)[S(t->text)-2] == ' ' && T(t->text)[S(t->text)-2] == ' '
&& T(t->text)[S(t->text)-1] == ' ' ) { && T(t->text)[S(t->text)-1] == ' ' ) {
@@ -2060,6 +2056,10 @@ display(Paragraph *p, MMIOT *f)
printhtml(p->text, f); printhtml(p->text, f);
break; break;
case FENCEDCODE:
printfenced(p->text, f);
break;
case CODE: case CODE:
printcode(p->text, p->lang, f); printcode(p->text, p->lang, f);
break; break;
+58 -26
View File
@@ -632,8 +632,10 @@ codeblock(Paragraph *p)
static int static int
iscodefence(Line *r, int size, line_type kind, mkd_flag_t *flags) iscodefence(Line *r, Line *orig, mkd_flag_t *flags)
{ {
int kind = 0, size = 2, dle = 0;
if ( !is_flag_set(flags, MKD_FENCEDCODE) || is_flag_set(flags, MKD_STRICT) ) if ( !is_flag_set(flags, MKD_FENCEDCODE) || is_flag_set(flags, MKD_STRICT) )
return 0; return 0;
@@ -644,6 +646,15 @@ iscodefence(Line *r, int size, line_type kind, mkd_flag_t *flags)
return 0; return 0;
if ( orig ) {
kind = orig->kind;
size = orig->count;
dle = orig->dle;
}
if ( (dle>>2) != (r->dle>>2) )
return 0;
if ( kind ) if ( kind )
return (r->kind == kind) && (r->count >= size); return (r->kind == kind) && (r->count >= size);
else else
@@ -652,19 +663,20 @@ iscodefence(Line *r, int size, line_type kind, mkd_flag_t *flags)
static Line * static Line *
fencedcodechunk(Line *first, mkd_flag_t *flags) fencedcodechunk(Line *first, mkd_flag_t *flags, int *yes)
{ {
Line *r, *q; Line *r, *q;
/* don't allow zero-length code fences /* don't allow zero-length code fences
*/ */
if ( (first->next == 0) || iscodefence(first->next, first->count, first->kind, flags) ) { if ( (first->next == 0) || iscodefence(first->next, first, flags) ) {
first->kind = chk_text; first->kind = chk_text;
first->is_fenced = 0; first->is_fenced = 0;
if ( first->next) { if ( first->next) {
first->next->kind = chk_text; first->next->kind = chk_text;
first->next->is_fenced = 0; first->next->is_fenced = 0;
} }
*yes = 0;
return first->next; return first->next;
} }
@@ -672,7 +684,7 @@ fencedcodechunk(Line *first, mkd_flag_t *flags)
* past the closing fence * past the closing fence
*/ */
for ( r = first->next; r; r = r->next ) { for ( r = first->next; r; r = r->next ) {
if ( iscodefence(r, first->count, first->kind, flags) ) { if ( iscodefence(r, first, flags) ) {
if (S(first->text) - first->count > 0) { if (S(first->text) - first->count > 0) {
char *lang_attr = T(first->text) + first->count; char *lang_attr = T(first->text) + first->count;
@@ -689,9 +701,13 @@ fencedcodechunk(Line *first, mkd_flag_t *flags)
S(first->text) = S(r->text) = 0; S(first->text) = S(r->text) = 0;
r->is_fenced = 0; r->is_fenced = 0;
return r->next; *yes = 1;
q = r->next;
r->next = 0;
return q;
} }
} }
*yes = 0;
first->is_fenced = 0; first->is_fenced = 0;
first->kind = chk_text; first->kind = chk_text;
return first; return first;
@@ -742,9 +758,7 @@ textblock(Paragraph *p, int toplevel, mkd_flag_t *flags)
Line *t, *next; Line *t, *next;
for ( t = p->text; t ; t = next ) { for ( t = p->text; t ; t = next ) {
if ( iscodefence(t, t->count, 0, flags) ) if ( ((next = t->next) == 0) || endoftextblock(next, toplevel, flags) ) {
next = fencedcodechunk(t, flags);
else if ( ((next = t->next) == 0) || endoftextblock(next, toplevel, flags) ) {
p->align = centered(p->text, t); p->align = centered(p->text, t);
t->next = 0; t->next = 0;
return next; return next;
@@ -1296,24 +1310,31 @@ compile_document(Line *ptr, MMIOT *f)
ptr = consume(addfootnote(ptr, f), &eaten); ptr = consume(addfootnote(ptr, f), &eaten);
previous_was_break = 1; previous_was_break = 1;
} }
else if (iscodefence(ptr, 2, 0, &(f->flags))) { else if ( previous_was_break && iscodefence(ptr, 0, &(f->flags)) ) {
Line *more = ptr;
/* scoop up _everything_ in a fenced code block, including html & footnotes /* scoop up _everything_ in a fenced code block, including html & footnotes
*/ */
int yes = 0;
Line *last = fencedcodechunk(ptr, &(f->flags), &yes );
ATTACH(source,more); if ( yes ) {
int dummy;
{ Cache checkpoint = source; /* dump out any previously cached text
while ( (more = more->next) && !iscodefence(more, ptr->count, ptr->kind, &(f->flags)) ) */
ATTACH(source,more); uncache(&source, &d, f);
if ( more ) p = Pp(&d, ptr, FENCEDCODE);
ptr = more;
else { ptr = consume(last, &dummy);
source = checkpoint; previous_was_break = 1;
ptr = ptr->next; }
} else {
/* unterminated fenced code; treat as regular markdown & cache until the next
* fenced code, htl, or style block
*/
ATTACH(source, ptr);
previous_was_break = 0;
ptr = ptr->next;
} }
} }
else { else {
@@ -1474,14 +1495,25 @@ compile(Line *ptr, int toplevel, MMIOT *f)
ptr = htmlblock(p, tag, &unclosed); ptr = htmlblock(p, tag, &unclosed);
if ( ! unclosed ) { if ( ! unclosed ) {
p->typ = HTML; p->typ = HTML;
continue;
} }
} }
if ( unclosed ) {
ptr = textblock(p, toplevel, &(f->flags) ); if ( iscodefence(p->text, 0, &(f->flags)) ) {
/* tables are a special kind of paragraph */ int yes = 0;
if ( actually_a_table(f, p->text) )
p->typ = TABLE; ptr = fencedcodechunk(p->text, &(f->flags), &yes);
if ( yes ) {
p->typ = FENCEDCODE;
continue;
}
} }
ptr = textblock(p, toplevel, &(f->flags) );
/* tables are a special kind of paragraph */
if ( actually_a_table(f, p->text) )
p->typ = TABLE;
} }
if ( (para||toplevel) && !p->align ) if ( (para||toplevel) && !p->align )
p->align = PARA; p->align = PARA;
+1 -1
View File
@@ -102,7 +102,7 @@ typedef struct paragraph {
char *label; /* toc label, uniqued */ char *label; /* toc label, uniqued */
char *ident; /* %id% tag for QUOTE */ char *ident; /* %id% tag for QUOTE */
char *lang; /* lang attribute for CODE */ char *lang; /* lang attribute for CODE */
enum { WHITESPACE=0, CODE, QUOTE, MARKUP, enum { WHITESPACE=0, CODE, FENCEDCODE, QUOTE, MARKUP,
HTML, STYLE, DL, UL, OL, AL, LISTITEM, HTML, STYLE, DL, UL, OL, AL, LISTITEM,
HDR, HR, TABLE, SOURCE } typ; HDR, HR, TABLE, SOURCE } typ;
enum { IMPLICIT=0, PARA, CENTER} align; enum { IMPLICIT=0, PARA, CENTER} align;
+36 -51
View File
@@ -50,19 +50,17 @@ code!
still code! still code!
~~~' \ ~~~' \
'<p><pre><code>code! '<pre><code>code!
still code! still code!
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block' \ try -ffencedcode 'fenced code block' \
'~~~ '~~~
code! code!
~~~' \ ~~~' \
'<p><pre><code>code! '<pre><code>code!
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block in list' \ try -ffencedcode 'fenced code block in list' \
'1. ~~~ '1. ~~~
@@ -78,9 +76,9 @@ try -ffencedcode 'fenced code block in blockquote' \
'>~~~ '>~~~
code code
~~~' \ ~~~' \
'<blockquote><p><pre><code>code '<blockquote><pre><code>code
</code></pre> </code></pre>
</p></blockquote>' </blockquote>'
try -ffencedcode 'unterminated fenced code block' \ try -ffencedcode 'unterminated fenced code block' \
'~~~ '~~~
@@ -94,11 +92,10 @@ try -ffencedcode 'fenced code block with tildes' \
code with tildes code with tildes
~~~ ~~~
~~~~~' \ ~~~~~' \
'<p><pre><code>~~~ '<pre><code>~~~
code with tildes code with tildes
~~~ ~~~
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'paragraph with trailing fenced block' \ try -ffencedcode 'paragraph with trailing fenced block' \
'text text text 'text text text
@@ -108,17 +105,16 @@ code code code?
~~~' \ ~~~' \
'<p>text text text '<p>text text text
text text text text text text
<pre><code>code code code? ~~~
</code></pre> code code code?
</p>' ~~~</p>'
try -ffencedcode 'fenced code blocks with backtick delimiters' \ try -ffencedcode 'fenced code blocks with backtick delimiters' \
'``` '```
code code
```' \ ```' \
'<p><pre><code>code '<pre><code>code
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block with mismatched delimters' \ try -ffencedcode 'fenced code block with mismatched delimters' \
'``` '```
@@ -132,57 +128,50 @@ try -ffencedcode 'fenced code block with lang attribute' \
'```lang '```lang
code code
```' \ ```' \
'<p><pre><code class="lang">code '<pre><code class="lang">code
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block with lang-name attribute' \ try -ffencedcode 'fenced code block with lang-name attribute' \
'```lang-name '```lang-name
code code
```' \ ```' \
'<p><pre><code class="lang-name">code '<pre><code class="lang-name">code
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block with lang_name attribute' \ try -ffencedcode 'fenced code block with lang_name attribute' \
'```lang_name '```lang_name
code code
```' \ ```' \
'<p><pre><code class="lang_name">code '<pre><code class="lang_name">code
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block with lang attribute and space' \ try -ffencedcode 'fenced code block with lang attribute and space' \
'``` lang '``` lang
code code
```' \ ```' \
'<p><pre><code class="lang">code '<pre><code class="lang">code
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block with lang attribute and multiple spaces' \ try -ffencedcode 'fenced code block with lang attribute and multiple spaces' \
'``` lang '``` lang
code code
```' \ ```' \
'<p><pre><code class="lang">code '<pre><code class="lang">code
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block with lang-name attribute and space' \ try -ffencedcode 'fenced code block with lang-name attribute and space' \
'``` lang-name '``` lang-name
code code
```' \ ```' \
'<p><pre><code class="lang-name">code '<pre><code class="lang-name">code
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block with lang_name attribute and space' \ try -ffencedcode 'fenced code block with lang_name attribute and space' \
'``` lang_name '``` lang_name
code code
```' \ ```' \
'<p><pre><code class="lang_name">code '<pre><code class="lang_name">code
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block with blank line in the middle' \ try -ffencedcode 'fenced code block with blank line in the middle' \
'``` '```
@@ -190,20 +179,18 @@ hello
sailor sailor
```' \ ```' \
'<p><pre><code>hello '<pre><code>hello
sailor sailor
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block with html in the middle' \ try -ffencedcode 'fenced code block with html in the middle' \
'~~~~ '~~~~
<h1>hello, sailor</h1> <h1>hello, sailor</h1>
~~~~' \ ~~~~' \
'<p><pre><code>&lt;h1&gt;hello, sailor&lt;/h1&gt; '<pre><code>&lt;h1&gt;hello, sailor&lt;/h1&gt;
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'fenced code block with trailing spaces in list item' \ try -ffencedcode 'fenced code block with trailing spaces in list item' \
'1. ~~~~ '1. ~~~~
@@ -229,9 +216,8 @@ bar
~~~~' \ ~~~~' \
'<p>foo</p> '<p>foo</p>
<p><pre><code>bar <pre><code>bar
</code></pre> </code></pre>'
</p>'
try -ffencedcode 'checkline misparse as fenced code' \ try -ffencedcode 'checkline misparse as fenced code' \
@@ -241,10 +227,9 @@ content
``` ```
' \ ' \
'<p><a href="#code"><code>label</code></a> '<p><a href="#code"><code>label</code></a>
<pre><code class="class">content <code>class
</code></pre> content
</p>' </code></p>'
summary $0 summary $0
exit $rc exit $rc
+4 -15
View File
@@ -76,21 +76,10 @@ RESULT='<ul>
./rep '#header' ' ' 400 | try -T 'a header with a bunch of trailing spaces' -heredoc "$RESULT" ./rep '#header' ' ' 400 | try -T 'a header with a bunch of trailing spaces' -heredoc "$RESULT"
RESULT='<table> RESULT='<p>: Y:|
<thead> <code>|
<tr> |
<th>: Y:</th> </code>|</p>'
</tr>
</thead>
<tbody>
<tr>
<td></td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>'
cat << \EOF | try '-F 0x03000000' 'random input that looks like a table' -heredoc "$RESULT" cat << \EOF | try '-F 0x03000000' 'random input that looks like a table' -heredoc "$RESULT"
: Y:| : Y:|