Merge pull request #38 from jmendeth/language-classes

Simplify and harden fenced code blocks
This commit is contained in:
Devin Torres 2014-01-16 14:52:38 -08:00
commit a7e72d2c72
3 changed files with 47 additions and 113 deletions

View file

@ -104,35 +104,10 @@ rndr_blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buf
if (ob->size) hoedown_buffer_putc(ob, '\n');
if (lang && lang->size) {
size_t i, cls = 0;
if (state->flags & HOEDOWN_HTML_PRETTIFY) {
HOEDOWN_BUFPUTSL(ob, "<pre><code class=\"prettyprint");
cls++;
} else {
HOEDOWN_BUFPUTSL(ob, "<pre><code class=\"");
}
for (i = 0; i < lang->size; ++i, ++cls) {
while (i < lang->size && isspace(lang->data[i]))
i++;
if (i < lang->size) {
size_t org = i;
while (i < lang->size && !isspace(lang->data[i]))
i++;
if (lang->data[org] == '.')
org++;
if (cls) hoedown_buffer_putc(ob, ' ');
escape_html(ob, lang->data + org, i - org);
}
}
if (lang) {
HOEDOWN_BUFPUTSL(ob, "<pre><code class=\"language-");
escape_html(ob, lang->data, lang->size);
HOEDOWN_BUFPUTSL(ob, "\">");
} else if (state->flags & HOEDOWN_HTML_PRETTIFY) {
HOEDOWN_BUFPUTSL(ob, "<pre><code class=\"prettyprint\">");
} else {
HOEDOWN_BUFPUTSL(ob, "<pre><code>");
}
@ -156,10 +131,7 @@ static int
rndr_codespan(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
{
hoedown_html_renderer_state *state = opaque;
if (state->flags & HOEDOWN_HTML_PRETTIFY)
HOEDOWN_BUFPUTSL(ob, "<code class=\"prettyprint\">");
else
HOEDOWN_BUFPUTSL(ob, "<code>");
HOEDOWN_BUFPUTSL(ob, "<code>");
if (text) escape_html(ob, text->data, text->size);
HOEDOWN_BUFPUTSL(ob, "</code>");
return 1;

View file

@ -21,8 +21,7 @@ typedef enum {
HOEDOWN_HTML_TOC = (1 << 6),
HOEDOWN_HTML_HARD_WRAP = (1 << 7),
HOEDOWN_HTML_USE_XHTML = (1 << 8),
HOEDOWN_HTML_ESCAPE = (1 << 9),
HOEDOWN_HTML_PRETTIFY = (1 << 10)
HOEDOWN_HTML_ESCAPE = (1 << 9)
} hoedown_html_render_mode;
typedef enum {

View file

@ -1321,10 +1321,11 @@ is_hrule(uint8_t *data, size_t size)
return n >= 3;
}
/* check if a line begins with a code fence; return the
* width of the code fence */
/* check if a line is a code fence; return the
* width of the code fence. if passed, width of
* the fence rule and character will be returned */
static size_t
prefix_codefence(uint8_t *data, size_t size)
is_codefence(uint8_t *data, size_t size, size_t *width, uint8_t *chr)
{
size_t i = 0, n = 0;
uint8_t c;
@ -1349,64 +1350,33 @@ prefix_codefence(uint8_t *data, size_t size)
if (n < 3)
return 0;
if (width) *width = n;
if (chr) *chr = c;
return i;
}
/* check if a line is a code fence; return its size if it is */
static size_t
is_codefence(uint8_t *data, size_t size, hoedown_buffer *syntax)
/* expects single line, checks if it's a codefence and extracts language */
static int
parse_codefence(uint8_t *data, size_t size, hoedown_buffer *lang, size_t *width, uint8_t *chr)
{
size_t i = 0, syn_len = 0;
uint8_t *syn_start;
size_t i, w, lang_start;
i = prefix_codefence(data, size);
i = w = is_codefence(data, size, width, chr);
if (i == 0)
return 0;
while (i < size && data[i] == ' ')
while (i < size && _isspace(data[i]))
i++;
syn_start = data + i;
if (i < size && data[i] == '{') {
i++; syn_start++;
while (i < size && data[i] != '}' && data[i] != '\n') {
syn_len++; i++;
}
if (i == size || data[i] != '}')
return 0;
/* strip all whitespace at the beginning and the end
* of the {} block */
while (syn_len > 0 && _isspace(syn_start[0])) {
syn_start++; syn_len--;
}
while (syn_len > 0 && _isspace(syn_start[syn_len - 1]))
syn_len--;
lang_start = i;
while (i < size && !_isspace(data[i]))
i++;
} else {
while (i < size && !_isspace(data[i])) {
syn_len++; i++;
}
}
if (syntax) {
syntax->data = syn_start;
syntax->size = syn_len;
}
lang->data = data + lang_start;
lang->size = i - lang_start;
while (i < size && data[i] != '\n') {
if (!_isspace(data[i]))
return 0;
i++;
}
return i + 1;
return w;
}
/* is_atxheader • returns whether the line is a hash-prefixed header */
@ -1639,7 +1609,7 @@ parse_paragraph(hoedown_buffer *ob, hoedown_markdown *md, uint8_t *data, size_t
/* see if a code fence starts here */
if ((md->ext_flags & HOEDOWN_EXT_FENCED_CODE) != 0 &&
is_codefence(data + i, size - i, NULL) != 0) {
is_codefence(data + i, size - i, NULL, NULL)) {
end = i;
break;
}
@ -1703,45 +1673,38 @@ parse_paragraph(hoedown_buffer *ob, hoedown_markdown *md, uint8_t *data, size_t
static size_t
parse_fencedcode(hoedown_buffer *ob, hoedown_markdown *md, uint8_t *data, size_t size)
{
size_t beg, end;
hoedown_buffer *work = 0;
size_t i = 0, text_start, line_start;
size_t w, w2;
size_t width, width2;
uint8_t chr, chr2;
hoedown_buffer text = { 0, 0, 0, 0 };
hoedown_buffer lang = { 0, 0, 0, 0 };
beg = is_codefence(data, size, &lang);
if (beg == 0) return 0;
// parse codefence line
while (i < size && data[i] != '\n') i++;
w = parse_codefence(data, i, &lang, &width, &chr);
if (!w) return 0;
work = newbuf(md, BUFFER_BLOCK);
// search for end
i++;
text_start = i;
for (; (line_start = i) < size; i++) {
while (i < size && data[i] != '\n') i++;
while (beg < size) {
size_t fence_end;
hoedown_buffer fence_trail = { 0, 0, 0, 0 };
fence_end = is_codefence(data + beg, size - beg, &fence_trail);
if (fence_end != 0 && fence_trail.size == 0) {
beg += fence_end;
w2 = is_codefence(data + line_start, i - line_start, &width2, &chr2);
if (w == w2 && width == width2 && chr == chr2 &&
is_empty(data + (line_start+w), i - (line_start+w)))
break;
}
for (end = beg + 1; end < size && data[end - 1] != '\n'; end++);
if (beg < end) {
/* verbatim copy to the working buffer,
escaping entities */
if (is_empty(data + beg, end - beg))
hoedown_buffer_putc(work, '\n');
else hoedown_buffer_put(work, data + beg, end - beg);
}
beg = end;
}
text.data = data + text_start;
text.size = line_start - text_start;
if (work->size && work->data[work->size - 1] != '\n')
hoedown_buffer_putc(work, '\n');
// call callback
if (md->md.blockcode)
md->md.blockcode(ob, work, lang.size ? &lang : NULL, md->md.opaque);
md->md.blockcode(ob, text.size ? &text : NULL, lang.size ? &lang : NULL, md->md.opaque);
popbuf(md, BUFFER_BLOCK);
return beg;
if (data[i] == '\n') i++;
return i;
}
static size_t
@ -1842,7 +1805,7 @@ parse_listitem(hoedown_buffer *ob, hoedown_markdown *md, uint8_t *data, size_t s
pre = i;
if (md->ext_flags & HOEDOWN_EXT_FENCED_CODE) {
if (is_codefence(data + beg + i, end - beg - i, NULL) != 0)
if (is_codefence(data + beg + i, end - beg - i, NULL, NULL))
in_fence = !in_fence;
}