dtext_rb 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/dtext/dtext.h DELETED
@@ -1,4 +0,0 @@
1
- #ifndef DTEXT_H
2
- #define DTEXT_H
3
-
4
- #endif
data/ext/dtext/dtext.rl DELETED
@@ -1,1454 +0,0 @@
1
- // situationally print newlines to make the generated html
2
- // easier to read
3
- #define PRETTY_PRINT 0
4
-
5
- #include <ruby.h>
6
- #include <ruby/encoding.h>
7
- #include <stdio.h>
8
- #include <stdint.h>
9
- #include <stdbool.h>
10
- #include <glib.h>
11
-
12
- typedef struct StateMachine {
13
- size_t top;
14
- int cs;
15
- int act;
16
- const char * p;
17
- const char * pb;
18
- const char * pe;
19
- const char * eof;
20
- const char * ts;
21
- const char * te;
22
-
23
- const char * a1;
24
- const char * a2;
25
- const char * b1;
26
- const char * b2;
27
- bool f_inline;
28
- bool f_strip;
29
- bool f_mentions;
30
- bool list_mode;
31
- bool header_mode;
32
- GString * output;
33
- GArray * stack;
34
- GQueue * dstack;
35
- int list_nest;
36
- int d;
37
- int b;
38
- int quote;
39
- } StateMachine;
40
-
41
- static const size_t MAX_STACK_DEPTH = 512;
42
-
43
- static const int BLOCK_P = 1;
44
- static const int INLINE_SPOILER = 2;
45
- static const int BLOCK_SPOILER = 3;
46
- static const int BLOCK_QUOTE = 4;
47
- static const int BLOCK_EXPAND = 5;
48
- static const int BLOCK_NODTEXT = 6;
49
- static const int BLOCK_CODE = 7;
50
- static const int BLOCK_TD = 8;
51
- static const int INLINE_NODTEXT = 9;
52
- static const int INLINE_B = 10;
53
- static const int INLINE_I = 11;
54
- static const int INLINE_U = 12;
55
- static const int INLINE_S = 13;
56
- static const int INLINE_TN = 14;
57
- static const int BLOCK_TN = 15;
58
- static const int BLOCK_TABLE = 16;
59
- static const int BLOCK_THEAD = 17;
60
- static const int BLOCK_TBODY = 18;
61
- static const int BLOCK_TR = 19;
62
- static const int BLOCK_UL = 20;
63
- static const int BLOCK_LI = 21;
64
- static const int BLOCK_TH = 22;
65
- static const int BLOCK_H1 = 23;
66
- static const int BLOCK_H2 = 24;
67
- static const int BLOCK_H3 = 25;
68
- static const int BLOCK_H4 = 26;
69
- static const int BLOCK_H5 = 27;
70
- static const int BLOCK_H6 = 28;
71
-
72
- %%{
73
- machine dtext;
74
-
75
- access sm->;
76
- variable p sm->p;
77
- variable pe sm->pe;
78
- variable eof sm->eof;
79
- variable top sm->top;
80
- variable ts sm->ts;
81
- variable te sm->te;
82
- variable act sm->act;
83
- variable stack ((int *)sm->stack->data);
84
-
85
- prepush {
86
- size_t len = sm->stack->len;
87
-
88
- if (len > MAX_STACK_DEPTH) {
89
- free_machine(sm);
90
- rb_raise(rb_eSyntaxError, "too many nested elements");
91
- }
92
-
93
- if (sm->top >= len) {
94
- sm->stack = g_array_set_size(sm->stack, len + 16);
95
- }
96
- }
97
-
98
- action mark_a1 {
99
- sm->a1 = sm->p;
100
- }
101
-
102
- action mark_a2 {
103
- sm->a2 = sm->p;
104
- }
105
-
106
- action mark_b1 {
107
- sm->b1 = sm->p;
108
- }
109
-
110
- action mark_b2 {
111
- sm->b2 = sm->p;
112
- }
113
-
114
- newline = '\r\n' | '\n';
115
-
116
- nonnewline = any - (newline | '\0' | '\r');
117
- nonquote = ^'"';
118
- nonbracket = ^']';
119
- nonpipe = ^'|';
120
- nonpipebracket = nonpipe & nonbracket;
121
- noncurly = ^'}';
122
-
123
- utf8graph = (0x00..0x7F) & graph
124
- | 0xC2..0xDF 0x80..0xBF
125
- | 0xE0..0xEF 0x80..0xBF 0x80..0xBF
126
- | 0xF0..0xF4 0x80..0xBF 0x80..0xBF 0x80..0xBF;
127
-
128
-
129
- mention = '@' utf8graph+ >mark_a1 %mark_a2;
130
-
131
- url = 'http' 's'? '://' utf8graph+;
132
- internal_url = '/' utf8graph+;
133
- basic_textile_link = '"' nonquote+ >mark_a1 '"' >mark_a2 ':' (url | internal_url) >mark_b1 %mark_b2;
134
- bracketed_textile_link = '"' nonquote+ >mark_a1 '"' >mark_a2 ':[' (url | internal_url) >mark_b1 %mark_b2 :>> ']';
135
-
136
- basic_wiki_link = '[[' (nonbracket nonpipebracket*) >mark_a1 %mark_a2 ']]';
137
- aliased_wiki_link = '[[' nonpipebracket+ >mark_a1 %mark_a2 '|' nonpipebracket+ >mark_b1 %mark_b2 ']]';
138
-
139
- post_link = '{{' noncurly+ >mark_a1 %mark_a2 '}}';
140
-
141
- spoilers_open = '[spoiler'i 's'i? ']';
142
- spoilers_close = '[/spoiler'i 's'i? ']';
143
-
144
- post_id = 'post #'i digit+ >mark_a1 %mark_a2;
145
- forum_post_id = 'forum #'i digit+ >mark_a1 %mark_a2;
146
- forum_topic_id = 'topic #'i digit+ >mark_a1 %mark_a2;
147
- forum_topic_paged_id = 'topic #'i digit+ >mark_a1 %mark_a2 '/p' digit+ >mark_b1 %mark_b2;
148
- comment_id = 'comment #'i digit+ >mark_a1 %mark_a2;
149
- pool_id = 'pool #'i digit+ >mark_a1 %mark_a2;
150
- user_id = 'user #'i digit+ >mark_a1 %mark_a2;
151
- artist_id = 'artist #'i digit+ >mark_a1 %mark_a2;
152
- github_issue_id = 'issue #'i digit+ >mark_a1 %mark_a2;
153
- pixiv_id = 'pixiv #'i digit+ >mark_a1 %mark_a2;
154
- pixiv_paged_id = 'pixiv #'i digit+ >mark_a1 %mark_a2 '/p' digit+ >mark_b1 %mark_b2;
155
-
156
- ws = ' ' | '\t';
157
- nonperiod = graph - ('.' | '"');
158
- header = 'h'i [123456] >mark_a1 %mark_a2 '.' ws*;
159
- header_with_id = 'h'i [123456] >mark_a1 %mark_a2 '#' nonperiod+ >mark_b1 %mark_b2 '.' ws*;
160
- aliased_expand = '[expand='i (nonbracket+ >mark_a1 %mark_a2) ']';
161
-
162
- list_item = '*'+ >mark_a1 %mark_a2 ws+ nonnewline+ >mark_b1 %mark_b2;
163
-
164
- inline := |*
165
- post_id => {
166
- append(sm, true, "<a href=\"/posts/");
167
- append_segment(sm, true, sm->a1, sm->a2 - 1);
168
- append(sm, true, "\">");
169
- append(sm, false, "post #");
170
- append_segment(sm, false, sm->a1, sm->a2 - 1);
171
- append(sm, true, "</a>");
172
- };
173
-
174
- forum_post_id => {
175
- append(sm, true, "<a href=\"/forum_posts/");
176
- append_segment(sm, true, sm->a1, sm->a2 - 1);
177
- append(sm, true, "\">");
178
- append(sm, false, "forum #");
179
- append_segment(sm, false, sm->a1, sm->a2 - 1);
180
- append(sm, true, "</a>");
181
- };
182
-
183
- forum_topic_id => {
184
- append(sm, true, "<a href=\"/forum_topics/");
185
- append_segment(sm, true, sm->a1, sm->a2 - 1);
186
- append(sm, true, "\">");
187
- append(sm, false, "topic #");
188
- append_segment(sm, false, sm->a1, sm->a2 - 1);
189
- append(sm, true, "</a>");
190
- };
191
-
192
- forum_topic_paged_id => {
193
- append(sm, true, "<a href=\"/forum_topics/");
194
- append_segment(sm, true, sm->a1, sm->a2 - 1);
195
- append(sm, true, "?page=");
196
- append_segment(sm, true, sm->b1, sm->b2 - 1);
197
- append(sm, true, "\">");
198
- append(sm, false, "topic #");
199
- append_segment(sm, false, sm->a1, sm->a2 - 1);
200
- append(sm, false, "/p");
201
- append_segment(sm, false, sm->b1, sm->b2 - 1);
202
- append(sm, true, "</a>");
203
- };
204
-
205
- comment_id => {
206
- append(sm, true, "<a href=\"/comments/");
207
- append_segment(sm, true, sm->a1, sm->a2 - 1);
208
- append(sm, true, "\">");
209
- append(sm, false, "comment #");
210
- append_segment(sm, false, sm->a1, sm->a2 - 1);
211
- append(sm, true, "</a>");
212
- };
213
-
214
- pool_id => {
215
- append(sm, true, "<a href=\"/pools/");
216
- append_segment(sm, true, sm->a1, sm->a2 - 1);
217
- append(sm, true, "\">");
218
- append(sm, false, "pool #");
219
- append_segment(sm, false, sm->a1, sm->a2 - 1);
220
- append(sm, true, "</a>");
221
- };
222
-
223
- user_id => {
224
- append(sm, true, "<a href=\"/users/");
225
- append_segment(sm, true, sm->a1, sm->a2 - 1);
226
- append(sm, true, "\">");
227
- append(sm, false, "user #");
228
- append_segment(sm, false, sm->a1, sm->a2 - 1);
229
- append(sm, true, "</a>");
230
- };
231
-
232
- artist_id => {
233
- append(sm, true, "<a href=\"/artists/");
234
- append_segment(sm, true, sm->a1, sm->a2 - 1);
235
- append(sm, true, "\">");
236
- append(sm, false, "artist #");
237
- append_segment(sm, false, sm->a1, sm->a2 - 1);
238
- append(sm, true, "</a>");
239
- };
240
-
241
- github_issue_id => {
242
- append(sm, true, "<a href=\"https://github.com/r888888888/danbooru/issues/");
243
- append_segment(sm, true, sm->a1, sm->a2 - 1);
244
- append(sm, true, "\">");
245
- append(sm, false, "issue #");
246
- append_segment(sm, false, sm->a1, sm->a2 - 1);
247
- append(sm, true, "</a>");
248
- };
249
-
250
- pixiv_id => {
251
- append(sm, true, "<a href=\"http://www.pixiv.net/member_illust.php?mode=medium&illust_id=");
252
- append_segment(sm, true, sm->a1, sm->a2 - 1);
253
- append(sm, true, "\">");
254
- append(sm, false, "pixiv #");
255
- append_segment(sm, false, sm->a1, sm->a2 - 1);
256
- append(sm, true, "</a>");
257
- };
258
-
259
- pixiv_paged_id => {
260
- append(sm, true, "<a href=\"http://www.pixiv.net/member_illust.php?mode=manga_big&illust_id=");
261
- append_segment(sm, true, sm->a1, sm->a2 - 1);
262
- append(sm, true, "&page=");
263
- append_segment(sm, true, sm->b1, sm->b2 - 1);
264
- append(sm, true, "\">");
265
- append(sm, false, "pixiv #");
266
- append_segment(sm, false, sm->a1, sm->a2 - 1);
267
- append(sm, false, "/p");
268
- append_segment(sm, false, sm->b1, sm->b2 - 1);
269
- append(sm, true, "</a>");
270
- };
271
-
272
- post_link => {
273
- append(sm, true, "<a rel=\"nofollow\" href=\"/posts?tags=");
274
- append_segment_uri_escaped(sm, sm->a1, sm->a2 - 1);
275
- append(sm, true, "\">");
276
- append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
277
- append(sm, true, "</a>");
278
- };
279
-
280
- basic_wiki_link => {
281
- GString * segment = g_string_new_len(sm->a1, sm->a2 - sm->a1);
282
- GString * lowercase_segment = NULL;
283
- underscore_string(segment->str, segment->len);
284
-
285
- if (g_utf8_validate(segment->str, -1, NULL)) {
286
- lowercase_segment = g_string_new(g_utf8_strdown(segment->str, -1));
287
- } else {
288
- lowercase_segment = g_string_new(g_ascii_strdown(segment->str, -1));
289
- }
290
-
291
- append(sm, true, "<a href=\"/wiki_pages/show_or_new?title=");
292
- append_segment_uri_escaped(sm, lowercase_segment->str, lowercase_segment->str + lowercase_segment->len - 1);
293
- append(sm, true, "\">");
294
- append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
295
- append(sm, true, "</a>");
296
-
297
- g_string_free(lowercase_segment, TRUE);
298
- g_string_free(segment, TRUE);
299
- };
300
-
301
- aliased_wiki_link => {
302
- GString * segment = g_string_new_len(sm->a1, sm->a2 - sm->a1);
303
- GString * lowercase_segment = NULL;
304
- underscore_string(segment->str, segment->len);
305
-
306
- if (g_utf8_validate(segment->str, -1, NULL)) {
307
- lowercase_segment = g_string_new(g_utf8_strdown(segment->str, -1));
308
- } else {
309
- lowercase_segment = g_string_new(g_ascii_strdown(segment->str, -1));
310
- }
311
-
312
- append(sm, true, "<a href=\"/wiki_pages/show_or_new?title=");
313
- append_segment_uri_escaped(sm, lowercase_segment->str, lowercase_segment->str + lowercase_segment->len - 1);
314
- append(sm, true, "\">");
315
- append_segment_html_escaped(sm, sm->b1, sm->b2 - 1);
316
- append(sm, true, "</a>");
317
-
318
- g_string_free(lowercase_segment, TRUE);
319
- g_string_free(segment, TRUE);
320
- };
321
-
322
- basic_textile_link => {
323
- if (is_boundary_c(fc)) {
324
- sm->d = 2;
325
- sm->b = true;
326
- } else {
327
- sm->d = 1;
328
- sm->b = false;
329
- }
330
-
331
- append(sm, true, "<a href=\"");
332
- append_segment_html_escaped(sm, sm->b1, sm->b2 - sm->d);
333
- append(sm, true, "\">");
334
- link_content_sm = parse_helper(sm->a1, sm->a2 - sm->a1, false, true, false);
335
- append(sm, true, link_content_sm->output->str);
336
- free_machine(link_content_sm);
337
- link_content_sm = NULL;
338
- append(sm, true, "</a>");
339
-
340
- if (sm->b) {
341
- append_c_html_escaped(sm, fc);
342
- }
343
- };
344
-
345
- bracketed_textile_link => {
346
- append(sm, true, "<a href=\"");
347
- append_segment_html_escaped(sm, sm->b1, sm->b2 - 1);
348
- append(sm, true, "\">");
349
- append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
350
- append(sm, true, "</a>");
351
- };
352
-
353
- url => {
354
- if (is_boundary_c(fc)) {
355
- sm->b = true;
356
- sm->d = 2;
357
- } else {
358
- sm->b = false;
359
- sm->d = 1;
360
- }
361
-
362
- append(sm, true, "<a href=\"");
363
- append_segment_html_escaped(sm, sm->ts, sm->te - sm->d);
364
- append(sm, true, "\">");
365
- append_segment_html_escaped(sm, sm->ts, sm->te - sm->d);
366
- append(sm, true, "</a>");
367
-
368
- if (sm->b) {
369
- append_c_html_escaped(sm, fc);
370
- }
371
- };
372
-
373
- # probably a tag. examples include @.@ and @_@
374
- '@' graph '@' => {
375
- append_segment_html_escaped(sm, sm->ts, sm->te - 1);
376
- };
377
-
378
- mention => {
379
- if (!sm->f_mentions || (sm->a1 > sm->pb && sm->a1 - 1 > sm->pb && sm->a1[-2] != ' ' && sm->a1[-2] != '\r' && sm->a1[-2] != '\n')) {
380
- // handle emails
381
- append_c(sm, '@');
382
- append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
383
-
384
- } else {
385
- if (is_boundary_c(fc)) {
386
- sm->b = true;
387
- sm->d = 2;
388
- } else {
389
- sm->b = false;
390
- sm->d = 1;
391
- }
392
-
393
- append(sm, true, "<a rel=\"nofollow\" href=\"/users?name=");
394
- append_segment_uri_escaped(sm, sm->a1, sm->a2 - sm->d);
395
- append(sm, true, "\">");
396
- append_c(sm, '@');
397
- append_segment_html_escaped(sm, sm->a1, sm->a2 - sm->d);
398
- append(sm, true, "</a>");
399
-
400
- if (sm->b) {
401
- append_c_html_escaped(sm, fc);
402
- }
403
- }
404
- };
405
-
406
- newline list_item => {
407
- g_debug("inline list");
408
-
409
- if (dstack_check(sm, BLOCK_LI)) {
410
- g_debug(" rewind li");
411
- dstack_rewind(sm);
412
- } else if (dstack_check(sm, BLOCK_P)) {
413
- g_debug(" rewind p");
414
- dstack_rewind(sm);
415
- } else if (sm->header_mode) {
416
- g_debug(" rewind header");
417
- dstack_rewind(sm);
418
- }
419
-
420
- g_debug(" next list");
421
- fexec sm->ts + 1;
422
- fnext list;
423
- };
424
-
425
- '[b]'i => {
426
- dstack_push(sm, &INLINE_B);
427
- append(sm, true, "<strong>");
428
- };
429
-
430
- '[/b]'i => {
431
- if (dstack_check(sm, INLINE_B)) {
432
- dstack_pop(sm);
433
- append(sm, true, "</strong>");
434
- } else {
435
- append(sm, true, "[/b]");
436
- }
437
- };
438
-
439
- '[i]'i => {
440
- dstack_push(sm, &INLINE_I);
441
- append(sm, true, "<em>");
442
- };
443
-
444
- '[/i]'i => {
445
- if (dstack_check(sm, INLINE_I)) {
446
- dstack_pop(sm);
447
- append(sm, true, "</em>");
448
- } else {
449
- append(sm, true, "[/i]");
450
- }
451
- };
452
-
453
- '[s]'i => {
454
- dstack_push(sm, &INLINE_S);
455
- append(sm, true, "<s>");
456
- };
457
-
458
- '[/s]'i => {
459
- if (dstack_check(sm, INLINE_S)) {
460
- dstack_pop(sm);
461
- append(sm, true, "</s>");
462
- } else {
463
- append(sm, true, "[/s]");
464
- }
465
- };
466
-
467
- '[u]'i => {
468
- dstack_push(sm, &INLINE_U);
469
- append(sm, true, "<u>");
470
- };
471
-
472
- '[/u]'i => {
473
- if (dstack_check(sm, INLINE_U)) {
474
- dstack_pop(sm);
475
- append(sm, true, "</u>");
476
- } else {
477
- append(sm, true, "[/u]");
478
- }
479
- };
480
-
481
- '[tn]'i => {
482
- dstack_push(sm, &INLINE_TN);
483
- append(sm, true, "<span class=\"tn\">");
484
- };
485
-
486
- '[/tn]'i => {
487
- dstack_close_before_block(sm);
488
-
489
- if (dstack_check(sm, BLOCK_TN)) {
490
- dstack_pop(sm);
491
- fret;
492
- } else if (dstack_check(sm, INLINE_TN)) {
493
- dstack_pop(sm);
494
- append(sm, true, "</span>");
495
- } else {
496
- append_block(sm, "[/tn]");
497
- }
498
- };
499
-
500
- spoilers_open => {
501
- g_debug("inline [spoiler]");
502
- g_debug(" push <span>");
503
- dstack_push(sm, &INLINE_SPOILER);
504
- append(sm, true, "<span class=\"spoiler\">");
505
- };
506
-
507
- spoilers_close => {
508
- g_debug("inline [/spoiler]");
509
- dstack_close_before_block(sm);
510
-
511
- if (dstack_check(sm, INLINE_SPOILER)) {
512
- g_debug(" pop dstack");
513
- g_debug(" print </span>");
514
- dstack_pop(sm);
515
- append(sm, true, "</span>");
516
- } else if (dstack_check(sm, BLOCK_SPOILER)) {
517
- g_debug(" pop dstack");
518
- g_debug(" print </div>");
519
- g_debug(" return");
520
- dstack_pop(sm);
521
- append_block(sm, "</div>");
522
- fret;
523
- } else {
524
- append_block(sm, "[/spoiler]");
525
- }
526
- };
527
-
528
- '[nodtext]'i => {
529
- dstack_push(sm, &INLINE_NODTEXT);
530
- g_debug("push inline nodtext");
531
- fcall nodtext;
532
- };
533
-
534
- # these are block level elements that should kick us out of the inline
535
- # scanner
536
-
537
- '[quote]'i => {
538
- g_debug("inline [quote]");
539
- dstack_close_before_block(sm);
540
- fexec sm->ts;
541
- fret;
542
- };
543
-
544
- '[/quote]'i space* => {
545
- g_debug("inline [/quote]");
546
- dstack_close_before_block(sm);
547
-
548
- if (dstack_check(sm, BLOCK_LI)) {
549
- dstack_close_list(sm);
550
- }
551
-
552
- if (dstack_check(sm, BLOCK_QUOTE)) {
553
- dstack_rewind(sm);
554
- fret;
555
- } else {
556
- append_block(sm, "[/quote]");
557
- }
558
- };
559
-
560
- '[expand]'i => {
561
- g_debug("inline [expand]");
562
- dstack_rewind(sm);
563
- fexec(sm->p - 7);
564
- fret;
565
- };
566
-
567
- '[/expand]'i => {
568
- dstack_close_before_block(sm);
569
-
570
- if (dstack_check(sm, BLOCK_EXPAND)) {
571
- append_block(sm, "</div></div>");
572
- dstack_pop(sm);
573
- fret;
574
- } else {
575
- append_block(sm, "[/expand]");
576
- }
577
- };
578
-
579
- '[/th]'i => {
580
- if (dstack_check(sm, BLOCK_TH)) {
581
- dstack_pop(sm);
582
- append_block(sm, "</th>");
583
- fret;
584
- } else {
585
- append_block(sm, "[/th]");
586
- }
587
- };
588
-
589
- '[/td]'i => {
590
- if (dstack_check(sm, BLOCK_TD)) {
591
- dstack_pop(sm);
592
- append_block(sm, "</td>");
593
- fret;
594
- } else {
595
- append_block(sm, "[/td]");
596
- }
597
- };
598
-
599
- '\0' => {
600
- g_debug("inline 0");
601
- g_debug(" return");
602
-
603
- fhold;
604
- fret;
605
- };
606
-
607
- newline{2,} => {
608
- g_debug("inline newline2");
609
- g_debug(" return");
610
-
611
- if (sm->list_mode) {
612
- dstack_close_list(sm);
613
- }
614
-
615
- fexec sm->ts;
616
- fret;
617
- };
618
-
619
- newline => {
620
- g_debug("inline newline");
621
-
622
- if (sm->header_mode) {
623
- sm->header_mode = false;
624
- dstack_rewind(sm);
625
- fret;
626
- } else {
627
- append(sm, true, "<br>");
628
- }
629
- };
630
-
631
- '\r' => {
632
- append_c(sm, ' ');
633
- };
634
-
635
- any => {
636
- g_debug("inline char: %c", fc);
637
- append_c_html_escaped(sm, fc);
638
- };
639
- *|;
640
-
641
- code := |*
642
- '[/code]'i => {
643
- if (dstack_check(sm, BLOCK_CODE)) {
644
- dstack_rewind(sm);
645
- } else {
646
- append(sm, true, "[/code]");
647
- }
648
- fret;
649
- };
650
-
651
- '\0' => {
652
- fhold;
653
- fret;
654
- };
655
-
656
- any => {
657
- append_c_html_escaped(sm, fc);
658
- };
659
- *|;
660
-
661
- nodtext := |*
662
- '[/nodtext]'i => {
663
- if (dstack_check2(sm, BLOCK_NODTEXT)) {
664
- g_debug("block dstack check");
665
- dstack_pop(sm);
666
- dstack_pop(sm);
667
- append_block(sm, "</p>");
668
- fret;
669
- } else if (dstack_check(sm, INLINE_NODTEXT)) {
670
- g_debug("inline dstack check");
671
- dstack_pop(sm);
672
- fret;
673
- } else {
674
- g_debug("else dstack check");
675
- append(sm, true, "[/nodtext]");
676
- }
677
- };
678
-
679
- '\0' => {
680
- fhold;
681
- fret;
682
- };
683
-
684
- any => {
685
- append_c_html_escaped(sm, fc);
686
- };
687
- *|;
688
-
689
- table := |*
690
- '[thead]'i => {
691
- dstack_push(sm, &BLOCK_THEAD);
692
- append_block(sm, "<thead>");
693
- };
694
-
695
- '[/thead]'i => {
696
- if (dstack_check(sm, BLOCK_THEAD)) {
697
- dstack_pop(sm);
698
- append_block(sm, "</thead>");
699
- } else {
700
- append(sm, true, "[/thead]");
701
- }
702
- };
703
-
704
- '[tbody]'i => {
705
- dstack_push(sm, &BLOCK_TBODY);
706
- append_block(sm, "<tbody>");
707
- };
708
-
709
- '[/tbody]'i => {
710
- if (dstack_check(sm, BLOCK_TBODY)) {
711
- dstack_pop(sm);
712
- append_block(sm, "</tbody>");
713
- } else {
714
- append(sm, true, "[/tbody]");
715
- }
716
- };
717
-
718
- '[th]'i => {
719
- dstack_push(sm, &BLOCK_TH);
720
- append_block(sm, "<th>");
721
- fcall inline;
722
- };
723
-
724
- '[tr]'i => {
725
- dstack_push(sm, &BLOCK_TR);
726
- append_block(sm, "<tr>");
727
- };
728
-
729
- '[/tr]'i => {
730
- if (dstack_check(sm, BLOCK_TR)) {
731
- dstack_pop(sm);
732
- append_block(sm, "</tr>");
733
- } else {
734
- append(sm, true, "[/tr]");
735
- }
736
- };
737
-
738
- '[td]'i => {
739
- dstack_push(sm, &BLOCK_TD);
740
- append_block(sm, "<td>");
741
- fcall inline;
742
- };
743
-
744
- '[/table]'i => {
745
- if (dstack_check(sm, BLOCK_TABLE)) {
746
- dstack_pop(sm);
747
- append_block(sm, "</table>");
748
- fret;
749
- } else {
750
- append(sm, true, "[/table]");
751
- }
752
- };
753
-
754
- '\0' => {
755
- fhold;
756
- fret;
757
- };
758
-
759
- any;
760
- *|;
761
-
762
- list := |*
763
- list_item => {
764
- int prev_nest = sm->list_nest;
765
- append_closing_p_if(sm);
766
- g_debug("list start");
767
- sm->list_mode = true;
768
- sm->list_nest = sm->a2 - sm->a1;
769
- fexec sm->b1;
770
-
771
- if (sm->list_nest > prev_nest) {
772
- int i=0;
773
- for (i=prev_nest; i<sm->list_nest; ++i) {
774
- g_debug(" dstack push ul");
775
- g_debug(" print <ul>");
776
- append_block(sm, "<ul>");
777
- dstack_push(sm, &BLOCK_UL);
778
- }
779
- } else if (sm->list_nest < prev_nest) {
780
- int i=0;
781
- for (i=sm->list_nest; i<prev_nest; ++i) {
782
- if (dstack_check(sm, BLOCK_UL)) {
783
- g_debug(" dstack pop");
784
- g_debug(" print </ul>");
785
- dstack_pop(sm);
786
- append_block(sm, "</ul>");
787
- }
788
- }
789
- }
790
-
791
- append_block(sm, "<li>");
792
- dstack_push(sm, &BLOCK_LI);
793
-
794
- g_debug(" print <li>");
795
- g_debug(" push li");
796
- g_debug(" call inline");
797
-
798
- fcall inline;
799
- };
800
-
801
- # exit list
802
- (newline{2,} | '\0') => {
803
- dstack_close_list(sm);
804
- fexec sm->ts;
805
- fret;
806
- };
807
-
808
- newline;
809
-
810
- any => {
811
- dstack_rewind(sm);
812
- fhold;
813
- fret;
814
- };
815
- *|;
816
-
817
- main := |*
818
- header_with_id => {
819
- char header = *sm->a1;
820
- GString * id_name = g_string_new_len(sm->b1, sm->b2 - sm->b1);
821
- id_name = g_string_prepend(id_name, "dtext-");
822
-
823
- if (sm->f_inline) {
824
- header = '6';
825
- }
826
-
827
- if (!sm->f_strip) {
828
- switch (header) {
829
- case '1':
830
- dstack_push(sm, &BLOCK_H1);
831
- append_block(sm, "<h1 id=\"");
832
- append_block(sm, id_name->str);
833
- append_block(sm, "\">");
834
- break;
835
-
836
- case '2':
837
- dstack_push(sm, &BLOCK_H2);
838
- append_block(sm, "<h2 id=\"");
839
- append_block(sm, id_name->str);
840
- append_block(sm, "\">");
841
- break;
842
-
843
- case '3':
844
- dstack_push(sm, &BLOCK_H3);
845
- append_block(sm, "<h3 id=\"");
846
- append_block(sm, id_name->str);
847
- append_block(sm, "\">");
848
- break;
849
-
850
- case '4':
851
- dstack_push(sm, &BLOCK_H4);
852
- append_block(sm, "<h4 id=\"");
853
- append_block(sm, id_name->str);
854
- append_block(sm, "\">");
855
- break;
856
-
857
- case '5':
858
- dstack_push(sm, &BLOCK_H5);
859
- append_block(sm, "<h5 id=\"");
860
- append_block(sm, id_name->str);
861
- append_block(sm, "\">");
862
- break;
863
-
864
- case '6':
865
- dstack_push(sm, &BLOCK_H6);
866
- append_block(sm, "<h6 id=\"");
867
- append_block(sm, id_name->str);
868
- append_block(sm, "\">");
869
- break;
870
- }
871
- }
872
-
873
- sm->header_mode = true;
874
- g_string_free(id_name, false);
875
- id_name = NULL;
876
- fcall inline;
877
- };
878
-
879
- header => {
880
- char header = *sm->a1;
881
-
882
- if (sm->f_inline) {
883
- header = '6';
884
- }
885
-
886
- if (!sm->f_strip) {
887
- switch (header) {
888
- case '1':
889
- dstack_push(sm, &BLOCK_H1);
890
- append_block(sm, "<h1>");
891
- break;
892
-
893
- case '2':
894
- dstack_push(sm, &BLOCK_H2);
895
- append_block(sm, "<h2>");
896
- break;
897
-
898
- case '3':
899
- dstack_push(sm, &BLOCK_H3);
900
- append_block(sm, "<h3>");
901
- break;
902
-
903
- case '4':
904
- dstack_push(sm, &BLOCK_H4);
905
- append_block(sm, "<h4>");
906
- break;
907
-
908
- case '5':
909
- dstack_push(sm, &BLOCK_H5);
910
- append_block(sm, "<h5>");
911
- break;
912
-
913
- case '6':
914
- dstack_push(sm, &BLOCK_H6);
915
- append_block(sm, "<h6>");
916
- break;
917
- }
918
- }
919
-
920
- sm->header_mode = true;
921
- fcall inline;
922
- };
923
-
924
- '[quote]'i space* => {
925
- g_debug("block [quote]");
926
- g_debug(" push quote");
927
- g_debug(" print <blockquote>");
928
- dstack_close_before_block(sm);
929
- dstack_push(sm, &BLOCK_QUOTE);
930
- append_block(sm, "<blockquote>");
931
- };
932
-
933
- spoilers_open space* => {
934
- g_debug("block [spoiler]");
935
- g_debug(" push spoiler");
936
- g_debug(" print <div>");
937
- dstack_close_before_block(sm);
938
- dstack_push(sm, &BLOCK_SPOILER);
939
- append_block(sm, "<div class=\"spoiler\">");
940
- };
941
-
942
- spoilers_close => {
943
- g_debug("block [/spoiler]");
944
- dstack_close_before_block(sm);
945
- if (dstack_check(sm, BLOCK_SPOILER)) {
946
- g_debug(" rewind");
947
- dstack_rewind(sm);
948
- }
949
- };
950
-
951
- '[code]'i space* => {
952
- g_debug("block [code]");
953
- dstack_close_before_block(sm);
954
- dstack_push(sm, &BLOCK_CODE);
955
- append_block(sm, "<pre>");
956
- fcall code;
957
- };
958
-
959
- '[expand]'i space* => {
960
- g_debug("block [expand]");
961
- dstack_close_before_block(sm);
962
- dstack_push(sm, &BLOCK_EXPAND);
963
- append_block(sm, "<div class=\"expandable\"><div class=\"expandable-header\">");
964
- append_block(sm, "<input type=\"button\" value=\"Show\" class=\"expandable-button\"/></div>");
965
- append_block(sm, "<div class=\"expandable-content\">");
966
- };
967
-
968
- aliased_expand space* => {
969
- g_debug("block [expand=]");
970
- dstack_close_before_block(sm);
971
- dstack_push(sm, &BLOCK_EXPAND);
972
- append_block(sm, "<div class=\"expandable\"><div class=\"expandable-header\">");
973
- append(sm, true, "<span>");
974
- append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
975
- append(sm, true, "</span>");
976
- append_block(sm, "<input type=\"button\" value=\"Show\" class=\"expandable-button\"/></div>");
977
- append_block(sm, "<div class=\"expandable-content\">");
978
- };
979
-
980
- '[nodtext]'i space* => {
981
- g_debug("block [nodtext]");
982
- dstack_close_before_block(sm);
983
- dstack_push(sm, &BLOCK_NODTEXT);
984
- dstack_push(sm, &BLOCK_P);
985
- g_debug("push block nodtext");
986
- g_debug("push block p");
987
- append_block(sm, "<p>");
988
- fcall nodtext;
989
- };
990
-
991
- '[table]'i => {
992
- dstack_close_before_block(sm);
993
- dstack_push(sm, &BLOCK_TABLE);
994
- append_block(sm, "<table class=\"striped\">");
995
- fcall table;
996
- };
997
-
998
- '[tn]'i => {
999
- dstack_push(sm, &BLOCK_TN);
1000
- append_block(sm, "<p class=\"tn\">");
1001
- fcall inline;
1002
- };
1003
-
1004
- list_item => {
1005
- g_debug("block list");
1006
- g_debug(" call list");
1007
- sm->list_nest = 0;
1008
- sm->list_mode = true;
1009
- append_closing_p_if(sm);
1010
- fexec sm->ts;
1011
- fcall list;
1012
- };
1013
-
1014
- '\0' => {
1015
- g_debug("block 0");
1016
- g_debug(" close dstack");
1017
- dstack_close(sm);
1018
- };
1019
-
1020
- newline{2,} => {
1021
- g_debug("block newline2");
1022
-
1023
- if (sm->header_mode) {
1024
- sm->header_mode = false;
1025
- dstack_rewind(sm);
1026
- } else if (sm->list_mode) {
1027
- dstack_close_list(sm);
1028
- } else {
1029
- dstack_close_before_block(sm);
1030
- }
1031
- };
1032
-
1033
- newline => {
1034
- g_debug("block newline");
1035
- };
1036
-
1037
- any => {
1038
- g_debug("block char: %c", fc);
1039
- fhold;
1040
-
1041
- if (g_queue_is_empty(sm->dstack) || dstack_check(sm, BLOCK_QUOTE) || dstack_check(sm, BLOCK_SPOILER) || dstack_check(sm, BLOCK_EXPAND)) {
1042
- g_debug(" push p");
1043
- g_debug(" print <p>");
1044
- dstack_push(sm, &BLOCK_P);
1045
- append_block(sm, "<p>");
1046
- }
1047
-
1048
- fcall inline;
1049
- };
1050
- *|;
1051
-
1052
- }%%
1053
-
1054
- %% write data;
1055
-
1056
- static inline void underscore_string(char * str, size_t len) {
1057
- for (size_t i=0; i<len; ++i) {
1058
- if (str[i] == ' ') {
1059
- str[i] = '_';
1060
- }
1061
- }
1062
- }
1063
-
1064
- static inline void dstack_push(StateMachine * sm, const int * element) {
1065
- g_queue_push_tail(sm->dstack, (gpointer)element);
1066
- }
1067
-
1068
- static inline int * dstack_pop(StateMachine * sm) {
1069
- return g_queue_pop_tail(sm->dstack);
1070
- }
1071
-
1072
- static inline int * dstack_peek(StateMachine * sm) {
1073
- return g_queue_peek_tail(sm->dstack);
1074
- }
1075
-
1076
- static inline bool dstack_search(StateMachine * sm, const int * element) {
1077
- return g_queue_find(sm->dstack, (gconstpointer)element);
1078
- }
1079
-
1080
- static inline bool dstack_check(StateMachine * sm, int expected_element) {
1081
- int * top = dstack_peek(sm);
1082
- return top && *top == expected_element;
1083
- }
1084
-
1085
- static inline bool dstack_check2(StateMachine * sm, int expected_element) {
1086
- int * top2 = NULL;
1087
-
1088
- if (sm->dstack->length < 2) {
1089
- return false;
1090
- }
1091
-
1092
- top2 = g_queue_peek_nth(sm->dstack, sm->dstack->length - 2);
1093
- return top2 && *top2 == expected_element;
1094
- }
1095
-
1096
- static inline void append(StateMachine * sm, bool is_markup, const char * s) {
1097
- if (!(is_markup && sm->f_strip)) {
1098
- sm->output = g_string_append(sm->output, s);
1099
- }
1100
- }
1101
-
1102
- static inline void append_c(StateMachine * sm, char s) {
1103
- sm->output = g_string_append_c(sm->output, s);
1104
- }
1105
-
1106
- static inline void append_c_html_escaped(StateMachine * sm, char s) {
1107
- switch (s) {
1108
- case '<':
1109
- sm->output = g_string_append(sm->output, "&lt;");
1110
- break;
1111
-
1112
- case '>':
1113
- sm->output = g_string_append(sm->output, "&gt;");
1114
- break;
1115
-
1116
- case '&':
1117
- sm->output = g_string_append(sm->output, "&amp;");
1118
- break;
1119
-
1120
- case '"':
1121
- sm->output = g_string_append(sm->output, "&quot;");
1122
- break;
1123
-
1124
- default:
1125
- sm->output = g_string_append_c(sm->output, s);
1126
- break;
1127
- }
1128
- }
1129
-
1130
- static inline void append_segment(StateMachine * sm, bool is_markup, const char * a, const char * b) {
1131
- if (!(is_markup && sm->f_strip)) {
1132
- sm->output = g_string_append_len(sm->output, a, b - a + 1);
1133
- }
1134
- }
1135
-
1136
- static inline void append_segment_uri_escaped(StateMachine * sm, const char * a, const char * b) {
1137
- if (sm->f_strip) {
1138
- return;
1139
- }
1140
-
1141
- char * segment1 = NULL;
1142
- char * segment2 = NULL;
1143
- GString * segment_string = g_string_new_len(a, b - a + 1);
1144
-
1145
- segment1 = g_uri_escape_string(segment_string->str, NULL, TRUE);
1146
- segment2 = g_markup_escape_text(segment1, -1);
1147
- sm->output = g_string_append(sm->output, segment2);
1148
- g_string_free(segment_string, TRUE);
1149
- g_free(segment1);
1150
- g_free(segment2);
1151
- }
1152
-
1153
- static inline void append_segment_html_escaped(StateMachine * sm, const char * a, const char * b) {
1154
- gchar * segment = g_markup_escape_text(a, b - a + 1);
1155
- sm->output = g_string_append(sm->output, segment);
1156
- g_free(segment);
1157
- }
1158
-
1159
- static inline void append_block(StateMachine * sm, const char * s) {
1160
- if (sm->f_inline) {
1161
- // sm->output = g_string_append_c(sm->output, ' ');
1162
- } else if (sm->f_strip) {
1163
- // do nothing
1164
- } else {
1165
- sm->output = g_string_append(sm->output, s);
1166
- }
1167
- }
1168
-
1169
- static void append_closing_p(StateMachine * sm) {
1170
- size_t i = sm->output->len;
1171
-
1172
- if (i > 4 && !strncmp(sm->output->str + i - 4, "<br>", 4)) {
1173
- sm->output = g_string_truncate(sm->output, sm->output->len - 4);
1174
- }
1175
-
1176
- if (i > 3 && !strncmp(sm->output->str + i - 3, "<p>", 3)) {
1177
- sm->output = g_string_truncate(sm->output, sm->output->len - 3);
1178
- return;
1179
- }
1180
-
1181
- append_block(sm, "</p>");
1182
- }
1183
-
1184
- static void append_closing_p_if(StateMachine * sm) {
1185
- if (!dstack_check(sm, BLOCK_P)) {
1186
- return;
1187
- }
1188
-
1189
- dstack_pop(sm);
1190
- append_closing_p(sm);
1191
- }
1192
-
1193
- static void dstack_rewind(StateMachine * sm) {
1194
- int * element = dstack_pop(sm);
1195
-
1196
- if (element == NULL) {
1197
- return;
1198
- }
1199
-
1200
- if (*element == BLOCK_P) {
1201
- append_closing_p(sm);
1202
-
1203
- } else if (*element == INLINE_SPOILER) {
1204
- append(sm, true, "</span>");
1205
-
1206
- } else if (*element == BLOCK_SPOILER) {
1207
- append_block(sm, "</div>");
1208
-
1209
- } else if (*element == BLOCK_QUOTE) {
1210
- append_block(sm, "</blockquote>");
1211
-
1212
- } else if (*element == BLOCK_EXPAND) {
1213
- append_block(sm, "</div></div>");
1214
-
1215
- } else if (*element == BLOCK_NODTEXT) {
1216
- append_closing_p(sm);
1217
-
1218
- } else if (*element == BLOCK_CODE) {
1219
- append_block(sm, "</pre>");
1220
-
1221
- } else if (*element == BLOCK_TD) {
1222
- append_block(sm, "</td>");
1223
-
1224
- } else if (*element == INLINE_NODTEXT) {
1225
-
1226
- } else if (*element == INLINE_B) {
1227
- append(sm, true, "</strong>");
1228
-
1229
- } else if (*element == INLINE_I) {
1230
- append(sm, true, "</em>");
1231
-
1232
- } else if (*element == INLINE_U) {
1233
- append(sm, true, "</u>");
1234
-
1235
- } else if (*element == INLINE_S) {
1236
- append(sm, true, "</s>");
1237
-
1238
- } else if (*element == INLINE_TN) {
1239
- append(sm, true, "</span>");
1240
-
1241
- } else if (*element == BLOCK_TN) {
1242
- append_closing_p(sm);
1243
-
1244
- } else if (*element == BLOCK_TABLE) {
1245
- append_block(sm, "</table>");
1246
-
1247
- } else if (*element == BLOCK_THEAD) {
1248
- append_block(sm, "</thead>");
1249
-
1250
- } else if (*element == BLOCK_TBODY) {
1251
- append_block(sm, "</tbody>");
1252
-
1253
- } else if (*element == BLOCK_TR) {
1254
- append_block(sm, "</tr>");
1255
-
1256
- } else if (*element == BLOCK_UL) {
1257
- append_block(sm, "</ul>");
1258
-
1259
- } else if (*element == BLOCK_LI) {
1260
- append_block(sm, "</li>");
1261
-
1262
- } else if (*element == BLOCK_H6) {
1263
- append_block(sm, "</h6>");
1264
-
1265
- } else if (*element == BLOCK_H5) {
1266
- append_block(sm, "</h5>");
1267
-
1268
- } else if (*element == BLOCK_H4) {
1269
- append_block(sm, "</h4>");
1270
-
1271
- } else if (*element == BLOCK_H3) {
1272
- append_block(sm, "</h3>");
1273
-
1274
- } else if (*element == BLOCK_H2) {
1275
- append_block(sm, "</h2>");
1276
-
1277
- } else if (*element == BLOCK_H1) {
1278
- append_block(sm, "</h1>");
1279
- }
1280
- }
1281
-
1282
- static void dstack_close_before_block(StateMachine * sm) {
1283
- while (1) {
1284
- if (dstack_check(sm, BLOCK_P)) {
1285
- dstack_pop(sm);
1286
- append_closing_p(sm);
1287
- } else if (dstack_check(sm, BLOCK_LI) || dstack_check(sm, BLOCK_UL)) {
1288
- dstack_rewind(sm);
1289
- } else {
1290
- return;
1291
- }
1292
- }
1293
- }
1294
-
1295
- static void dstack_close(StateMachine * sm) {
1296
- while (dstack_peek(sm) != NULL) {
1297
- dstack_rewind(sm);
1298
- }
1299
- }
1300
-
1301
- static void dstack_close_list(StateMachine * sm) {
1302
- while (dstack_check(sm, BLOCK_LI) || dstack_check(sm, BLOCK_UL)) {
1303
- dstack_rewind(sm);
1304
- }
1305
-
1306
- sm->list_mode = false;
1307
- sm->list_nest = 0;
1308
- }
1309
-
1310
- static inline bool is_boundary_c(char c) {
1311
- switch (c) {
1312
- case ':':
1313
- case ';':
1314
- case '.':
1315
- case ',':
1316
- case '!':
1317
- case '?':
1318
- case ')':
1319
- case ']':
1320
- case '<':
1321
- case '>':
1322
- return true;
1323
- }
1324
-
1325
- return false;
1326
- }
1327
-
1328
- static bool print_machine(StateMachine * sm) {
1329
- printf("p=%c\n", *sm->p);
1330
- return true;
1331
- }
1332
-
1333
- static void init_machine(StateMachine * sm, const char * src, size_t len) {
1334
- size_t output_length = 0;
1335
- sm->p = src;
1336
- sm->pb = sm->p;
1337
- sm->pe = sm->p + len;
1338
- sm->eof = sm->pe;
1339
- sm->ts = NULL;
1340
- sm->te = NULL;
1341
- sm->cs = 0;
1342
- sm->act = 0;
1343
- sm->top = 0;
1344
- output_length = len;
1345
- if (output_length < (INT16_MAX / 2)) {
1346
- output_length *= 2;
1347
- }
1348
- sm->output = g_string_sized_new(output_length);
1349
- sm->a1 = NULL;
1350
- sm->a2 = NULL;
1351
- sm->b1 = NULL;
1352
- sm->b2 = NULL;
1353
- sm->f_inline = false;
1354
- sm->f_strip = false;
1355
- sm->f_mentions = true;
1356
- sm->stack = g_array_sized_new(FALSE, TRUE, sizeof(int), 16);
1357
- sm->dstack = g_queue_new();
1358
- sm->list_nest = 0;
1359
- sm->list_mode = false;
1360
- sm->header_mode = false;
1361
- sm->d = 0;
1362
- sm->b = 0;
1363
- sm->quote = 0;
1364
- }
1365
-
1366
- static void free_machine(StateMachine * sm) {
1367
- g_string_free(sm->output, TRUE);
1368
- g_array_free(sm->stack, FALSE);
1369
- g_queue_free(sm->dstack);
1370
- g_free(sm);
1371
- }
1372
-
1373
- static StateMachine * parse_helper(const char * src, size_t len, bool f_strip, bool f_inline, bool f_mentions) {
1374
- StateMachine * sm = NULL;
1375
- StateMachine * link_content_sm = NULL;
1376
-
1377
- sm = (StateMachine *)g_malloc0(sizeof(StateMachine));
1378
- init_machine(sm, src, len);
1379
- sm->f_strip = f_strip;
1380
- sm->f_inline = f_inline;
1381
- sm->f_mentions = f_mentions;
1382
-
1383
- %% write init;
1384
- %% write exec;
1385
-
1386
- dstack_close(sm);
1387
-
1388
- return sm;
1389
- }
1390
-
1391
- static VALUE parse(int argc, VALUE * argv, VALUE self) {
1392
- VALUE input;
1393
- VALUE input0;
1394
- VALUE options;
1395
- VALUE opt_inline;
1396
- VALUE opt_strip;
1397
- VALUE opt_mentions;
1398
- VALUE ret;
1399
- rb_encoding * encoding = NULL;
1400
- StateMachine * sm = NULL;
1401
- bool f_strip = false;
1402
- bool f_inline = false;
1403
- bool f_mentions = true;
1404
-
1405
- g_debug("start\n");
1406
-
1407
- if (argc == 0) {
1408
- rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
1409
- }
1410
-
1411
- input = argv[0];
1412
-
1413
- if (NIL_P(input)) {
1414
- return Qnil;
1415
- }
1416
-
1417
- input0 = rb_str_dup(input);
1418
- input0 = rb_str_cat(input0, "\0", 1);
1419
-
1420
- if (argc > 1) {
1421
- options = argv[1];
1422
-
1423
- if (!NIL_P(options)) {
1424
- opt_strip = rb_hash_aref(options, ID2SYM(rb_intern("strip")));
1425
- if (RTEST(opt_strip)) {
1426
- f_strip = true;
1427
- }
1428
-
1429
- opt_inline = rb_hash_aref(options, ID2SYM(rb_intern("inline")));
1430
- if (RTEST(opt_inline)) {
1431
- f_inline = true;
1432
- }
1433
-
1434
- opt_mentions = rb_hash_aref(options, ID2SYM(rb_intern("disable_mentions")));
1435
- if (RTEST(opt_mentions)) {
1436
- f_mentions = false;
1437
- }
1438
- }
1439
- }
1440
-
1441
- sm = parse_helper(RSTRING_PTR(input0), RSTRING_LEN(input0), f_strip, f_inline, f_mentions);
1442
-
1443
- encoding = rb_enc_find("utf-8");
1444
- ret = rb_enc_str_new(sm->output->str, sm->output->len, encoding);
1445
-
1446
- free_machine(sm);
1447
-
1448
- return ret;
1449
- }
1450
-
1451
- void Init_dtext() {
1452
- VALUE mDTextRagel = rb_define_module("DTextRagel");
1453
- rb_define_singleton_method(mDTextRagel, "parse", parse, -1);
1454
- }