hive_markup 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2b5de6cfd829708c16d638eaad678d63e5ba173d
4
+ data.tar.gz: b4dad87f58e68df2d1d30dbf06a8073d61b23665
5
+ SHA512:
6
+ metadata.gz: c65ff215346e34525b5c79fd902b1ddfccb443299eceecab9015c5f65aff2cdefb0799934af0d4835fabc3766cbfc86f71b9111854ae3b832aec94b8eb1d5dcc
7
+ data.tar.gz: 2511dc20b3e43a2c5028dbf9690ccf29d5804ece4173b0007262ed4fff619458b64eb58e0838b30ee0d97eb572e7af85b69ded8ce5a6af232209972f23bf3d56
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile('hive_markup')
@@ -0,0 +1,719 @@
1
+ #define RSTRING_NOT_MODIFIED
2
+
3
+ #include <ruby/ruby.h>
4
+ #include <ruby/encoding.h>
5
+ #include <ctype.h>
6
+
7
+ #include "houdini.h"
8
+
9
+ #define MIN_BUF_SIZE 128
10
+ #define MAX_BUF_SIZE 2 * 1024 * 1024
11
+ #define buf_puts(buf, str) buf_append(buf, str, sizeof str - 1)
12
+
13
+ static VALUE rb_mHive;
14
+ static VALUE rb_cMarkup;
15
+
16
+ typedef struct {
17
+ uint8_t *data;
18
+ size_t size;
19
+ size_t total;
20
+ uint8_t fragile;
21
+ } buffer;
22
+
23
+ static size_t parse_text(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
24
+ static size_t parse_em(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
25
+ static size_t parse_maybequote(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
26
+ static size_t parse_quote(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
27
+ static size_t parse_quotelink(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
28
+ static size_t parse_linebreak(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
29
+ static size_t parse_codeblock(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
30
+ static size_t parse_aablock(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
31
+ static size_t parse_spoiler(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
32
+ static size_t parse_escape(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
33
+ static size_t parse_autolink(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
34
+
35
+ typedef size_t (*trigger_func)(const uint8_t *text, size_t start, size_t size, buffer *out_buf);
36
+
37
+ static char trigger_map[256];
38
+
39
+ enum trigger_keys {
40
+ HIVE_NULL = 0,
41
+ HIVE_EM,
42
+ HIVE_QUOTE,
43
+ HIVE_LINEBREAK,
44
+ HIVE_CODE,
45
+ HIVE_SPOILER,
46
+ HIVE_ESCAPE,
47
+ HIVE_AA,
48
+ HIVE_AUTOLINK
49
+ };
50
+
51
+ static trigger_func trigger_funcs[] = {
52
+ 0,
53
+ parse_em,
54
+ parse_maybequote,
55
+ parse_linebreak,
56
+ parse_codeblock,
57
+ parse_spoiler,
58
+ parse_escape,
59
+ parse_aablock,
60
+ parse_autolink
61
+ };
62
+
63
+ static void init_triggers() {
64
+ trigger_map['*'] = HIVE_EM;
65
+ trigger_map['>'] = HIVE_QUOTE;
66
+ trigger_map['\n'] = HIVE_LINEBREAK;
67
+ trigger_map['`'] = HIVE_CODE;
68
+ trigger_map['$'] = HIVE_SPOILER;
69
+ trigger_map['\\'] = HIVE_ESCAPE;
70
+ trigger_map['~'] = HIVE_AA;
71
+ trigger_map['/'] = HIVE_AUTOLINK;
72
+ }
73
+
74
+ static buffer * buf_new() {
75
+ buffer *buf;
76
+
77
+ buf = malloc(sizeof (buffer));
78
+
79
+ if (buf) {
80
+ buf->data = 0;
81
+ buf->size = 0;
82
+ buf->total = 0;
83
+ buf->fragile = 0;
84
+ }
85
+
86
+ return buf;
87
+ }
88
+
89
+ static int buf_expand(buffer *buf, size_t new_size) {
90
+ void *new_ptr;
91
+
92
+ new_size = MIN_BUF_SIZE + new_size + (new_size >> 1);
93
+
94
+ if (new_size > MAX_BUF_SIZE) {
95
+ return 0;
96
+ }
97
+
98
+ new_ptr = realloc(buf->data, new_size);
99
+
100
+ if (new_ptr) {
101
+ buf->data = new_ptr;
102
+ buf->total = new_size;
103
+ return 1;
104
+ }
105
+
106
+ return 0;
107
+ }
108
+
109
+ static void buf_append(buffer *buf, const void *str, size_t size) {
110
+ if (buf->size + size > buf->total && !buf_expand(buf, buf->size + size)) {
111
+ return;
112
+ }
113
+
114
+ memcpy(buf->data + buf->size, str, size);
115
+ buf->size += size;
116
+ }
117
+
118
+ static void buf_putc(buffer *buf, uint8_t c) {
119
+ if (buf->size >= buf->total && !buf_expand(buf, buf->size + 1)) {
120
+ return;
121
+ }
122
+
123
+ buf->data[buf->size] = c;
124
+ ++buf->size;
125
+ }
126
+
127
+ static void buf_free(buffer *buf) {
128
+ free(buf->data);
129
+ free(buf);
130
+ }
131
+
132
+ static inline int is_space(uint8_t c) {
133
+ return c == ' ' || c == '\n';
134
+ }
135
+
136
+ static inline int is_alnum(uint8_t c) {
137
+ return isalnum(c) && c < 0x7b;
138
+ }
139
+
140
+ static inline int is_alpha(uint8_t c) {
141
+ return isalpha(c) && c < 0x7b;
142
+ }
143
+
144
+ static inline int is_digit(uint8_t c) {
145
+ return c >= '0' && c <= '9';
146
+ }
147
+
148
+ static inline int is_xdigit(uint8_t c) {
149
+ return is_digit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
150
+ }
151
+
152
+ static void preprocess_text(const uint8_t *text, size_t size, buffer *out_buf) {
153
+ size_t end = 0;
154
+
155
+ while (end < size) {
156
+ size_t from = end;
157
+
158
+ while (end < size && text[end] > 31 && text[end] != 127) {
159
+ ++end;
160
+ }
161
+
162
+ if (end > from) {
163
+ buf_append(out_buf, text + from, end - from);
164
+ }
165
+
166
+ if (end >= size) {
167
+ break;
168
+ }
169
+
170
+ if (text[end] == '\n') {
171
+ buf_putc(out_buf, '\n');
172
+ }
173
+ else if (text[end] == '\t') {
174
+ buf_putc(out_buf, ' ');
175
+ buf_putc(out_buf, ' ');
176
+ }
177
+
178
+ ++end;
179
+ }
180
+ }
181
+
182
+ static void escape_html_char(uint8_t c, buffer *out_buf) {
183
+ uint8_t esc;
184
+
185
+ if ((esc = HTML_ESCAPE_TABLE[c]) != 0) {
186
+ buf_append(out_buf, HTML_ESCAPES[esc], HTML_ESCAPES_LEN[esc]);
187
+ }
188
+ else {
189
+ buf_putc(out_buf, c);
190
+ }
191
+ }
192
+
193
+ static size_t escape_html(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
194
+ uint8_t esc = 0;
195
+ size_t end = start;
196
+
197
+ while (end < size) {
198
+ size_t from = end;
199
+
200
+ while (end < size && (esc = HTML_ESCAPE_TABLE[text[end]]) == 0) {
201
+ ++end;
202
+ }
203
+
204
+ if (end > from) {
205
+ buf_append(out_buf, text + from, end - from);
206
+ }
207
+
208
+ if (end >= size) {
209
+ break;
210
+ }
211
+
212
+ buf_append(out_buf, HTML_ESCAPES[esc], HTML_ESCAPES_LEN[esc]);
213
+
214
+ ++end;
215
+ }
216
+
217
+ return end - start;
218
+ }
219
+
220
+ static size_t parse_aablock(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
221
+ if (out_buf->fragile) {
222
+ return 0;
223
+ }
224
+
225
+ if (start > 0 && text[start - 1] != '\n') {
226
+ return 0;
227
+ }
228
+
229
+ if (start + 2 >= size || text[start + 1] != '~' || text[start + 2] != '~') {
230
+ return 0;
231
+ }
232
+
233
+ size_t end = start + 3;
234
+
235
+ while (end < size && text[end] == '\n') {
236
+ ++end;
237
+ }
238
+
239
+ if (end >= size) {
240
+ return 0;
241
+ }
242
+
243
+ size_t i, block_start = end;
244
+
245
+ for (i = 0; end < size; ++end) {
246
+ if (text[end] != '~' || text[end - 1] == '\\') {
247
+ i = 0;
248
+ }
249
+ else {
250
+ ++i;
251
+ }
252
+ if (i == 3 && text[end - 3] == '\n' && (end + 1 >= size || text[end + 1] == '\n')) {
253
+ break;
254
+ }
255
+ }
256
+
257
+ if (i < 3) {
258
+ return 0;
259
+ }
260
+
261
+ size_t block_end = end - 2;
262
+
263
+ while (block_end > block_start && text[block_end - 1] == '\n') {
264
+ block_end--;
265
+ }
266
+
267
+ if (block_end <= block_start) {
268
+ return 0;
269
+ }
270
+
271
+ buf_puts(out_buf, "<div class=\"aa\">");
272
+
273
+ escape_html(text, block_start, block_end, out_buf);
274
+
275
+ buf_puts(out_buf, "</div>");
276
+
277
+ if (end + 1 < size) {
278
+ ++end;
279
+ }
280
+
281
+ return end - start + 1;
282
+ }
283
+
284
+ static size_t parse_codeblock(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
285
+ if (out_buf->fragile) {
286
+ return 0;
287
+ }
288
+
289
+ if (start > 0 && text[start - 1] != '\n') {
290
+ return 0;
291
+ }
292
+
293
+ if (start + 2 >= size || text[start + 1] != '`' || text[start + 2] != '`') {
294
+ return 0;
295
+ }
296
+
297
+ size_t end = start + 3;
298
+
299
+ while (end < size && text[end] == '\n') {
300
+ ++end;
301
+ }
302
+
303
+ if (end >= size) {
304
+ return 0;
305
+ }
306
+
307
+ size_t i, block_start = end;
308
+
309
+ for (i = 0; end < size; ++end) {
310
+ if (text[end] != '`' || text[end - 1] == '\\') {
311
+ i = 0;
312
+ }
313
+ else {
314
+ ++i;
315
+ }
316
+ if (i == 3 && text[end - 3] == '\n' && (end + 1 >= size || text[end + 1] == '\n')) {
317
+ break;
318
+ }
319
+ }
320
+
321
+ if (i < 3) {
322
+ return 0;
323
+ }
324
+
325
+ size_t block_end = end - 2;
326
+
327
+ while (block_end > block_start && text[block_end - 1] == '\n') {
328
+ block_end--;
329
+ }
330
+
331
+ if (block_end <= block_start) {
332
+ return 0;
333
+ }
334
+
335
+ buf_puts(out_buf, "<pre><code class=\"prettyprint\">");
336
+
337
+ escape_html(text, block_start, block_end, out_buf);
338
+
339
+ buf_puts(out_buf, "</code></pre>");
340
+
341
+ if (end + 1 < size) {
342
+ ++end;
343
+ }
344
+
345
+ return end - start + 1;
346
+ }
347
+
348
+ static size_t parse_spoiler(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
349
+ if (start > 0 && is_alnum(text[start - 1])) {
350
+ return 0;
351
+ }
352
+
353
+ size_t end = start + 1;
354
+
355
+ while (end < size && text[end] == '$') {
356
+ ++end;
357
+ }
358
+
359
+ if (end - start != 2) {
360
+ buf_append(out_buf, text + start, end - start); // $
361
+ return end - start;
362
+ }
363
+
364
+ while (end < size && text[end] == '\n') {
365
+ ++end;
366
+ }
367
+
368
+ if (end >= size) {
369
+ return 0;
370
+ }
371
+
372
+ size_t block_start = end;
373
+
374
+ while (end < size) {
375
+ if (text[end] == '$'
376
+ && end + 1 < size
377
+ && text[end + 1] == '$'
378
+ && (end + 1 >= size || !is_alnum(text[end + 1]))
379
+ ) {
380
+ break;
381
+ }
382
+ ++end;
383
+ }
384
+
385
+ if (end >= size) {
386
+ return 0;
387
+ }
388
+
389
+ size_t block_end = end;
390
+
391
+ while (block_end > block_start && text[block_end - 1] == '\n') {
392
+ block_end--;
393
+ }
394
+
395
+ if (block_end <= block_start) {
396
+ return 0;
397
+ }
398
+
399
+ out_buf->fragile = 1;
400
+
401
+ buf_puts(out_buf, "<span class=\"s\">");
402
+
403
+ parse_text(text, block_start, block_end, out_buf);
404
+
405
+ buf_puts(out_buf, "</span>");
406
+
407
+ out_buf->fragile = 0;
408
+
409
+ return end - start + 2;
410
+ }
411
+
412
+ static size_t parse_em(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
413
+ if (start > 0 && is_alnum(text[start - 1])) {
414
+ return 0;
415
+ }
416
+
417
+ size_t end = start + 1;
418
+
419
+ while (end < size && text[end] == '*') {
420
+ ++end;
421
+ }
422
+
423
+ if (end - start > 1) {
424
+ buf_append(out_buf, text + start, end - start); // *
425
+ return end - start;
426
+ }
427
+
428
+ if (end < size && is_space(text[end])) {
429
+ return 0;
430
+ }
431
+
432
+ while (end < size && text[end] != '\n') {
433
+ if (text[end] == '*' && !is_space(text[end - 1])
434
+ && (end + 1 >= size || !is_alnum(text[end + 1]))
435
+ && text[end - 1] != '\\') {
436
+ break;
437
+ }
438
+ ++end;
439
+ }
440
+
441
+ if (end >= size || text[end] == '\n') {
442
+ return 0;
443
+ }
444
+
445
+ if (is_space(text[end - 1])) {
446
+ return 0;
447
+ }
448
+
449
+ ++start;
450
+
451
+ buf_puts(out_buf, "<em>");
452
+
453
+ parse_text(text, start, end, out_buf);
454
+
455
+ buf_puts(out_buf, "</em>");
456
+
457
+ return end - start + 2;
458
+ }
459
+
460
+ static size_t parse_escape(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
461
+ if (start + 1 < size) {
462
+ uint8_t c = text[start + 1];
463
+ if (c == '*' || c == '`' || c == '$' || c == '~') {
464
+ escape_html_char(c, out_buf);
465
+ return 2;
466
+ }
467
+ }
468
+ return 0;
469
+ }
470
+
471
+ static size_t parse_autolink(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
472
+ static const char *autolink_scheme = "http";
473
+ static const char *punct = ":;!?,.'\"&";
474
+
475
+ if (start < 5 || start + 2 >= size || text[start - 1] != ':' || text[start + 1] != '/') {
476
+ return 0;
477
+ }
478
+
479
+ size_t block_start, scheme_len;
480
+
481
+ if (text[start - 2] != 's') {
482
+ scheme_len = 5;
483
+ }
484
+ else {
485
+ scheme_len = 6;
486
+ }
487
+
488
+ if (scheme_len > start) {
489
+ return 0;
490
+ }
491
+
492
+ block_start = start - scheme_len;
493
+
494
+ if (memcmp(&text[block_start], autolink_scheme, 4) != 0) {
495
+ return 0;
496
+ }
497
+
498
+ size_t block_end = start + 2;
499
+
500
+ while (block_end < size && !is_space(text[block_end])) {
501
+ ++block_end;
502
+ }
503
+
504
+ while (block_end > start) {
505
+ if (strchr(punct, text[block_end - 1]) == 0) {
506
+ break;
507
+ }
508
+ block_end--;
509
+ }
510
+
511
+ size_t i = block_end;
512
+
513
+ while (i > start && text[i - 1] == ')') {
514
+ i--;
515
+ }
516
+
517
+ if (i < block_end) {
518
+ block_end = i;
519
+ while (i > start) {
520
+ if (text[i] == '(') {
521
+ ++block_end;
522
+ break;
523
+ }
524
+ i--;
525
+ }
526
+ }
527
+
528
+ out_buf->size -= scheme_len;
529
+
530
+ buf_puts(out_buf, "<a href=\"");
531
+ escape_html(text, block_start, block_end, out_buf);
532
+ buf_puts(out_buf, "\">");
533
+ escape_html(text, block_start, block_end, out_buf);
534
+ buf_puts(out_buf, "</a>");
535
+
536
+ return block_end - start;
537
+ }
538
+
539
+ static size_t parse_linebreak(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
540
+ size_t count = 1;
541
+
542
+ buf_puts(out_buf, "<br>");
543
+
544
+ ++start;
545
+
546
+ while (start < size && text[start] == '\n') {
547
+ ++start;
548
+ ++count;
549
+ }
550
+
551
+ if (count > 1) {
552
+ buf_puts(out_buf, "<br>");
553
+ }
554
+
555
+ return count;
556
+ }
557
+
558
+ static size_t parse_maybequote(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
559
+ size_t count;
560
+
561
+ if (count = parse_quotelink(text, start, size, out_buf)) {
562
+ return count;
563
+ }
564
+
565
+ return parse_quote(text, start, size, out_buf);
566
+ }
567
+
568
+ static size_t parse_quotelink(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
569
+ if (start > 0 && is_alnum(text[start - 1])) {
570
+ return 0;
571
+ }
572
+
573
+ ++start;
574
+
575
+ if (start >= size || text[start] != '>') {
576
+ return 0;
577
+ }
578
+
579
+ ++start;
580
+
581
+ size_t end = start;
582
+ size_t count = end - start;
583
+
584
+ while (end < size && is_digit(text[end]) && count < 10) {
585
+ ++end;
586
+ ++count;
587
+ }
588
+
589
+ if (end == start || (end < size && is_alpha(text[end]))) {
590
+ return 0;
591
+ }
592
+
593
+ size_t i;
594
+ uint8_t num[count];
595
+
596
+ for (i = 0; i < count; ++i) {
597
+ num[i] = text[start + i];
598
+ }
599
+
600
+ buf_puts(out_buf, "<a class=\"ql\" href=\"#");
601
+ buf_append(out_buf, &num, count);
602
+ buf_puts(out_buf, "\">&gt;&gt;");
603
+ buf_append(out_buf, &num, count);
604
+ buf_puts(out_buf, "</a>");
605
+
606
+ return count + 2;
607
+ }
608
+
609
+ static size_t parse_quote(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
610
+ if (start > 0 && text[start - 1] != '\n') {
611
+ return 0;
612
+ }
613
+
614
+ size_t end = start;
615
+
616
+ while (end < size && text[end] != '\n' ) {
617
+ ++end;
618
+ }
619
+
620
+ size_t block_start = start + 1;
621
+
622
+ while (block_start + 2 < size && text[block_start + 2] == '>') {
623
+ ++block_start;
624
+ }
625
+
626
+ size_t count = block_start - start;
627
+
628
+ buf_puts(out_buf, "<span class=\"q\">&gt;");
629
+
630
+ while (count > 1) {
631
+ buf_puts(out_buf, "&gt;");
632
+ count--;
633
+ }
634
+
635
+ parse_text(text, block_start, end, out_buf);
636
+
637
+ buf_puts(out_buf, "</span>");
638
+
639
+ return end - start;
640
+ }
641
+
642
+ static size_t parse_text(const uint8_t *text, size_t start, size_t size, buffer *out_buf) {
643
+ uint8_t action = 0;
644
+ size_t from, count, end;
645
+
646
+ end = start;
647
+
648
+ while (end < size) {
649
+ from = end;
650
+
651
+ while (end < size && (action = trigger_map[text[end]]) == 0) {
652
+ ++end;
653
+ }
654
+
655
+ if (end > from) {
656
+ escape_html(text, from, end, out_buf);
657
+ }
658
+
659
+ if (end >= size) {
660
+ break;
661
+ }
662
+
663
+ if ((count = trigger_funcs[action](text, end, size, out_buf)) != 0) {
664
+ end += count;
665
+ }
666
+ else {
667
+ escape_html(text, end, end + 1, out_buf);
668
+ ++end;
669
+ }
670
+ }
671
+
672
+ return end - start;
673
+ }
674
+
675
+ static VALUE rb_hive_markup_render(VALUE self, VALUE text) {
676
+ Check_Type(text, T_STRING);
677
+
678
+ size_t size;
679
+ size = RSTRING_LEN(text);
680
+
681
+ buffer *pre_buf = buf_new();
682
+
683
+ if (!pre_buf) {
684
+ return Qnil;
685
+ }
686
+
687
+ buffer *out_buf = buf_new();
688
+
689
+ if (!out_buf) {
690
+ return Qnil;
691
+ }
692
+
693
+ buf_expand(pre_buf, size);
694
+ buf_expand(out_buf, size);
695
+
696
+ preprocess_text((const uint8_t *)StringValuePtr(text), size, pre_buf);
697
+
698
+ parse_text(pre_buf->data, 0, pre_buf->size, out_buf);
699
+
700
+ text = rb_enc_str_new(
701
+ (const char *)out_buf->data,
702
+ out_buf->size,
703
+ rb_enc_get(text)
704
+ );
705
+
706
+ buf_free(pre_buf);
707
+ buf_free(out_buf);
708
+
709
+ return text;
710
+ }
711
+
712
+ void Init_hive_markup() {
713
+ init_triggers();
714
+
715
+ rb_mHive = rb_define_module("Hive");
716
+ rb_cMarkup = rb_define_class_under(rb_mHive, "Markup", rb_cObject);
717
+
718
+ rb_define_singleton_method(rb_cMarkup, "render", rb_hive_markup_render, 1);
719
+ }
@@ -0,0 +1,70 @@
1
+ /*
2
+ * Copyright (c) 2012, Vicent Marti
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ * THE SOFTWARE.
21
+ */
22
+
23
+ #ifndef HOUDINI_H
24
+ #define HOUDINI_H
25
+
26
+ /**
27
+ * According to the OWASP rules:
28
+ *
29
+ * & --> &amp;
30
+ * < --> &lt;
31
+ * > --> &gt;
32
+ * " --> &quot;
33
+ * ' --> &#x27; &apos; is not recommended
34
+ * / --> &#x2F; forward slash is included as it helps end an HTML entity
35
+ *
36
+ */
37
+ const char HTML_ESCAPE_TABLE[] = {
38
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40
+ 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4,
41
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0,
42
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
47
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54
+ };
55
+
56
+ const char *HTML_ESCAPES[] = {
57
+ "",
58
+ "&quot;",
59
+ "&amp;",
60
+ "&#39;",
61
+ "&#47;",
62
+ "&lt;",
63
+ "&gt;"
64
+ };
65
+
66
+ const char HTML_ESCAPES_LEN[] = {
67
+ 0, 6, 5, 5, 5, 4, 4
68
+ };
69
+
70
+ #endif
@@ -0,0 +1,18 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'hive_markup'
3
+ s.version = '0.0.1'
4
+ s.summary = 'Markup parser for HiveBBS'
5
+ s.author = 'Maxime Youdine'
6
+ s.license = 'MIT'
7
+ s.homepage = 'https://github.com/desuwa/hive_markup'
8
+ s.required_ruby_version = '>= 1.9.3'
9
+ s.files = %w[
10
+ hive_markup.gemspec
11
+ lib/hive_markup/hive_markup.rb
12
+ ext/hive_markup/extconf.rb
13
+ ext/hive_markup/houdini.h
14
+ ext/hive_markup/hive_markup.c
15
+ ]
16
+ s.extensions = ['ext/hive_markup/extconf.rb']
17
+ s.require_paths = ['lib']
18
+ end
@@ -0,0 +1 @@
1
+ require 'hive_markup.so'
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hive_markup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Maxime Youdine
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-05 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ executables: []
16
+ extensions:
17
+ - ext/hive_markup/extconf.rb
18
+ extra_rdoc_files: []
19
+ files:
20
+ - hive_markup.gemspec
21
+ - lib/hive_markup/hive_markup.rb
22
+ - ext/hive_markup/extconf.rb
23
+ - ext/hive_markup/houdini.h
24
+ - ext/hive_markup/hive_markup.c
25
+ homepage: https://github.com/desuwa/hive_markup
26
+ licenses:
27
+ - MIT
28
+ metadata: {}
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 1.9.3
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubyforge_project:
45
+ rubygems_version: 2.0.14
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: Markup parser for HiveBBS
49
+ test_files: []