mirror of
https://github.com/Orc/discount.git
synced 2026-09-25 04:10:00 +03:00
first pass at collapsing fenced code blocks into regular paragraphs
This commit is contained in:
+25
-5
@@ -1664,6 +1664,23 @@ printtable(Paragraph *pp, MMIOT *f)
|
||||
}
|
||||
|
||||
|
||||
static Line *
|
||||
printfenced(Line *t, MMIOT *f)
|
||||
{
|
||||
Qstring("<pre><code", f);
|
||||
if ( t->fence_class )
|
||||
Qprintf(f, " class=\"%s\"", t->fence_class);
|
||||
Qstring(">\n", f);
|
||||
while ( (t = t->next) && t->is_fenced ) {
|
||||
code(f, T(t->text), S(t->text));
|
||||
Qchar('\n', f);
|
||||
}
|
||||
|
||||
Qstring("</code></pre>\n", f);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
printblock(Paragraph *pp, MMIOT *f)
|
||||
{
|
||||
@@ -1672,8 +1689,13 @@ printblock(Paragraph *pp, MMIOT *f)
|
||||
Line *t = pp->text;
|
||||
int align = pp->align;
|
||||
|
||||
while (t) {
|
||||
if ( S(t->text) ) {
|
||||
Qstring(Begin[align], f);
|
||||
do {
|
||||
if ( t->is_fenced ) {
|
||||
text(f);
|
||||
t = printfenced(t, f);
|
||||
}
|
||||
else if ( S(t->text) ) {
|
||||
if ( t->next && S(t->text) > 2
|
||||
&& T(t->text)[S(t->text)-2] == ' '
|
||||
&& T(t->text)[S(t->text)-1] == ' ' ) {
|
||||
@@ -1688,9 +1710,7 @@ printblock(Paragraph *pp, MMIOT *f)
|
||||
pushc('\n', f);
|
||||
}
|
||||
}
|
||||
t = t->next;
|
||||
}
|
||||
Qstring(Begin[align], f);
|
||||
} while (t && (t = t->next) );
|
||||
text(f);
|
||||
Qstring(End[align], f);
|
||||
return 1;
|
||||
|
||||
+53
-49
@@ -176,7 +176,7 @@ splitline(Line *t, int cutpoint)
|
||||
}
|
||||
}
|
||||
|
||||
#define UNCHECK(l) ((l)->line_flags &= ~CHECKED)
|
||||
#define UNCHECK(t) ((t)->is_checked = 0)
|
||||
|
||||
#define UNLESS_FENCED(t) if (fenced) { \
|
||||
other = 1; l->count += (c == ' ' ? 0 : -1); \
|
||||
@@ -195,10 +195,11 @@ checkline(Line *l, mkd_flag_t *flags)
|
||||
stars = 0, tildes = 0, other = 0,
|
||||
backticks = 0, fenced = 0;
|
||||
|
||||
l->line_flags |= CHECKED;
|
||||
l->is_checked = 1;
|
||||
l->kind = chk_text;
|
||||
l->count = 0;
|
||||
|
||||
|
||||
if (l->dle >= 4) { l->kind=chk_code; return; }
|
||||
|
||||
for ( eol = S(l->text); eol > l->dle && isspace(T(l->text)[eol-1]); --eol )
|
||||
@@ -206,7 +207,6 @@ checkline(Line *l, mkd_flag_t *flags)
|
||||
|
||||
for (i=l->dle; i<eol; i++) {
|
||||
register int c = T(l->text)[i];
|
||||
int is_fence_char = 0;
|
||||
|
||||
if ( c != ' ' ) l->count++;
|
||||
|
||||
@@ -219,17 +219,10 @@ checkline(Line *l, mkd_flag_t *flags)
|
||||
default:
|
||||
if ( is_flag_set(flags, MKD_FENCEDCODE) ) {
|
||||
switch (c) {
|
||||
case '~': if (other) return; is_fence_char = 1; tildes = 1; break;
|
||||
case '`': if (other) return; is_fence_char = 1; backticks = 1; break;
|
||||
}
|
||||
if (is_fence_char) {
|
||||
fenced = 1;
|
||||
break;
|
||||
case '~': fenced++; tildes = 1; break;
|
||||
case '`': fenced++; backticks = 1; break;
|
||||
}
|
||||
}
|
||||
other = 1;
|
||||
l->count--;
|
||||
if (!fenced) return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,6 +240,10 @@ checkline(Line *l, mkd_flag_t *flags)
|
||||
else if ( equals ) { l->kind = chk_equal; }
|
||||
else if ( tildes ) { l->kind = chk_tilde; }
|
||||
else if ( backticks ) { l->kind = chk_backtick; }
|
||||
if ( fenced > 1 ) {
|
||||
l->is_fenced = 1;
|
||||
l->count = fenced;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -381,7 +378,7 @@ iscode(Line *t)
|
||||
static inline int
|
||||
ishr(Line *t, mkd_flag_t *flags)
|
||||
{
|
||||
if ( ! (t->line_flags & CHECKED) )
|
||||
if ( ! (t->is_checked) )
|
||||
checkline(t, flags);
|
||||
|
||||
if ( t->count > 2 )
|
||||
@@ -400,7 +397,7 @@ issetext(Line *t, int *htyp, mkd_flag_t *flags)
|
||||
*/
|
||||
|
||||
if ( (n = t->next) ) {
|
||||
if ( !(n->line_flags & CHECKED) )
|
||||
if ( !(n->is_checked) )
|
||||
checkline(n, flags);
|
||||
|
||||
if ( n->kind == chk_dash || n->kind == chk_equal ) {
|
||||
@@ -626,7 +623,7 @@ iscodefence(Line *r, int size, line_type kind, mkd_flag_t *flags)
|
||||
if ( !is_flag_set(flags, MKD_FENCEDCODE) )
|
||||
return 0;
|
||||
|
||||
if ( !(r->line_flags & CHECKED) )
|
||||
if ( !(r->is_checked) )
|
||||
checkline(r, flags);
|
||||
|
||||
if ( kind )
|
||||
@@ -636,40 +633,52 @@ iscodefence(Line *r, int size, line_type kind, mkd_flag_t *flags)
|
||||
}
|
||||
|
||||
|
||||
static Paragraph *
|
||||
fencedcodeblock(ParagraphRoot *d, Line **ptr, mkd_flag_t *flags)
|
||||
static Line *
|
||||
fencedcodechunk(Line *first, mkd_flag_t *flags)
|
||||
{
|
||||
Line *first, *r;
|
||||
Paragraph *ret;
|
||||
|
||||
first = (*ptr);
|
||||
Line *r, *q;
|
||||
|
||||
/* don't allow zero-length code fences
|
||||
*/
|
||||
if ( (first->next == 0) || iscodefence(first->next, first->count, 0, flags) )
|
||||
return 0;
|
||||
if ( (first->next == 0) || iscodefence(first->next, first->count, first->kind, flags) ) {
|
||||
first->kind = chk_text;
|
||||
first->is_fenced = 0;
|
||||
if ( first->next) {
|
||||
first->next->kind = chk_text;
|
||||
first->next->is_fenced = 0;
|
||||
}
|
||||
return first->next;
|
||||
}
|
||||
|
||||
/* find the closing fence, discard the fences,
|
||||
* return a Paragraph with the contents
|
||||
*/
|
||||
for ( r = first; r && r->next; r = r->next )
|
||||
if ( iscodefence(r->next, first->count, first->kind, flags) ) {
|
||||
(*ptr) = r->next->next;
|
||||
ret = Pp(d, first->next, CODE);
|
||||
/* find the closing fence, return a pointer to the Line
|
||||
* past the closing fence
|
||||
*/
|
||||
for ( r = first->next; r; r = r->next ) {
|
||||
fprintf(stderr, "? %.*s\n", S(r->text), T(r->text));
|
||||
|
||||
if ( iscodefence(r, first->count, first->kind, flags) ) {
|
||||
if (S(first->text) - first->count > 0) {
|
||||
char *lang_attr = T(first->text) + first->count;
|
||||
|
||||
while ( *lang_attr != 0 && *lang_attr == ' ' ) lang_attr++;
|
||||
ret->lang = strdup(lang_attr);
|
||||
|
||||
if ( lang_attr && *lang_attr ) {
|
||||
first->fence_class = strdup(lang_attr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret->lang = 0;
|
||||
|
||||
for ( q = first; q && (q != r); q = q->next )
|
||||
q->is_fenced = 1;
|
||||
|
||||
S(first->text) = S(r->text) = 0;
|
||||
r->is_fenced = 0;
|
||||
|
||||
return r->next;
|
||||
}
|
||||
___mkd_freeLine(first);
|
||||
___mkd_freeLine(r->next);
|
||||
r->next = 0;
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
first->is_fenced = 0;
|
||||
first->kind = chk_text;
|
||||
return first;
|
||||
}
|
||||
|
||||
|
||||
@@ -717,7 +726,9 @@ textblock(Paragraph *p, int toplevel, mkd_flag_t *flags)
|
||||
Line *t, *next;
|
||||
|
||||
for ( t = p->text; t ; t = next ) {
|
||||
if ( ((next = t->next) == 0) || endoftextblock(next, toplevel, flags) ) {
|
||||
if ( iscodefence(t, t->count, 0, flags) )
|
||||
next = fencedcodechunk(t, flags);
|
||||
else if ( ((next = t->next) == 0) || endoftextblock(next, toplevel, flags) ) {
|
||||
p->align = centered(p->text, t);
|
||||
t->next = 0;
|
||||
return next;
|
||||
@@ -804,7 +815,7 @@ quoteblock(Paragraph *p, mkd_flag_t *flags)
|
||||
if ( T(t->text)[qp] == ' ' )
|
||||
qp++;
|
||||
__mkd_trim_line(t,qp);
|
||||
UNCHECK(t);
|
||||
checkline(t, flags);
|
||||
}
|
||||
|
||||
q = skipempty(t->next);
|
||||
@@ -859,6 +870,7 @@ listitem(Paragraph *p, int indent, mkd_flag_t *flags, linefn check)
|
||||
|
||||
for ( t = p->text; t ; t = q) {
|
||||
UNCHECK(t);
|
||||
|
||||
__mkd_trim_line(t, clip);
|
||||
|
||||
if ( firstpara && !is_flag_set(flags, MKD_NORMAL_LISTITEM) ) {
|
||||
@@ -1223,13 +1235,7 @@ compile_document(Line *ptr, MMIOT *f)
|
||||
ptr = consume(addfootnote(ptr, f), &eaten);
|
||||
previous_was_break = 1;
|
||||
}
|
||||
else if ( previous_was_break && iscodefence(ptr,3,0,&(f->flags)) ) {
|
||||
uncache(&source, &d, f);
|
||||
if ( !fencedcodeblock(&d, &ptr, &(f->flags)) ) /* just source */
|
||||
goto attach;
|
||||
}
|
||||
else {
|
||||
attach:
|
||||
/* source; cache it up to wait for eof or the
|
||||
* next html/style block
|
||||
*/
|
||||
@@ -1278,7 +1284,7 @@ actually_a_table(MMIOT *f, Line *pp)
|
||||
|
||||
/* all lines must contain |'s */
|
||||
for (r = pp; r; r = r->next )
|
||||
if ( !(r->line_flags & PIPECHAR) ) {
|
||||
if ( !(r->has_pipechar) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1336,8 +1342,6 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
||||
|
||||
ptr = codeblock(p);
|
||||
}
|
||||
else if ( iscodefence(ptr,3,0,&(f->flags)) && (p=fencedcodeblock(&d, &ptr, &(f->flags))) )
|
||||
/* yay, it's already done */ ;
|
||||
else if ( ishr(ptr, &(f->flags)) ) {
|
||||
p = Pp(&d, 0, HR);
|
||||
r = ptr;
|
||||
|
||||
+4
-4
@@ -79,11 +79,11 @@ typedef struct line {
|
||||
Cstring text;
|
||||
struct line *next;
|
||||
int dle; /* leading indent on the line */
|
||||
int line_flags; /* special attributes for this line */
|
||||
#define PIPECHAR 0x01 /* line contains a | */
|
||||
#define CHECKED 0x02
|
||||
|
||||
int has_pipechar; /* line contains a | */
|
||||
int is_checked;
|
||||
line_type kind;
|
||||
int is_fenced; /* line inside a fenced code block (ick) */
|
||||
char *fence_class; /* fenced code class (ick) */
|
||||
int count;
|
||||
} Line;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ __mkd_enqueue(Document* a, Cstring *line)
|
||||
}
|
||||
else if ( c >= ' ' ) {
|
||||
if ( c == '|' )
|
||||
p->line_flags |= PIPECHAR;
|
||||
p->has_pipechar = 1;
|
||||
EXPAND(p->text) = c;
|
||||
++xp;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
void
|
||||
___mkd_freeLine(Line *ptr)
|
||||
{
|
||||
if ( ptr->fence_class )
|
||||
free(ptr->fence_class);
|
||||
DELETE(ptr->text);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
+71
-36
@@ -46,33 +46,41 @@ code!
|
||||
|
||||
still code!
|
||||
~~~' \
|
||||
'<pre><code>code!
|
||||
'<p><pre><code>
|
||||
code!
|
||||
|
||||
still code!
|
||||
</code></pre>'
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code block' \
|
||||
'~~~
|
||||
code!
|
||||
~~~' \
|
||||
'<pre><code>code!
|
||||
</code></pre>'
|
||||
'<p><pre><code>
|
||||
code!
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code block in list' \
|
||||
'1. ~~~
|
||||
code block
|
||||
~~~' \
|
||||
'<ol>
|
||||
<li><pre><code>code block
|
||||
</code></pre></li>
|
||||
<li><pre><code>
|
||||
code block
|
||||
</code></pre>
|
||||
</li>
|
||||
</ol>'
|
||||
|
||||
try -ffencedcode 'fenced code block in blockquote' \
|
||||
'>~~~
|
||||
code
|
||||
~~~' \
|
||||
'<blockquote><pre><code>code
|
||||
</code></pre></blockquote>'
|
||||
'<blockquote><p><pre><code>
|
||||
code
|
||||
</code></pre>
|
||||
</p></blockquote>'
|
||||
|
||||
try -ffencedcode 'unterminated fenced code block' \
|
||||
'~~~
|
||||
@@ -86,10 +94,12 @@ try -ffencedcode 'fenced code block with tildes' \
|
||||
code with tildes
|
||||
~~~
|
||||
~~~~~' \
|
||||
'<pre><code>~~~
|
||||
'<p><pre><code>
|
||||
~~~
|
||||
code with tildes
|
||||
~~~
|
||||
</code></pre>'
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'paragraph with trailing fenced block' \
|
||||
'text text text
|
||||
@@ -99,16 +109,19 @@ code code code?
|
||||
~~~' \
|
||||
'<p>text text text
|
||||
text text text
|
||||
~~~
|
||||
<pre><code>
|
||||
code code code?
|
||||
~~~</p>'
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code blocks with backtick delimiters' \
|
||||
'```
|
||||
code
|
||||
```' \
|
||||
'<pre><code>code
|
||||
</code></pre>'
|
||||
'<p><pre><code>
|
||||
code
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code block with mismatched delimters' \
|
||||
'```
|
||||
@@ -122,50 +135,64 @@ try -ffencedcode 'fenced code block with lang attribute' \
|
||||
'```lang
|
||||
code
|
||||
```' \
|
||||
'<pre><code class="lang">code
|
||||
</code></pre>'
|
||||
'<p><pre><code class="lang">
|
||||
code
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code block with lang-name attribute' \
|
||||
'```lang-name
|
||||
code
|
||||
```' \
|
||||
'<pre><code class="lang-name">code
|
||||
</code></pre>'
|
||||
'<p><pre><code class="lang-name">
|
||||
code
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code block with lang_name attribute' \
|
||||
'```lang_name
|
||||
code
|
||||
```' \
|
||||
'<pre><code class="lang_name">code
|
||||
</code></pre>'
|
||||
'<p><pre><code class="lang_name">
|
||||
code
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code block with lang attribute and space' \
|
||||
'``` lang
|
||||
code
|
||||
```' \
|
||||
'<pre><code class="lang">code
|
||||
</code></pre>'
|
||||
'<p><pre><code class="lang">
|
||||
code
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code block with lang attribute and multiple spaces' \
|
||||
'``` lang
|
||||
code
|
||||
```' \
|
||||
'<pre><code class="lang">code
|
||||
</code></pre>'
|
||||
'<p><pre><code class="lang">
|
||||
code
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code block with lang-name attribute and space' \
|
||||
'``` lang-name
|
||||
code
|
||||
```' \
|
||||
'<pre><code class="lang-name">code
|
||||
</code></pre>'
|
||||
'<p><pre><code class="lang-name">
|
||||
code
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code block with lang_name attribute and space' \
|
||||
'``` lang_name
|
||||
code
|
||||
```' \
|
||||
'<pre><code class="lang_name">code
|
||||
</code></pre>'
|
||||
'<p><pre><code class="lang_name">
|
||||
code
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code block with blank line in the middle' \
|
||||
'```
|
||||
@@ -173,26 +200,32 @@ hello
|
||||
|
||||
sailor
|
||||
```' \
|
||||
'<pre><code>hello
|
||||
'<p><pre><code>
|
||||
hello
|
||||
|
||||
sailor
|
||||
</code></pre>'
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
|
||||
try -ffencedcode 'fenced code block with html in the middle' \
|
||||
'~~~~
|
||||
<h1>hello, sailor</h1>
|
||||
~~~~' \
|
||||
'<pre><code><h1>hello, sailor</h1>
|
||||
</code></pre>'
|
||||
'<p><pre><code>
|
||||
<h1>hello, sailor</h1>
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
try -ffencedcode 'fenced code block with trailing spaces in list item' \
|
||||
'1. ~~~~
|
||||
test me
|
||||
~~~~' \
|
||||
'<ol>
|
||||
<li><pre><code>test me
|
||||
</code></pre></li>
|
||||
<li><pre><code>
|
||||
test me
|
||||
</code></pre>
|
||||
</li>
|
||||
</ol>'
|
||||
|
||||
try -ffencedcode 'unterminated fenced code block' \
|
||||
@@ -209,8 +242,10 @@ bar
|
||||
~~~~' \
|
||||
'<p>foo</p>
|
||||
|
||||
<pre><code>bar
|
||||
</code></pre>'
|
||||
<p><pre><code>
|
||||
bar
|
||||
</code></pre>
|
||||
</p>'
|
||||
|
||||
summary $0
|
||||
exit $rc
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ char **argv;
|
||||
if ( fgets(line, sizeof line, pipe) != 0 ) {
|
||||
strtok(line, "\n");
|
||||
if ( strcmp(line, "main" ) != 0 )
|
||||
printf("\"(%s)\"", line);
|
||||
printf("\"(%s)-\"", line);
|
||||
}
|
||||
pclose(pipe);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user