markly 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/conduct.md +133 -0
  4. data/ext/markly/arena.c +9 -8
  5. data/ext/markly/autolink.c +217 -134
  6. data/ext/markly/blocks.c +27 -2
  7. data/ext/markly/cmark-gfm-core-extensions.h +11 -11
  8. data/ext/markly/cmark-gfm-extension_api.h +1 -0
  9. data/ext/markly/cmark-gfm.h +18 -2
  10. data/ext/markly/cmark.c +3 -3
  11. data/ext/markly/commonmark.c +19 -34
  12. data/ext/markly/extconf.rb +8 -1
  13. data/ext/markly/html.c +22 -6
  14. data/ext/markly/inlines.c +148 -51
  15. data/ext/markly/latex.c +6 -4
  16. data/ext/markly/man.c +7 -11
  17. data/ext/markly/map.c +11 -4
  18. data/ext/markly/map.h +5 -2
  19. data/ext/markly/markly.c +582 -586
  20. data/ext/markly/markly.h +1 -1
  21. data/ext/markly/node.c +76 -10
  22. data/ext/markly/node.h +42 -1
  23. data/ext/markly/parser.h +1 -0
  24. data/ext/markly/plaintext.c +12 -29
  25. data/ext/markly/references.c +1 -0
  26. data/ext/markly/render.c +15 -7
  27. data/ext/markly/scanners.c +13916 -10380
  28. data/ext/markly/scanners.h +8 -0
  29. data/ext/markly/scanners.re +47 -8
  30. data/ext/markly/strikethrough.c +1 -1
  31. data/ext/markly/table.c +81 -31
  32. data/ext/markly/xml.c +2 -1
  33. data/lib/markly/flags.rb +16 -0
  34. data/lib/markly/node/inspect.rb +59 -53
  35. data/lib/markly/node.rb +125 -58
  36. data/lib/markly/renderer/generic.rb +129 -124
  37. data/lib/markly/renderer/html.rb +294 -275
  38. data/lib/markly/version.rb +7 -1
  39. data/lib/markly.rb +36 -30
  40. data/license.md +39 -0
  41. data/readme.md +36 -0
  42. data.tar.gz.sig +0 -0
  43. metadata +61 -29
  44. metadata.gz.sig +0 -0
  45. data/bin/markly +0 -94
  46. data/lib/markly/markly.bundle +0 -0
@@ -15,6 +15,10 @@ bufsize_t _scan_autolink_uri(const unsigned char *p);
15
15
  bufsize_t _scan_autolink_email(const unsigned char *p);
16
16
  bufsize_t _scan_html_tag(const unsigned char *p);
17
17
  bufsize_t _scan_liberal_html_tag(const unsigned char *p);
18
+ bufsize_t _scan_html_comment(const unsigned char *p);
19
+ bufsize_t _scan_html_pi(const unsigned char *p);
20
+ bufsize_t _scan_html_declaration(const unsigned char *p);
21
+ bufsize_t _scan_html_cdata(const unsigned char *p);
18
22
  bufsize_t _scan_html_block_start(const unsigned char *p);
19
23
  bufsize_t _scan_html_block_start_7(const unsigned char *p);
20
24
  bufsize_t _scan_html_block_end_1(const unsigned char *p);
@@ -37,6 +41,10 @@ bufsize_t _scan_footnote_definition(const unsigned char *p);
37
41
  #define scan_autolink_email(c, n) _scan_at(&_scan_autolink_email, c, n)
38
42
  #define scan_html_tag(c, n) _scan_at(&_scan_html_tag, c, n)
39
43
  #define scan_liberal_html_tag(c, n) _scan_at(&_scan_liberal_html_tag, c, n)
44
+ #define scan_html_comment(c, n) _scan_at(&_scan_html_comment, c, n)
45
+ #define scan_html_pi(c, n) _scan_at(&_scan_html_pi, c, n)
46
+ #define scan_html_declaration(c, n) _scan_at(&_scan_html_declaration, c, n)
47
+ #define scan_html_cdata(c, n) _scan_at(&_scan_html_cdata, c, n)
40
48
  #define scan_html_block_start(c, n) _scan_at(&_scan_html_block_start, c, n)
41
49
  #define scan_html_block_start_7(c, n) _scan_at(&_scan_html_block_start_7, c, n)
42
50
  #define scan_html_block_end_1(c, n) _scan_at(&_scan_html_block_end_1, c, n)
@@ -54,16 +54,15 @@ bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c,
54
54
  opentag = tagname attribute* spacechar* [/]? [>];
55
55
  closetag = [/] tagname spacechar* [>];
56
56
 
57
- htmlcomment = "!---->" | ("!--" ([-]? [^\x00>-]) ([-]? [^\x00-])* "-->");
57
+ htmlcomment = "--" ([^\x00-]+ | "-" [^\x00-] | "--" [^\x00>])* "-->";
58
58
 
59
- processinginstruction = "?" ([^?>\x00]+ | [?][^>\x00] | [>])* "?>";
59
+ processinginstruction = ([^?>\x00]+ | [?][^>\x00] | [>])+;
60
60
 
61
- declaration = "!" [A-Z]+ spacechar+ [^>\x00]* ">";
61
+ declaration = [A-Z]+ spacechar+ [^>\x00]*;
62
62
 
63
- cdata = "![CDATA[" ([^\]\x00]+ | "]" [^\]\x00] | "]]" [^>\x00])* "]]>";
63
+ cdata = "CDATA[" ([^\]\x00]+ | "]" [^\]\x00] | "]]" [^>\x00])*;
64
64
 
65
- htmltag = opentag | closetag | htmlcomment | processinginstruction |
66
- declaration | cdata;
65
+ htmltag = opentag | closetag;
67
66
 
68
67
  in_parens_nosp = [(] (reg_char|escaped_char|[\\])* [)];
69
68
 
@@ -133,6 +132,46 @@ bufsize_t _scan_liberal_html_tag(const unsigned char *p)
133
132
  */
134
133
  }
135
134
 
135
+ bufsize_t _scan_html_comment(const unsigned char *p)
136
+ {
137
+ const unsigned char *marker = NULL;
138
+ const unsigned char *start = p;
139
+ /*!re2c
140
+ htmlcomment { return (bufsize_t)(p - start); }
141
+ * { return 0; }
142
+ */
143
+ }
144
+
145
+ bufsize_t _scan_html_pi(const unsigned char *p)
146
+ {
147
+ const unsigned char *marker = NULL;
148
+ const unsigned char *start = p;
149
+ /*!re2c
150
+ processinginstruction { return (bufsize_t)(p - start); }
151
+ * { return 0; }
152
+ */
153
+ }
154
+
155
+ bufsize_t _scan_html_declaration(const unsigned char *p)
156
+ {
157
+ const unsigned char *marker = NULL;
158
+ const unsigned char *start = p;
159
+ /*!re2c
160
+ declaration { return (bufsize_t)(p - start); }
161
+ * { return 0; }
162
+ */
163
+ }
164
+
165
+ bufsize_t _scan_html_cdata(const unsigned char *p)
166
+ {
167
+ const unsigned char *marker = NULL;
168
+ const unsigned char *start = p;
169
+ /*!re2c
170
+ cdata { return (bufsize_t)(p - start); }
171
+ * { return 0; }
172
+ */
173
+ }
174
+
136
175
  // Try to match an HTML block tag start line, returning
137
176
  // an integer code for the type of block (1-6, matching the spec).
138
177
  // #7 is handled by a separate function, below.
@@ -140,7 +179,7 @@ bufsize_t _scan_html_block_start(const unsigned char *p)
140
179
  {
141
180
  const unsigned char *marker = NULL;
142
181
  /*!re2c
143
- [<] ('script'|'pre'|'style') (spacechar | [>]) { return 1; }
182
+ [<] ('script'|'pre'|'textarea'|'style') (spacechar | [>]) { return 1; }
144
183
  '<!--' { return 2; }
145
184
  '<?' { return 3; }
146
185
  '<!' [A-Z] { return 4; }
@@ -167,7 +206,7 @@ bufsize_t _scan_html_block_end_1(const unsigned char *p)
167
206
  const unsigned char *marker = NULL;
168
207
  const unsigned char *start = p;
169
208
  /*!re2c
170
- [^\n\x00]* [<] [/] ('script'|'pre'|'style') [>] { return (bufsize_t)(p - start); }
209
+ [^\n\x00]* [<] [/] ('script'|'pre'|'textarea'|'style') [>] { return (bufsize_t)(p - start); }
171
210
  * { return 0; }
172
211
  */
173
212
  }
@@ -67,6 +67,7 @@ static delimiter *insert(cmark_syntax_extension *self, cmark_parser *parser,
67
67
  strikethrough->end_column = closer->inl_text->start_column + closer->inl_text->as.literal.len - 1;
68
68
  cmark_node_free(closer->inl_text);
69
69
 
70
+ done:
70
71
  delim = closer;
71
72
  while (delim != NULL && delim != opener) {
72
73
  tmp_delim = delim->previous;
@@ -76,7 +77,6 @@ static delimiter *insert(cmark_syntax_extension *self, cmark_parser *parser,
76
77
 
77
78
  cmark_inline_parser_remove_delimiter(inline_parser, opener);
78
79
 
79
- done:
80
80
  return res;
81
81
  }
82
82
 
data/ext/markly/table.c CHANGED
@@ -11,13 +11,21 @@
11
11
  #include "table.h"
12
12
  #include "cmark-gfm-core-extensions.h"
13
13
 
14
+ // Custom node flag, initialized in `create_table_extension`.
15
+ static cmark_node_internal_flags CMARK_NODE__TABLE_VISITED;
16
+
14
17
  cmark_node_type CMARK_NODE_TABLE, CMARK_NODE_TABLE_ROW,
15
18
  CMARK_NODE_TABLE_CELL;
16
19
 
20
+ typedef struct {
21
+ cmark_strbuf *buf;
22
+ int start_offset, end_offset, internal_offset;
23
+ } node_cell;
24
+
17
25
  typedef struct {
18
26
  uint16_t n_columns;
19
27
  int paragraph_offset;
20
- cmark_llist *cells;
28
+ node_cell *cells;
21
29
  } table_row;
22
30
 
23
31
  typedef struct {
@@ -29,24 +37,24 @@ typedef struct {
29
37
  bool is_header;
30
38
  } node_table_row;
31
39
 
32
- typedef struct {
33
- cmark_strbuf *buf;
34
- int start_offset, end_offset, internal_offset;
35
- } node_cell;
36
-
37
- static void free_table_cell(cmark_mem *mem, void *data) {
38
- node_cell *cell = (node_cell *)data;
40
+ static void free_table_cell(cmark_mem *mem, node_cell *cell) {
39
41
  cmark_strbuf_free((cmark_strbuf *)cell->buf);
40
42
  mem->free(cell->buf);
41
- mem->free(cell);
43
+ }
44
+
45
+ static void free_row_cells(cmark_mem *mem, table_row *row) {
46
+ while (row->n_columns > 0) {
47
+ free_table_cell(mem, &row->cells[--row->n_columns]);
48
+ }
49
+ mem->free(row->cells);
50
+ row->cells = NULL;
42
51
  }
43
52
 
44
53
  static void free_table_row(cmark_mem *mem, table_row *row) {
45
54
  if (!row)
46
55
  return;
47
56
 
48
- cmark_llist_free_full(mem, row->cells, (cmark_free_func)free_table_cell);
49
-
57
+ free_row_cells(mem, row);
50
58
  mem->free(row);
51
59
  }
52
60
 
@@ -111,6 +119,24 @@ static cmark_strbuf *unescape_pipes(cmark_mem *mem, unsigned char *string, bufsi
111
119
  return res;
112
120
  }
113
121
 
122
+ // Adds a new cell to the end of the row. A pointer to the new cell is returned
123
+ // for the caller to initialize.
124
+ static node_cell* append_row_cell(cmark_mem *mem, table_row *row) {
125
+ const uint32_t n_columns = row->n_columns + 1;
126
+ // realloc when n_columns is a power of 2
127
+ if ((n_columns & (n_columns-1)) == 0) {
128
+ // make sure we never wrap row->n_columns
129
+ // offset will != len and our exit will clean up as intended
130
+ if (n_columns > UINT16_MAX) {
131
+ return NULL;
132
+ }
133
+ // Use realloc to double the size of the buffer.
134
+ row->cells = (node_cell *)mem->realloc(row->cells, (2 * n_columns - 1) * sizeof(node_cell));
135
+ }
136
+ row->n_columns = (uint16_t)n_columns;
137
+ return &row->cells[n_columns-1];
138
+ }
139
+
114
140
  static table_row *row_from_string(cmark_syntax_extension *self,
115
141
  cmark_parser *parser, unsigned char *string,
116
142
  int len) {
@@ -129,6 +155,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
129
155
  bufsize_t cell_matched = 1, pipe_matched = 1, offset;
130
156
  int expect_more_cells = 1;
131
157
  int row_end_offset = 0;
158
+ int int_overflow_abort = 0;
132
159
 
133
160
  row = (table_row *)parser->mem->calloc(1, sizeof(table_row));
134
161
  row->n_columns = 0;
@@ -151,18 +178,22 @@ static table_row *row_from_string(cmark_syntax_extension *self,
151
178
  cell_matched);
152
179
  cmark_strbuf_trim(cell_buf);
153
180
 
154
- node_cell *cell = (node_cell *)parser->mem->calloc(1, sizeof(*cell));
181
+ node_cell *cell = append_row_cell(parser->mem, row);
182
+ if (!cell) {
183
+ int_overflow_abort = 1;
184
+ cmark_strbuf_free(cell_buf);
185
+ parser->mem->free(cell_buf);
186
+ break;
187
+ }
155
188
  cell->buf = cell_buf;
156
189
  cell->start_offset = offset;
157
190
  cell->end_offset = offset + cell_matched - 1;
191
+ cell->internal_offset = 0;
158
192
 
159
- while (cell->start_offset > 0 && string[cell->start_offset - 1] != '|') {
193
+ while (cell->start_offset > row->paragraph_offset && string[cell->start_offset - 1] != '|') {
160
194
  --cell->start_offset;
161
195
  ++cell->internal_offset;
162
196
  }
163
-
164
- row->n_columns += 1;
165
- row->cells = cmark_llist_append(parser->mem, row->cells, cell);
166
197
  }
167
198
 
168
199
  offset += cell_matched + pipe_matched;
@@ -180,9 +211,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
180
211
  if (row_end_offset && offset != len) {
181
212
  row->paragraph_offset = offset;
182
213
 
183
- cmark_llist_free_full(parser->mem, row->cells, (cmark_free_func)free_table_cell);
184
- row->cells = NULL;
185
- row->n_columns = 0;
214
+ free_row_cells(parser->mem, row);
186
215
 
187
216
  // Scan past the (optional) leading pipe.
188
217
  offset += scan_table_cell_end(string, len, offset);
@@ -194,7 +223,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
194
223
  }
195
224
  }
196
225
 
197
- if (offset != len || row->n_columns == 0) {
226
+ if (offset != len || row->n_columns == 0 || int_overflow_abort) {
198
227
  free_table_row(parser->mem, row);
199
228
  row = NULL;
200
229
  }
@@ -233,6 +262,10 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
233
262
  const char *parent_string;
234
263
  uint16_t i;
235
264
 
265
+ if (parent_container->flags & CMARK_NODE__TABLE_VISITED) {
266
+ return parent_container;
267
+ }
268
+
236
269
  if (!scan_table_start(input, len, cmark_parser_get_first_nonspace(parser))) {
237
270
  return parent_container;
238
271
  }
@@ -241,6 +274,11 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
241
274
  marker_row = row_from_string(self, parser,
242
275
  input + cmark_parser_get_first_nonspace(parser),
243
276
  len - cmark_parser_get_first_nonspace(parser));
277
+ // assert may be optimized out, don't rely on it for security boundaries
278
+ if (!marker_row) {
279
+ return parent_container;
280
+ }
281
+
244
282
  assert(marker_row);
245
283
 
246
284
  cmark_arena_push();
@@ -255,6 +293,7 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
255
293
  free_table_row(parser->mem, marker_row);
256
294
  free_table_row(parser->mem, header_row);
257
295
  cmark_arena_pop();
296
+ parent_container->flags |= CMARK_NODE__TABLE_VISITED;
258
297
  return parent_container;
259
298
  }
260
299
 
@@ -264,6 +303,12 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
264
303
  len - cmark_parser_get_first_nonspace(parser));
265
304
  header_row = row_from_string(self, parser, (unsigned char *)parent_string,
266
305
  (int)strlen(parent_string));
306
+ // row_from_string can return NULL, add additional check to ensure n_columns match
307
+ if (!marker_row || !header_row || header_row->n_columns != marker_row->n_columns) {
308
+ free_table_row(parser->mem, marker_row);
309
+ free_table_row(parser->mem, header_row);
310
+ return parent_container;
311
+ }
267
312
  }
268
313
 
269
314
  if (!cmark_node_set_type(parent_container, CMARK_NODE_TABLE)) {
@@ -281,11 +326,12 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
281
326
  parent_container->as.opaque = parser->mem->calloc(1, sizeof(node_table));
282
327
  set_n_table_columns(parent_container, header_row->n_columns);
283
328
 
329
+ // allocate alignments based on marker_row->n_columns
330
+ // since we populate the alignments array based on marker_row->cells
284
331
  uint8_t *alignments =
285
- (uint8_t *)parser->mem->calloc(header_row->n_columns, sizeof(uint8_t));
286
- cmark_llist *it = marker_row->cells;
287
- for (i = 0; it; it = it->next, ++i) {
288
- node_cell *node = (node_cell *)it->data;
332
+ (uint8_t *)parser->mem->calloc(marker_row->n_columns, sizeof(uint8_t));
333
+ for (i = 0; i < marker_row->n_columns; ++i) {
334
+ node_cell *node = &marker_row->cells[i];
289
335
  bool left = node->buf->ptr[0] == ':', right = node->buf->ptr[node->buf->size - 1] == ':';
290
336
 
291
337
  if (left && right)
@@ -308,10 +354,8 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
308
354
  ntr->is_header = true;
309
355
 
310
356
  {
311
- cmark_llist *tmp;
312
-
313
- for (tmp = header_row->cells; tmp; tmp = tmp->next) {
314
- node_cell *cell = (node_cell *) tmp->data;
357
+ for (i = 0; i < header_row->n_columns; ++i) {
358
+ node_cell *cell = &header_row->cells[i];
315
359
  cmark_node *header_cell = cmark_parser_add_child(parser, table_header,
316
360
  CMARK_NODE_TABLE_CELL, parent_container->start_column + cell->start_offset);
317
361
  header_cell->start_line = header_cell->end_line = parent_container->start_line;
@@ -351,12 +395,17 @@ static cmark_node *try_opening_table_row(cmark_syntax_extension *self,
351
395
  row = row_from_string(self, parser, input + cmark_parser_get_first_nonspace(parser),
352
396
  len - cmark_parser_get_first_nonspace(parser));
353
397
 
398
+ if (!row) {
399
+ // clean up the dangling node
400
+ cmark_node_free(table_row_block);
401
+ return NULL;
402
+ }
403
+
354
404
  {
355
- cmark_llist *tmp;
356
405
  int i, table_columns = get_n_table_columns(parent_container);
357
406
 
358
- for (tmp = row->cells, i = 0; tmp && i < table_columns; tmp = tmp->next, ++i) {
359
- node_cell *cell = (node_cell *) tmp->data;
407
+ for (i = 0; i < row->n_columns && i < table_columns; ++i) {
408
+ node_cell *cell = &row->cells[i];
360
409
  cmark_node *node = cmark_parser_add_child(parser, table_row_block,
361
410
  CMARK_NODE_TABLE_CELL, parent_container->start_column + cell->start_offset);
362
411
  node->internal_offset = cell->internal_offset;
@@ -759,6 +808,7 @@ static int escape(cmark_syntax_extension *self, cmark_node *node, int c) {
759
808
  cmark_syntax_extension *create_table_extension(void) {
760
809
  cmark_syntax_extension *self = cmark_syntax_extension_new("table");
761
810
 
811
+ cmark_register_node_flag(&CMARK_NODE__TABLE_VISITED);
762
812
  cmark_syntax_extension_set_match_block_func(self, matches);
763
813
  cmark_syntax_extension_set_open_block_func(self, try_opening_table_block);
764
814
  cmark_syntax_extension_set_get_type_string_func(self, get_type_string);
data/ext/markly/xml.c CHANGED
@@ -11,6 +11,7 @@
11
11
  #include "syntax_extension.h"
12
12
 
13
13
  #define BUFFER_SIZE 100
14
+ #define MAX_INDENT 40
14
15
 
15
16
  // Functions to convert cmark_nodes to XML strings.
16
17
 
@@ -26,7 +27,7 @@ struct render_state {
26
27
 
27
28
  static CMARK_INLINE void indent(struct render_state *state) {
28
29
  int i;
29
- for (i = 0; i < state->indent; i++) {
30
+ for (i = 0; i < state->indent && i < MAX_INDENT; i++) {
30
31
  cmark_strbuf_putc(state->xml, ' ');
31
32
  }
32
33
  }
data/lib/markly/flags.rb CHANGED
@@ -1,12 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Released under the MIT License.
4
+ # Copyright, 2020-2023, by Samuel Williams.
5
+
3
6
  module Markly
7
+ # The default parsing system.
4
8
  DEFAULT = 0
9
+ # Replace illegal sequences with the replacement character `U+FFFD`.
5
10
  VALIDATE_UTF8 = 1 << 9
11
+ # Use smart punctuation (curly quotes, etc.).
6
12
  SMART = 1 << 10
13
+ # Support liberal parsing of inline HTML tags.
7
14
  LIBERAL_HTML_TAG = 1 << 12
15
+ # Parse footnotes.
8
16
  FOOTNOTES = 1 << 13
17
+ # Support strikethrough using double tildes.
9
18
  STRIKETHROUGH_DOUBLE_TILDE = 1 << 14
19
+ # Allow raw/custom HTML and unsafe links.
10
20
  UNSAFE = 1 << 17
11
21
 
12
22
  PARSE_FLAGS = {
@@ -18,11 +28,17 @@ module Markly
18
28
  unsafe: UNSAFE,
19
29
  }
20
30
 
31
+ # Include source position in rendered HTML.
21
32
  SOURCE_POSITION = 1 << 1
33
+ # Treat `\n` as hardbreaks (by adding `<br/>`).
22
34
  HARD_BREAKS = 1 << 2
35
+ # Translate `\n` in the source to a single whitespace.
23
36
  NO_BREAKS = 1 << 4
37
+ # Use GitHub-style `<pre lang>` for fenced code blocks.
24
38
  GITHUB_PRE_LANG = 1 << 11
39
+ # Use `style` insted of `align` for table cells.
25
40
  TABLE_PREFER_STYLE_ATTRIBUTES = 1 << 15
41
+ # Include full info strings of code blocks in separate attribute.
26
42
  FULL_INFO_STRING = 1 << 16
27
43
 
28
44
  RENDER_FLAGS = {
@@ -1,59 +1,65 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Released under the MIT License.
4
+ # Copyright, 2017, by Goro Fuji.
5
+ # Copyright, 2017-2019, by Garen Torikian.
6
+ # Copyright, 2020, by Olle Jonsson.
7
+ # Copyright, 2020-2023, by Samuel Williams.
8
+
3
9
  require 'pp'
4
10
 
5
11
  module Markly
6
- class Node
7
- module Inspect
8
- PP_INDENT_SIZE = 2
9
-
10
- def inspect
11
- PP.pp(self, +'', Float::INFINITY)
12
- end
13
-
14
- # @param printer [PrettyPrint] pp
15
- def pretty_print(printer)
16
- printer.group(PP_INDENT_SIZE, "#<#{self.class}(#{type}):", '>') do
17
- printer.breakable
18
-
19
- attrs = %i[
20
- source_position
21
- string_content
22
- url
23
- title
24
- header_level
25
- list_type
26
- list_start
27
- list_tight
28
- fence_info
29
- ].map do |name|
30
- begin
31
- [name, __send__(name)]
32
- rescue Error
33
- nil
34
- end
35
- end.compact
36
-
37
- printer.seplist(attrs) do |name, value|
38
- printer.text "#{name}="
39
- printer.pp value
40
- end
41
-
42
- if first_child
43
- printer.breakable
44
- printer.group(PP_INDENT_SIZE) do
45
- children = []
46
- node = first_child
47
- while node
48
- children << node
49
- node = node.next
50
- end
51
- printer.text 'children='
52
- printer.pp children
53
- end
54
- end
55
- end
56
- end
57
- end
58
- end
12
+ class Node
13
+ module Inspect
14
+ PP_INDENT_SIZE = 2
15
+
16
+ def inspect
17
+ PP.pp(self, +'', Float::INFINITY)
18
+ end
19
+
20
+ # @param printer [PrettyPrint] pp
21
+ def pretty_print(printer)
22
+ printer.group(PP_INDENT_SIZE, "#<#{self.class}(#{type}):", '>') do
23
+ printer.breakable
24
+
25
+ attrs = %i[
26
+ source_position
27
+ string_content
28
+ url
29
+ title
30
+ header_level
31
+ list_type
32
+ list_start
33
+ list_tight
34
+ fence_info
35
+ ].map do |name|
36
+ begin
37
+ [name, __send__(name)]
38
+ rescue Error
39
+ nil
40
+ end
41
+ end.compact
42
+
43
+ printer.seplist(attrs) do |name, value|
44
+ printer.text "#{name}="
45
+ printer.pp value
46
+ end
47
+
48
+ if first_child
49
+ printer.breakable
50
+ printer.group(PP_INDENT_SIZE) do
51
+ children = []
52
+ node = first_child
53
+ while node
54
+ children << node
55
+ node = node.next
56
+ end
57
+ printer.text 'children='
58
+ printer.pp children
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
59
65
  end