markly 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/bin/markly +94 -0
  3. data/ext/markly/arena.c +103 -0
  4. data/ext/markly/autolink.c +425 -0
  5. data/ext/markly/autolink.h +8 -0
  6. data/ext/markly/blocks.c +1585 -0
  7. data/ext/markly/buffer.c +278 -0
  8. data/ext/markly/buffer.h +116 -0
  9. data/ext/markly/case_fold_switch.inc +4327 -0
  10. data/ext/markly/chunk.h +135 -0
  11. data/ext/markly/cmark-gfm-core-extensions.h +54 -0
  12. data/ext/markly/cmark-gfm-extension_api.h +736 -0
  13. data/ext/markly/cmark-gfm-extensions_export.h +42 -0
  14. data/ext/markly/cmark-gfm.h +817 -0
  15. data/ext/markly/cmark-gfm_export.h +42 -0
  16. data/ext/markly/cmark-gfm_version.h +7 -0
  17. data/ext/markly/cmark.c +55 -0
  18. data/ext/markly/cmark_ctype.c +44 -0
  19. data/ext/markly/cmark_ctype.h +33 -0
  20. data/ext/markly/commonmark.c +519 -0
  21. data/ext/markly/config.h +76 -0
  22. data/ext/markly/core-extensions.c +27 -0
  23. data/ext/markly/entities.inc +2138 -0
  24. data/ext/markly/ext_scanners.c +1159 -0
  25. data/ext/markly/ext_scanners.h +24 -0
  26. data/ext/markly/extconf.rb +7 -0
  27. data/ext/markly/footnotes.c +40 -0
  28. data/ext/markly/footnotes.h +25 -0
  29. data/ext/markly/houdini.h +57 -0
  30. data/ext/markly/houdini_href_e.c +100 -0
  31. data/ext/markly/houdini_html_e.c +66 -0
  32. data/ext/markly/houdini_html_u.c +149 -0
  33. data/ext/markly/html.c +465 -0
  34. data/ext/markly/html.h +27 -0
  35. data/ext/markly/inlines.c +1633 -0
  36. data/ext/markly/inlines.h +29 -0
  37. data/ext/markly/iterator.c +159 -0
  38. data/ext/markly/iterator.h +26 -0
  39. data/ext/markly/latex.c +466 -0
  40. data/ext/markly/linked_list.c +37 -0
  41. data/ext/markly/man.c +278 -0
  42. data/ext/markly/map.c +122 -0
  43. data/ext/markly/map.h +41 -0
  44. data/ext/markly/markly.c +1226 -0
  45. data/ext/markly/markly.h +16 -0
  46. data/ext/markly/node.c +979 -0
  47. data/ext/markly/node.h +118 -0
  48. data/ext/markly/parser.h +58 -0
  49. data/ext/markly/plaintext.c +235 -0
  50. data/ext/markly/plugin.c +36 -0
  51. data/ext/markly/plugin.h +34 -0
  52. data/ext/markly/references.c +42 -0
  53. data/ext/markly/references.h +26 -0
  54. data/ext/markly/registry.c +63 -0
  55. data/ext/markly/registry.h +24 -0
  56. data/ext/markly/render.c +205 -0
  57. data/ext/markly/render.h +62 -0
  58. data/ext/markly/scanners.c +20382 -0
  59. data/ext/markly/scanners.h +62 -0
  60. data/ext/markly/scanners.re +326 -0
  61. data/ext/markly/strikethrough.c +167 -0
  62. data/ext/markly/strikethrough.h +9 -0
  63. data/ext/markly/syntax_extension.c +149 -0
  64. data/ext/markly/syntax_extension.h +34 -0
  65. data/ext/markly/table.c +803 -0
  66. data/ext/markly/table.h +12 -0
  67. data/ext/markly/tagfilter.c +60 -0
  68. data/ext/markly/tagfilter.h +8 -0
  69. data/ext/markly/tasklist.c +156 -0
  70. data/ext/markly/tasklist.h +8 -0
  71. data/ext/markly/utf8.c +317 -0
  72. data/ext/markly/utf8.h +35 -0
  73. data/ext/markly/xml.c +181 -0
  74. data/lib/markly.rb +43 -0
  75. data/lib/markly/flags.rb +37 -0
  76. data/lib/markly/markly.so +0 -0
  77. data/lib/markly/node.rb +70 -0
  78. data/lib/markly/node/inspect.rb +59 -0
  79. data/lib/markly/renderer.rb +133 -0
  80. data/lib/markly/renderer/html_renderer.rb +252 -0
  81. data/lib/markly/version.rb +5 -0
  82. metadata +211 -0
@@ -0,0 +1,37 @@
1
+ #include <stdlib.h>
2
+
3
+ #include "cmark-gfm.h"
4
+
5
+ cmark_llist *cmark_llist_append(cmark_mem *mem, cmark_llist *head, void *data) {
6
+ cmark_llist *tmp;
7
+ cmark_llist *new_node = (cmark_llist *) mem->calloc(1, sizeof(cmark_llist));
8
+
9
+ new_node->data = data;
10
+ new_node->next = NULL;
11
+
12
+ if (!head)
13
+ return new_node;
14
+
15
+ for (tmp = head; tmp->next; tmp=tmp->next);
16
+
17
+ tmp->next = new_node;
18
+
19
+ return head;
20
+ }
21
+
22
+ void cmark_llist_free_full(cmark_mem *mem, cmark_llist *head, cmark_free_func free_func) {
23
+ cmark_llist *tmp, *prev;
24
+
25
+ for (tmp = head; tmp;) {
26
+ if (free_func)
27
+ free_func(mem, tmp->data);
28
+
29
+ prev = tmp;
30
+ tmp = tmp->next;
31
+ mem->free(prev);
32
+ }
33
+ }
34
+
35
+ void cmark_llist_free(cmark_mem *mem, cmark_llist *head) {
36
+ cmark_llist_free_full(mem, head, NULL);
37
+ }
@@ -0,0 +1,278 @@
1
+ #include <stdlib.h>
2
+ #include <stdio.h>
3
+ #include <string.h>
4
+ #include <assert.h>
5
+
6
+ #include "config.h"
7
+ #include "cmark-gfm.h"
8
+ #include "node.h"
9
+ #include "buffer.h"
10
+ #include "utf8.h"
11
+ #include "render.h"
12
+ #include "syntax_extension.h"
13
+
14
+ #define OUT(s, wrap, escaping) renderer->out(renderer, node, s, wrap, escaping)
15
+ #define LIT(s) renderer->out(renderer, node, s, false, LITERAL)
16
+ #define CR() renderer->cr(renderer)
17
+ #define BLANKLINE() renderer->blankline(renderer)
18
+ #define LIST_NUMBER_SIZE 20
19
+
20
+ // Functions to convert cmark_nodes to groff man strings.
21
+ static void S_outc(cmark_renderer *renderer, cmark_node *node,
22
+ cmark_escaping escape, int32_t c,
23
+ unsigned char nextc) {
24
+ (void)(nextc);
25
+
26
+ if (escape == LITERAL) {
27
+ cmark_render_code_point(renderer, c);
28
+ return;
29
+ }
30
+
31
+ switch (c) {
32
+ case 46:
33
+ if (renderer->begin_line) {
34
+ cmark_render_ascii(renderer, "\\&.");
35
+ } else {
36
+ cmark_render_code_point(renderer, c);
37
+ }
38
+ break;
39
+ case 39:
40
+ if (renderer->begin_line) {
41
+ cmark_render_ascii(renderer, "\\&'");
42
+ } else {
43
+ cmark_render_code_point(renderer, c);
44
+ }
45
+ break;
46
+ case 45:
47
+ cmark_render_ascii(renderer, "\\-");
48
+ break;
49
+ case 92:
50
+ cmark_render_ascii(renderer, "\\e");
51
+ break;
52
+ case 8216: // left single quote
53
+ cmark_render_ascii(renderer, "\\[oq]");
54
+ break;
55
+ case 8217: // right single quote
56
+ cmark_render_ascii(renderer, "\\[cq]");
57
+ break;
58
+ case 8220: // left double quote
59
+ cmark_render_ascii(renderer, "\\[lq]");
60
+ break;
61
+ case 8221: // right double quote
62
+ cmark_render_ascii(renderer, "\\[rq]");
63
+ break;
64
+ case 8212: // em dash
65
+ cmark_render_ascii(renderer, "\\[em]");
66
+ break;
67
+ case 8211: // en dash
68
+ cmark_render_ascii(renderer, "\\[en]");
69
+ break;
70
+ default:
71
+ cmark_render_code_point(renderer, c);
72
+ }
73
+ }
74
+
75
+ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
76
+ cmark_event_type ev_type, int options) {
77
+ cmark_node *tmp;
78
+ int list_number;
79
+ bool entering = (ev_type == CMARK_EVENT_ENTER);
80
+ bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);
81
+
82
+ if (node->extension && node->extension->man_render_func) {
83
+ node->extension->man_render_func(node->extension, renderer, node, ev_type, options);
84
+ return 1;
85
+ }
86
+
87
+ switch (node->type) {
88
+ case CMARK_NODE_DOCUMENT:
89
+ if (entering) {
90
+ /* Define a strikethrough macro */
91
+ /* Commenting out because this makes tests fail
92
+ LIT(".de ST");
93
+ CR();
94
+ LIT(".nr ww \\w'\\\\$1'");
95
+ CR();
96
+ LIT("\\Z@\\v'-.25m'\\l'\\\\n[ww]u'@\\\\$1");
97
+ CR();
98
+ LIT("..");
99
+ CR();
100
+ */
101
+ }
102
+ break;
103
+
104
+ case CMARK_NODE_BLOCK_QUOTE:
105
+ if (entering) {
106
+ CR();
107
+ LIT(".RS");
108
+ CR();
109
+ } else {
110
+ CR();
111
+ LIT(".RE");
112
+ CR();
113
+ }
114
+ break;
115
+
116
+ case CMARK_NODE_LIST:
117
+ break;
118
+
119
+ case CMARK_NODE_ITEM:
120
+ if (entering) {
121
+ CR();
122
+ LIT(".IP ");
123
+ if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
124
+ LIT("\\[bu] 2");
125
+ } else {
126
+ list_number = cmark_node_get_list_start(node->parent);
127
+ tmp = node;
128
+ while (tmp->prev) {
129
+ tmp = tmp->prev;
130
+ list_number += 1;
131
+ }
132
+ char list_number_s[LIST_NUMBER_SIZE];
133
+ snprintf(list_number_s, LIST_NUMBER_SIZE, "\"%d.\" 4", list_number);
134
+ LIT(list_number_s);
135
+ }
136
+ CR();
137
+ } else {
138
+ CR();
139
+ }
140
+ break;
141
+
142
+ case CMARK_NODE_HEADING:
143
+ if (entering) {
144
+ CR();
145
+ LIT(cmark_node_get_heading_level(node) == 1 ? ".SH" : ".SS");
146
+ CR();
147
+ } else {
148
+ CR();
149
+ }
150
+ break;
151
+
152
+ case CMARK_NODE_CODE_BLOCK:
153
+ CR();
154
+ LIT(".IP\n.nf\n\\f[C]\n");
155
+ OUT(cmark_node_get_literal(node), false, NORMAL);
156
+ CR();
157
+ LIT("\\f[]\n.fi");
158
+ CR();
159
+ break;
160
+
161
+ case CMARK_NODE_HTML_BLOCK:
162
+ break;
163
+
164
+ case CMARK_NODE_CUSTOM_BLOCK:
165
+ CR();
166
+ OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
167
+ false, LITERAL);
168
+ CR();
169
+ break;
170
+
171
+ case CMARK_NODE_THEMATIC_BREAK:
172
+ CR();
173
+ LIT(".PP\n * * * * *");
174
+ CR();
175
+ break;
176
+
177
+ case CMARK_NODE_PARAGRAPH:
178
+ if (entering) {
179
+ // no blank line if first paragraph in list:
180
+ if (node->parent && node->parent->type == CMARK_NODE_ITEM &&
181
+ node->prev == NULL) {
182
+ // no blank line or .PP
183
+ } else {
184
+ CR();
185
+ LIT(".PP");
186
+ CR();
187
+ }
188
+ } else {
189
+ CR();
190
+ }
191
+ break;
192
+
193
+ case CMARK_NODE_TEXT:
194
+ OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
195
+ break;
196
+
197
+ case CMARK_NODE_LINEBREAK:
198
+ LIT(".PD 0\n.P\n.PD");
199
+ CR();
200
+ break;
201
+
202
+ case CMARK_NODE_SOFTBREAK:
203
+ if (options & CMARK_OPT_HARDBREAKS) {
204
+ LIT(".PD 0\n.P\n.PD");
205
+ CR();
206
+ } else if (renderer->width == 0 && !(CMARK_OPT_NOBREAKS & options)) {
207
+ CR();
208
+ } else {
209
+ OUT(" ", allow_wrap, LITERAL);
210
+ }
211
+ break;
212
+
213
+ case CMARK_NODE_CODE:
214
+ LIT("\\f[C]");
215
+ OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
216
+ LIT("\\f[]");
217
+ break;
218
+
219
+ case CMARK_NODE_HTML_INLINE:
220
+ break;
221
+
222
+ case CMARK_NODE_CUSTOM_INLINE:
223
+ OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
224
+ false, LITERAL);
225
+ break;
226
+
227
+ case CMARK_NODE_STRONG:
228
+ if (entering) {
229
+ LIT("\\f[B]");
230
+ } else {
231
+ LIT("\\f[]");
232
+ }
233
+ break;
234
+
235
+ case CMARK_NODE_EMPH:
236
+ if (entering) {
237
+ LIT("\\f[I]");
238
+ } else {
239
+ LIT("\\f[]");
240
+ }
241
+ break;
242
+
243
+ case CMARK_NODE_LINK:
244
+ if (!entering) {
245
+ LIT(" (");
246
+ OUT(cmark_node_get_url(node), allow_wrap, URL);
247
+ LIT(")");
248
+ }
249
+ break;
250
+
251
+ case CMARK_NODE_IMAGE:
252
+ if (entering) {
253
+ LIT("[IMAGE: ");
254
+ } else {
255
+ LIT("]");
256
+ }
257
+ break;
258
+
259
+ case CMARK_NODE_FOOTNOTE_DEFINITION:
260
+ case CMARK_NODE_FOOTNOTE_REFERENCE:
261
+ // TODO
262
+ break;
263
+
264
+ default:
265
+ assert(false);
266
+ break;
267
+ }
268
+
269
+ return 1;
270
+ }
271
+
272
+ char *cmark_render_man(cmark_node *root, int options, int width) {
273
+ return cmark_render_man_with_mem(root, options, width, cmark_node_mem(root));
274
+ }
275
+
276
+ char *cmark_render_man_with_mem(cmark_node *root, int options, int width, cmark_mem *mem) {
277
+ return cmark_render(mem, root, options, width, S_outc, S_render_node);
278
+ }
@@ -0,0 +1,122 @@
1
+ #include "map.h"
2
+ #include "utf8.h"
3
+ #include "parser.h"
4
+
5
+ // normalize map label: collapse internal whitespace to single space,
6
+ // remove leading/trailing whitespace, case fold
7
+ // Return NULL if the label is actually empty (i.e. composed solely from
8
+ // whitespace)
9
+ unsigned char *normalize_map_label(cmark_mem *mem, cmark_chunk *ref) {
10
+ cmark_strbuf normalized = CMARK_BUF_INIT(mem);
11
+ unsigned char *result;
12
+
13
+ if (ref == NULL)
14
+ return NULL;
15
+
16
+ if (ref->len == 0)
17
+ return NULL;
18
+
19
+ cmark_utf8proc_case_fold(&normalized, ref->data, ref->len);
20
+ cmark_strbuf_trim(&normalized);
21
+ cmark_strbuf_normalize_whitespace(&normalized);
22
+
23
+ result = cmark_strbuf_detach(&normalized);
24
+ assert(result);
25
+
26
+ if (result[0] == '\0') {
27
+ mem->free(result);
28
+ return NULL;
29
+ }
30
+
31
+ return result;
32
+ }
33
+
34
+ static int
35
+ labelcmp(const unsigned char *a, const unsigned char *b) {
36
+ return strcmp((const char *)a, (const char *)b);
37
+ }
38
+
39
+ static int
40
+ refcmp(const void *p1, const void *p2) {
41
+ cmark_map_entry *r1 = *(cmark_map_entry **)p1;
42
+ cmark_map_entry *r2 = *(cmark_map_entry **)p2;
43
+ int res = labelcmp(r1->label, r2->label);
44
+ return res ? res : ((int)r1->age - (int)r2->age);
45
+ }
46
+
47
+ static int
48
+ refsearch(const void *label, const void *p2) {
49
+ cmark_map_entry *ref = *(cmark_map_entry **)p2;
50
+ return labelcmp((const unsigned char *)label, ref->label);
51
+ }
52
+
53
+ static void sort_map(cmark_map *map) {
54
+ unsigned int i = 0, last = 0, size = map->size;
55
+ cmark_map_entry *r = map->refs, **sorted = NULL;
56
+
57
+ sorted = (cmark_map_entry **)map->mem->calloc(size, sizeof(cmark_map_entry *));
58
+ while (r) {
59
+ sorted[i++] = r;
60
+ r = r->next;
61
+ }
62
+
63
+ qsort(sorted, size, sizeof(cmark_map_entry *), refcmp);
64
+
65
+ for (i = 1; i < size; i++) {
66
+ if (labelcmp(sorted[i]->label, sorted[last]->label) != 0)
67
+ sorted[++last] = sorted[i];
68
+ }
69
+
70
+ map->sorted = sorted;
71
+ map->size = last + 1;
72
+ }
73
+
74
+ cmark_map_entry *cmark_map_lookup(cmark_map *map, cmark_chunk *label) {
75
+ cmark_map_entry **ref = NULL;
76
+ unsigned char *norm;
77
+
78
+ if (label->len < 1 || label->len > MAX_LINK_LABEL_LENGTH)
79
+ return NULL;
80
+
81
+ if (map == NULL || !map->size)
82
+ return NULL;
83
+
84
+ norm = normalize_map_label(map->mem, label);
85
+ if (norm == NULL)
86
+ return NULL;
87
+
88
+ if (!map->sorted)
89
+ sort_map(map);
90
+
91
+ ref = (cmark_map_entry **)bsearch(norm, map->sorted, map->size, sizeof(cmark_map_entry *), refsearch);
92
+ map->mem->free(norm);
93
+
94
+ if (!ref)
95
+ return NULL;
96
+
97
+ return ref[0];
98
+ }
99
+
100
+ void cmark_map_free(cmark_map *map) {
101
+ cmark_map_entry *ref;
102
+
103
+ if (map == NULL)
104
+ return;
105
+
106
+ ref = map->refs;
107
+ while (ref) {
108
+ cmark_map_entry *next = ref->next;
109
+ map->free(map, ref);
110
+ ref = next;
111
+ }
112
+
113
+ map->mem->free(map->sorted);
114
+ map->mem->free(map);
115
+ }
116
+
117
+ cmark_map *cmark_map_new(cmark_mem *mem, cmark_map_free_f free) {
118
+ cmark_map *map = (cmark_map *)mem->calloc(1, sizeof(cmark_map));
119
+ map->mem = mem;
120
+ map->free = free;
121
+ return map;
122
+ }
@@ -0,0 +1,41 @@
1
+ #ifndef CMARK_MAP_H
2
+ #define CMARK_MAP_H
3
+
4
+ #include "chunk.h"
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ struct cmark_map_entry {
11
+ struct cmark_map_entry *next;
12
+ unsigned char *label;
13
+ unsigned int age;
14
+ };
15
+
16
+ typedef struct cmark_map_entry cmark_map_entry;
17
+
18
+ struct cmark_map;
19
+
20
+ typedef void (*cmark_map_free_f)(struct cmark_map *, cmark_map_entry *);
21
+
22
+ struct cmark_map {
23
+ cmark_mem *mem;
24
+ cmark_map_entry *refs;
25
+ cmark_map_entry **sorted;
26
+ unsigned int size;
27
+ cmark_map_free_f free;
28
+ };
29
+
30
+ typedef struct cmark_map cmark_map;
31
+
32
+ unsigned char *normalize_map_label(cmark_mem *mem, cmark_chunk *ref);
33
+ cmark_map *cmark_map_new(cmark_mem *mem, cmark_map_free_f free);
34
+ void cmark_map_free(cmark_map *map);
35
+ cmark_map_entry *cmark_map_lookup(cmark_map *map, cmark_chunk *label);
36
+
37
+ #ifdef __cplusplus
38
+ }
39
+ #endif
40
+
41
+ #endif