Skip to content

Commit

Permalink
Don't apply smart typography to escaped text.
Browse files Browse the repository at this point in the history
This passes all escaped text back out as HTEXT_ESCAPED, which is
opaque to the smart formatter.
  • Loading branch information
Kristaps Dzonsons committed Apr 3, 2023
1 parent d6d0714 commit 23f12aa
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 14 deletions.
50 changes: 39 additions & 11 deletions document.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,26 +158,29 @@ parse_listitem(struct lowdown_buf *, struct lowdown_doc *,
char *, size_t, enum hlist_fl *, size_t);

/*
* Add a node to the parse stack, or retrieve a current node if
* requesting multiple LOWDOWN_NORMAL_TEXTs in sequence. Returns the
* node, initialised to the given type, after adjusting the parse
* Add a node to the parse stack or retrieve a current node if
* requesting multiple similar LOWDOWN_NORMAL_TEXT in sequence. Returns
* the node, initialised to the given type, after adjusting the parse
* position. Returns NULL on memory allocation failure.
*/
static struct lowdown_node *
pushnode(struct lowdown_doc *doc, enum lowdown_rndrt t)
pushnode_full(struct lowdown_doc *doc, enum lowdown_rndrt t, int fl)
{
struct lowdown_node *n;

/*
* Special case: if we're pushing a NORMAL_TEXT node, see if one
* already exists and return that. This means that each push
* for text nodes should be careful to use hbuf_push() instead
* of hbuf_create() when adding text content.
* already exists with the same flags and return that. This
* means that each push for text nodes should be careful to use
* hbuf_push() instead of hbuf_create() when adding text
* content.
*/

if (t == LOWDOWN_NORMAL_TEXT && doc->current != NULL) {
n = TAILQ_LAST(&doc->current->children, lowdown_nodeq);
if (n != NULL && n->type == t) {
if (n != NULL &&
n->type == LOWDOWN_NORMAL_TEXT &&
n->rndr_normal_text.flags == fl) {
doc->depth++;
doc->current = n;
return n;
Expand All @@ -201,6 +204,26 @@ pushnode(struct lowdown_doc *doc, enum lowdown_rndrt t)
return n;
}

/*
* Push a new node or, if LOWDOWN_NORMAL_TEXT, retrieve the existing one
* if the flags exactly match.
*/
static struct lowdown_node *
pushnode(struct lowdown_doc *doc, enum lowdown_rndrt t)
{
return pushnode_full(doc, t, 0);
}

/*
* Push a new LOWDOWN_NORMAL_TEXT or retrieve the existing one if the
* flags exactly match.
*/
static struct lowdown_node *
pushtext(struct lowdown_doc *doc, int flags)
{
return pushnode_full(doc, LOWDOWN_NORMAL_TEXT, flags);
}

/*
* Sets a buffer with the contents of "data" of size "datasz". The
* buffer must be empty. Return FALSE on failure, TRUE on success.
Expand Down Expand Up @@ -1047,7 +1070,10 @@ char_codespan(struct lowdown_doc *doc,
}

/*
* '\\' backslash escape
* '\\' backslash escaped text.
* Escaped text isn't handled by smart typography, although it must be
* escaped for output. Mark it as HTEXT_ESCAPED to make sure that we
* don't use smart typography on the node.
*/
static ssize_t
char_escape(struct lowdown_doc *doc,
Expand Down Expand Up @@ -1091,14 +1117,16 @@ char_escape(struct lowdown_doc *doc,

if (strchr(escape_chars, data[1]) == NULL)
return 0;
if ((n = pushnode(doc, LOWDOWN_NORMAL_TEXT)) == NULL)
if ((n = pushtext(doc, HTEXT_ESCAPED)) == NULL)
return -1;
n->rndr_normal_text.flags = HTEXT_ESCAPED;
if (!hbuf_push(&n->rndr_normal_text.text, data + 1, 1))
return -1;
popnode(doc, n);
} else if (size == 1) {
if ((n = pushnode(doc, LOWDOWN_NORMAL_TEXT)) == NULL)
if ((n = pushtext(doc, HTEXT_ESCAPED)) == NULL)
return -1;
n->rndr_normal_text.flags = HTEXT_ESCAPED;
if (!hbuf_push(&n->rndr_normal_text.text, data, 1))
return -1;
popnode(doc, n);
Expand Down
2 changes: 2 additions & 0 deletions lowdown.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ struct rndr_paragraph {
};

struct rndr_normal_text {
int flags;
#define HTEXT_ESCAPED 0x01
struct lowdown_buf text;
};

Expand Down
6 changes: 6 additions & 0 deletions man/lowdown.3
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,12 @@ The basic
.Va text
content for
.Dv LOWDOWN_NORMAL_TEXT .
If
.Va flags
is set to
.Dv HTEXT_ESCAPED ,
the text may be escaped for output, but may not be altered by any smart
typography or similar (it should be passed as-is).
.It Va rndr_paragraph
For
.Dv LOWDOWN_PARAGRAPH ,
Expand Down
1 change: 1 addition & 0 deletions regress/smarty-no-escape.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>Hi "there".</p>
2 changes: 2 additions & 0 deletions regress/smarty-no-escape.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

Hi \"there\".
4 changes: 4 additions & 0 deletions regress/smarty-no-escape2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<ul>
<li><strong>&#8211;foo-bar</strong></li>
<li><strong>--foo-bar</strong></li>
</ul>
4 changes: 4 additions & 0 deletions regress/smarty-no-escape2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Blah:

- **--foo-bar**
- **\-\-foo-bar**
1 change: 1 addition & 0 deletions regress/smarty-no-escape3.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>Should be esaped: &#60;hi &#47;&#62;. &#60;hi&#62;.</p>
2 changes: 2 additions & 0 deletions regress/smarty-no-escape3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

Should be esaped: \<hi /\>. \<hi\>.
1 change: 1 addition & 0 deletions regress/smarty-no-escape4.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>a&#8211;--b</p>
2 changes: 2 additions & 0 deletions regress/smarty-no-escape4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

a--\-\-b
11 changes: 8 additions & 3 deletions smartypants.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ smarty_right_wb(const struct lowdown_node *n, size_t pos)
* of the parse tree, <0 on failure, otherwise return zero.
*/
static int
smarty_hbuf(struct lowdown_node *n, size_t *maxn,
smarty_text(struct lowdown_node *n, size_t *maxn,
struct lowdown_buf *b, struct smarty *s)
{
size_t i = 0, j, sz;
Expand All @@ -329,6 +329,11 @@ smarty_hbuf(struct lowdown_node *n, size_t *maxn,

assert(n->type == LOWDOWN_NORMAL_TEXT);

/* If the text node was escaped, pass it out unchanged. */

if (n->rndr_normal_text.flags & HTEXT_ESCAPED)
return 0;

for (i = 0; i < b->size; i++) {
switch (b->data[i]) {
case '.':
Expand Down Expand Up @@ -421,7 +426,7 @@ smarty_span(struct lowdown_node *root, size_t *maxn,
TAILQ_FOREACH(n, &root->children, entries)
switch (types[n->type]) {
case TYPE_TEXT:
c = smarty_hbuf(n, maxn,
c = smarty_text(n, maxn,
&n->rndr_normal_text.text, s);
if (c < 0)
return 0;
Expand Down Expand Up @@ -464,7 +469,7 @@ smarty_block(struct lowdown_node *root,
return 0;
break;
case TYPE_TEXT:
c = smarty_hbuf(n, maxn,
c = smarty_text(n, maxn,
&n->rndr_normal_text.text, &s);
if (c < 0)
return 0;
Expand Down

0 comments on commit 23f12aa

Please sign in to comment.