@@ -11,25 +11,74 @@ static cmark_node *match(cmark_syntax_extension *self, cmark_parser *parser,
11
11
int left_flanking , right_flanking , punct_before , punct_after , delims ;
12
12
char buffer [101 ];
13
13
14
- if (character != '|' )
15
- return NULL ;
16
-
17
- delims = cmark_inline_parser_scan_delimiters (
18
- inline_parser , sizeof (buffer ) - 1 , '|' ,
19
- & left_flanking ,
20
- & right_flanking , & punct_before , & punct_after );
21
-
22
- memset (buffer , '|' , delims );
23
- buffer [delims ] = 0 ;
24
-
25
- res = cmark_node_new_with_mem (CMARK_NODE_TEXT , parser -> mem );
26
- cmark_node_set_literal (res , buffer );
27
- res -> start_line = res -> end_line = cmark_inline_parser_get_line (inline_parser );
28
- res -> start_column = cmark_inline_parser_get_column (inline_parser ) - delims ;
29
-
30
- if ((left_flanking || right_flanking ) && (delims == 2 )) {
31
- cmark_inline_parser_push_delimiter (inline_parser , character , left_flanking ,
32
- right_flanking , res );
14
+ if ((parser -> options & CMARK_OPT_SPOILER_REDDIT_STYLE )) {
15
+ // Reddit-style spoilers - flanked by angle brackets and exclamation marks,
16
+ // e.g. >!this is a spoiler!<
17
+ int pos = cmark_inline_parser_get_offset (inline_parser );
18
+ char * txt = NULL ;
19
+ bool opener = false;
20
+ bool closer = false;
21
+ if (cmark_inline_parser_peek_at (inline_parser , pos ) == '>' &&
22
+ cmark_inline_parser_peek_at (inline_parser , pos + 1 ) == '!' ) {
23
+ txt = ">!" ;
24
+ opener = true;
25
+ } else if (cmark_inline_parser_peek_at (inline_parser , pos ) == '!' &&
26
+ cmark_inline_parser_peek_at (inline_parser , pos + 1 ) == '<' ) {
27
+ txt = "!<" ;
28
+ closer = true;
29
+ }
30
+
31
+ if (opener && pos > 0 && !cmark_isspace (cmark_inline_parser_peek_at (inline_parser , pos - 1 ))) {
32
+ opener = false;
33
+ }
34
+
35
+ if (closer ) {
36
+ cmark_chunk * chunk = cmark_inline_parser_get_chunk (inline_parser );
37
+ bufsize_t len = chunk -> len ;
38
+ if (pos + 2 < len && !cmark_isspace (cmark_inline_parser_peek_at (inline_parser , pos + 2 ))) {
39
+ closer = false;
40
+ }
41
+ }
42
+
43
+ if ((!opener && !closer ) || !txt )
44
+ return NULL ;
45
+
46
+ res = cmark_node_new_with_mem (CMARK_NODE_TEXT , parser -> mem );
47
+ cmark_node_set_literal (res , txt );
48
+ res -> start_line = cmark_inline_parser_get_line (inline_parser );
49
+ res -> start_column = cmark_inline_parser_get_column (inline_parser );
50
+
51
+ cmark_inline_parser_set_offset (inline_parser , pos + 2 );
52
+
53
+ res -> end_line = cmark_inline_parser_get_line (inline_parser );
54
+ res -> end_column = cmark_inline_parser_get_column (inline_parser );
55
+
56
+ // Set the character for this delimiter to `!`, since it's a heterogenous
57
+ // delimiter and the delimiter API assumes single repeated characters.
58
+ cmark_inline_parser_push_delimiter (inline_parser , '!' , opener , closer , res );
59
+ } else {
60
+ // Discord-style spoilers - flanked on both sides by two pipes,
61
+ // e.g. ||this is a spoiler||
62
+ if (character != '|' )
63
+ return NULL ;
64
+
65
+ delims = cmark_inline_parser_scan_delimiters (
66
+ inline_parser , sizeof (buffer ) - 1 , '|' ,
67
+ & left_flanking ,
68
+ & right_flanking , & punct_before , & punct_after );
69
+
70
+ memset (buffer , '|' , delims );
71
+ buffer [delims ] = 0 ;
72
+
73
+ res = cmark_node_new_with_mem (CMARK_NODE_TEXT , parser -> mem );
74
+ cmark_node_set_literal (res , buffer );
75
+ res -> start_line = res -> end_line = cmark_inline_parser_get_line (inline_parser );
76
+ res -> start_column = cmark_inline_parser_get_column (inline_parser ) - delims ;
77
+
78
+ if ((left_flanking || right_flanking ) && (delims == 2 )) {
79
+ cmark_inline_parser_push_delimiter (inline_parser , character , left_flanking ,
80
+ right_flanking , res );
81
+ }
33
82
}
34
83
35
84
return res ;
@@ -95,7 +144,16 @@ static int can_contain(cmark_syntax_extension *extension, cmark_node *node,
95
144
static void commonmark_render (cmark_syntax_extension * extension ,
96
145
cmark_renderer * renderer , cmark_node * node ,
97
146
cmark_event_type ev_type , int options ) {
98
- renderer -> out (renderer , node , "||" , false, LITERAL );
147
+ if (options & CMARK_OPT_SPOILER_REDDIT_STYLE ) {
148
+ bool entering = (ev_type == CMARK_EVENT_ENTER );
149
+ if (entering ) {
150
+ renderer -> out (renderer , node , ">!" , false, LITERAL );
151
+ } else {
152
+ renderer -> out (renderer , node , "!<" , false, LITERAL );
153
+ }
154
+ } else {
155
+ renderer -> out (renderer , node , "||" , false, LITERAL );
156
+ }
99
157
}
100
158
101
159
static void html_render (cmark_syntax_extension * extension ,
@@ -109,12 +167,6 @@ static void html_render(cmark_syntax_extension *extension,
109
167
}
110
168
}
111
169
112
- static void plaintext_render (cmark_syntax_extension * extension ,
113
- cmark_renderer * renderer , cmark_node * node ,
114
- cmark_event_type ev_type , int options ) {
115
- renderer -> out (renderer , node , "~" , false, LITERAL );
116
- }
117
-
118
170
cmark_syntax_extension * create_spoiler_extension (void ) {
119
171
cmark_syntax_extension * ext = cmark_syntax_extension_new ("spoiler" );
120
172
cmark_llist * special_chars = NULL ;
@@ -123,14 +175,17 @@ cmark_syntax_extension *create_spoiler_extension(void) {
123
175
cmark_syntax_extension_set_can_contain_func (ext , can_contain );
124
176
cmark_syntax_extension_set_commonmark_render_func (ext , commonmark_render );
125
177
cmark_syntax_extension_set_html_render_func (ext , html_render );
126
- cmark_syntax_extension_set_plaintext_render_func (ext , plaintext_render );
178
+ cmark_syntax_extension_set_plaintext_render_func (ext , commonmark_render );
127
179
CMARK_NODE_SPOILER = cmark_syntax_extension_add_node (1 );
128
180
129
181
cmark_syntax_extension_set_match_inline_func (ext , match );
130
182
cmark_syntax_extension_set_inline_from_delim_func (ext , insert );
131
183
132
184
cmark_mem * mem = cmark_get_default_mem_allocator ();
133
185
special_chars = cmark_llist_append (mem , special_chars , (void * )'|' );
186
+ special_chars = cmark_llist_append (mem , special_chars , (void * )'>' );
187
+ special_chars = cmark_llist_append (mem , special_chars , (void * )'<' );
188
+ special_chars = cmark_llist_append (mem , special_chars , (void * )'!' );
134
189
cmark_syntax_extension_set_special_inline_chars (ext , special_chars );
135
190
136
191
cmark_syntax_extension_set_emphasis (ext , 1 );
0 commit comments