Skip to content

Commit 1c22565

Browse files
Example inline extension: strikethrough text
1 parent d3777c5 commit 1c22565

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

extensions/core-extensions.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,94 @@ static cmark_syntax_extension *register_table_syntax_extension(void) {
220220
return ext;
221221
}
222222

223+
static cmark_node *strikethrough_match(cmark_syntax_extension *self,
224+
cmark_parser *parser,
225+
cmark_node *parent,
226+
unsigned char character,
227+
cmark_inline_parser *inline_parser)
228+
{
229+
cmark_node *res = NULL;
230+
int left_flanking, right_flanking, punct_before, punct_after;
231+
int num_delims;
232+
233+
/* Exit early */
234+
if (character != '~')
235+
return NULL;
236+
237+
num_delims = cmark_inline_parser_scan_delimiters(inline_parser, 1, '~',
238+
&left_flanking, &right_flanking, &punct_before, &punct_after);
239+
240+
if (num_delims > 0) { /* Should not be needed */
241+
int can_open, can_close;
242+
243+
res = cmark_node_new(CMARK_NODE_TEXT);
244+
cmark_node_set_literal(res, "~");
245+
246+
can_open = left_flanking;
247+
can_close = right_flanking;
248+
if (can_open || can_close)
249+
cmark_inline_parser_push_delimiter(inline_parser, character, can_open, can_close, res);
250+
}
251+
252+
return res;
253+
}
254+
255+
static delimiter *strikethrough_insert(cmark_syntax_extension *self,
256+
cmark_parser *parser,
257+
cmark_inline_parser *inline_parser,
258+
delimiter *opener,
259+
delimiter *closer)
260+
{
261+
cmark_node *strikethrough;
262+
cmark_node *tmp, *next;
263+
delimiter *delim, *tmp_delim;
264+
delimiter *res = closer->next;
265+
266+
strikethrough = opener->inl_text;
267+
268+
if (!cmark_node_set_type(strikethrough, CMARK_NODE_STRIKETHROUGH))
269+
goto done;
270+
271+
cmark_node_set_string_content(strikethrough, "~");
272+
tmp = cmark_node_next(opener->inl_text);
273+
274+
while (tmp) {
275+
if (tmp == closer->inl_text)
276+
break;
277+
next = cmark_node_next(tmp);
278+
cmark_node_append_child(strikethrough, tmp);
279+
tmp = next;
280+
}
281+
282+
cmark_node_free(closer->inl_text);
283+
284+
delim = closer;
285+
while (delim != NULL && delim != opener) {
286+
tmp_delim = delim->previous;
287+
cmark_inline_parser_remove_delimiter(inline_parser, delim);
288+
delim = tmp_delim;
289+
}
290+
291+
cmark_inline_parser_remove_delimiter(inline_parser, opener);
292+
293+
done:
294+
return res;
295+
}
296+
297+
static cmark_syntax_extension *create_strikethrough_extension(void) {
298+
cmark_syntax_extension *ext = cmark_syntax_extension_new("tilde_strikethrough");
299+
cmark_llist *special_chars = NULL;
300+
301+
cmark_syntax_extension_set_match_inline_func(ext, strikethrough_match);
302+
cmark_syntax_extension_set_inline_from_delim_func(ext, strikethrough_insert);
303+
special_chars = cmark_llist_append(special_chars, (void *) '~');
304+
cmark_syntax_extension_set_special_inline_chars(ext, special_chars);
305+
306+
return ext;
307+
}
308+
223309
int init_libcmarkextensions(cmark_plugin *plugin) {
224310
cmark_plugin_register_syntax_extension(plugin, register_table_syntax_extension());
311+
cmark_plugin_register_syntax_extension(plugin, create_strikethrough_extension());
225312
return 1;
226313
}

0 commit comments

Comments
 (0)