/src/mupdf/thirdparty/cmark-gfm/extensions/strikethrough.c
Line | Count | Source |
1 | | #include "strikethrough.h" |
2 | | #include <parser.h> |
3 | | #include <render.h> |
4 | | |
5 | | cmark_node_type CMARK_NODE_STRIKETHROUGH; |
6 | | |
7 | | static cmark_node *match(cmark_syntax_extension *self, cmark_parser *parser, |
8 | | cmark_node *parent, unsigned char character, |
9 | 0 | cmark_inline_parser *inline_parser) { |
10 | 0 | cmark_node *res = NULL; |
11 | 0 | int left_flanking, right_flanking, punct_before, punct_after, delims; |
12 | 0 | char buffer[101]; |
13 | |
|
14 | 0 | if (character != '~') |
15 | 0 | return NULL; |
16 | | |
17 | 0 | delims = cmark_inline_parser_scan_delimiters( |
18 | 0 | inline_parser, sizeof(buffer) - 1, '~', |
19 | 0 | &left_flanking, |
20 | 0 | &right_flanking, &punct_before, &punct_after); |
21 | |
|
22 | 0 | memset(buffer, '~', delims); |
23 | 0 | buffer[delims] = 0; |
24 | |
|
25 | 0 | res = cmark_node_new_with_mem(CMARK_NODE_TEXT, parser->mem); |
26 | 0 | cmark_node_set_literal(res, buffer); |
27 | 0 | res->start_line = res->end_line = cmark_inline_parser_get_line(inline_parser); |
28 | 0 | res->start_column = cmark_inline_parser_get_column(inline_parser) - delims; |
29 | |
|
30 | 0 | if ((left_flanking || right_flanking) && |
31 | 0 | (delims == 2 || (!(parser->options & CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE) && delims == 1))) { |
32 | 0 | cmark_inline_parser_push_delimiter(inline_parser, character, left_flanking, |
33 | 0 | right_flanking, res); |
34 | 0 | } |
35 | |
|
36 | 0 | return res; |
37 | 0 | } |
38 | | |
39 | | static delimiter *insert(cmark_syntax_extension *self, cmark_parser *parser, |
40 | | cmark_inline_parser *inline_parser, delimiter *opener, |
41 | 0 | delimiter *closer) { |
42 | 0 | cmark_node *strikethrough; |
43 | 0 | cmark_node *tmp, *next; |
44 | 0 | delimiter *delim, *tmp_delim; |
45 | 0 | delimiter *res = closer->next; |
46 | |
|
47 | 0 | strikethrough = opener->inl_text; |
48 | |
|
49 | 0 | if (opener->inl_text->as.literal.len != closer->inl_text->as.literal.len) |
50 | 0 | goto done; |
51 | | |
52 | 0 | if (!cmark_node_set_type(strikethrough, CMARK_NODE_STRIKETHROUGH)) |
53 | 0 | goto done; |
54 | | |
55 | 0 | cmark_node_set_syntax_extension(strikethrough, self); |
56 | |
|
57 | 0 | tmp = cmark_node_next(opener->inl_text); |
58 | |
|
59 | 0 | while (tmp) { |
60 | 0 | if (tmp == closer->inl_text) |
61 | 0 | break; |
62 | 0 | next = cmark_node_next(tmp); |
63 | 0 | cmark_node_append_child(strikethrough, tmp); |
64 | 0 | tmp = next; |
65 | 0 | } |
66 | |
|
67 | 0 | strikethrough->end_column = closer->inl_text->start_column + closer->inl_text->as.literal.len - 1; |
68 | 0 | cmark_node_free(closer->inl_text); |
69 | |
|
70 | 0 | done: |
71 | 0 | delim = closer; |
72 | 0 | while (delim != NULL && delim != opener) { |
73 | 0 | tmp_delim = delim->previous; |
74 | 0 | cmark_inline_parser_remove_delimiter(inline_parser, delim); |
75 | 0 | delim = tmp_delim; |
76 | 0 | } |
77 | |
|
78 | 0 | cmark_inline_parser_remove_delimiter(inline_parser, opener); |
79 | |
|
80 | 0 | return res; |
81 | 0 | } |
82 | | |
83 | | static const char *get_type_string(cmark_syntax_extension *extension, |
84 | 0 | cmark_node *node) { |
85 | 0 | return node->type == CMARK_NODE_STRIKETHROUGH ? "strikethrough" : "<unknown>"; |
86 | 0 | } |
87 | | |
88 | | static int can_contain(cmark_syntax_extension *extension, cmark_node *node, |
89 | 0 | cmark_node_type child_type) { |
90 | 0 | if (node->type != CMARK_NODE_STRIKETHROUGH) |
91 | 0 | return false; |
92 | | |
93 | 0 | return CMARK_NODE_TYPE_INLINE_P(child_type); |
94 | 0 | } |
95 | | |
96 | | static void commonmark_render(cmark_syntax_extension *extension, |
97 | | cmark_renderer *renderer, cmark_node *node, |
98 | 0 | cmark_event_type ev_type, int options) { |
99 | 0 | renderer->out(renderer, node, "~~", false, LITERAL); |
100 | 0 | } |
101 | | |
102 | | static void latex_render(cmark_syntax_extension *extension, |
103 | | cmark_renderer *renderer, cmark_node *node, |
104 | 0 | cmark_event_type ev_type, int options) { |
105 | | // requires \usepackage{ulem} |
106 | 0 | bool entering = (ev_type == CMARK_EVENT_ENTER); |
107 | 0 | if (entering) { |
108 | 0 | renderer->out(renderer, node, "\\sout{", false, LITERAL); |
109 | 0 | } else { |
110 | 0 | renderer->out(renderer, node, "}", false, LITERAL); |
111 | 0 | } |
112 | 0 | } |
113 | | |
114 | | static void man_render(cmark_syntax_extension *extension, |
115 | | cmark_renderer *renderer, cmark_node *node, |
116 | 0 | cmark_event_type ev_type, int options) { |
117 | 0 | bool entering = (ev_type == CMARK_EVENT_ENTER); |
118 | 0 | if (entering) { |
119 | 0 | renderer->cr(renderer); |
120 | 0 | renderer->out(renderer, node, ".ST \"", false, LITERAL); |
121 | 0 | } else { |
122 | 0 | renderer->out(renderer, node, "\"", false, LITERAL); |
123 | 0 | renderer->cr(renderer); |
124 | 0 | } |
125 | 0 | } |
126 | | |
127 | | static void html_render(cmark_syntax_extension *extension, |
128 | | cmark_html_renderer *renderer, cmark_node *node, |
129 | 0 | cmark_event_type ev_type, int options) { |
130 | 0 | bool entering = (ev_type == CMARK_EVENT_ENTER); |
131 | 0 | if (entering) { |
132 | 0 | cmark_strbuf_puts(renderer->html, "<del>"); |
133 | 0 | } else { |
134 | 0 | cmark_strbuf_puts(renderer->html, "</del>"); |
135 | 0 | } |
136 | 0 | } |
137 | | |
138 | | static void plaintext_render(cmark_syntax_extension *extension, |
139 | | cmark_renderer *renderer, cmark_node *node, |
140 | 0 | cmark_event_type ev_type, int options) { |
141 | 0 | renderer->out(renderer, node, "~", false, LITERAL); |
142 | 0 | } |
143 | | |
144 | 0 | cmark_syntax_extension *create_strikethrough_extension(void) { |
145 | 0 | cmark_syntax_extension *ext = cmark_syntax_extension_new("strikethrough"); |
146 | 0 | cmark_llist *special_chars = NULL; |
147 | |
|
148 | 0 | cmark_syntax_extension_set_get_type_string_func(ext, get_type_string); |
149 | 0 | cmark_syntax_extension_set_can_contain_func(ext, can_contain); |
150 | 0 | cmark_syntax_extension_set_commonmark_render_func(ext, commonmark_render); |
151 | 0 | cmark_syntax_extension_set_latex_render_func(ext, latex_render); |
152 | 0 | cmark_syntax_extension_set_man_render_func(ext, man_render); |
153 | 0 | cmark_syntax_extension_set_html_render_func(ext, html_render); |
154 | 0 | cmark_syntax_extension_set_plaintext_render_func(ext, plaintext_render); |
155 | 0 | CMARK_NODE_STRIKETHROUGH = cmark_syntax_extension_add_node(1); |
156 | |
|
157 | 0 | cmark_syntax_extension_set_match_inline_func(ext, match); |
158 | 0 | cmark_syntax_extension_set_inline_from_delim_func(ext, insert); |
159 | |
|
160 | 0 | cmark_mem *mem = cmark_get_default_mem_allocator(); |
161 | 0 | special_chars = cmark_llist_append(mem, special_chars, (void *)'~'); |
162 | 0 | cmark_syntax_extension_set_special_inline_chars(ext, special_chars); |
163 | |
|
164 | 0 | cmark_syntax_extension_set_emphasis(ext, 1); |
165 | |
|
166 | 0 | return ext; |
167 | 0 | } |