qiita_marker 0.23.2.2 → 0.23.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +19 -17
  3. data/Rakefile +57 -56
  4. data/bin/qiita_marker +2 -7
  5. data/ext/qiita_marker/blocks.c +4 -1
  6. data/ext/qiita_marker/cmark-gfm_version.h +2 -2
  7. data/ext/qiita_marker/qfm_custom_block.c +33 -52
  8. data/ext/qiita_marker/qiita_marker.c +30 -44
  9. data/ext/qiita_marker/scanners.c +2438 -2450
  10. data/ext/qiita_marker/table.c +28 -2
  11. data/lib/qiita_marker/config.rb +3 -3
  12. data/lib/qiita_marker/node/inspect.rb +8 -18
  13. data/lib/qiita_marker/node.rb +6 -6
  14. data/lib/qiita_marker/renderer/html_renderer.rb +38 -38
  15. data/lib/qiita_marker/renderer.rb +5 -5
  16. data/lib/qiita_marker/version.rb +1 -1
  17. data/lib/qiita_marker.rb +9 -11
  18. data/qiita_marker.gemspec +27 -29
  19. metadata +3 -63
  20. data/test/benchmark.rb +0 -32
  21. data/test/fixtures/curly.md +0 -1
  22. data/test/fixtures/dingus.md +0 -10
  23. data/test/fixtures/strong.md +0 -1
  24. data/test/fixtures/table.md +0 -10
  25. data/test/test_attributes.rb +0 -24
  26. data/test/test_basics.rb +0 -35
  27. data/test/test_commands.rb +0 -72
  28. data/test/test_commonmark.rb +0 -36
  29. data/test/test_doc.rb +0 -130
  30. data/test/test_encoding.rb +0 -23
  31. data/test/test_extensions.rb +0 -116
  32. data/test/test_footnotes.rb +0 -60
  33. data/test/test_gc.rb +0 -47
  34. data/test/test_helper.rb +0 -71
  35. data/test/test_linebreaks.rb +0 -15
  36. data/test/test_maliciousness.rb +0 -262
  37. data/test/test_node.rb +0 -89
  38. data/test/test_options.rb +0 -37
  39. data/test/test_pathological_inputs.rb +0 -94
  40. data/test/test_plaintext.rb +0 -46
  41. data/test/test_qfm_autolink_class_name.rb +0 -62
  42. data/test/test_qfm_code_data_metadata.rb +0 -41
  43. data/test/test_qfm_custom_block.rb +0 -39
  44. data/test/test_qfm_mention_no_emphasis.rb +0 -60
  45. data/test/test_renderer.rb +0 -47
  46. data/test/test_smartpunct.rb +0 -27
  47. data/test/test_spec.rb +0 -30
  48. data/test/test_tasklists.rb +0 -43
  49. data/test/test_xml.rb +0 -107
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15d5d73e2386cf310ae997adc33bfca334a51c241a0345b8d5fddc2af9a988bf
4
- data.tar.gz: c45e0c3f30cfd5dfad5d8beb4dc0f3ee08fc6bb405e2dfb188623393180fa104
3
+ metadata.gz: 343d2a549df9aee75c4bb3890307425d9a82251a2dfe46826afd6f8a8bfcb245
4
+ data.tar.gz: bf76c480df59b28e13cace472228b3ca39a60d9ce3406a866125f347c18689c1
5
5
  SHA512:
6
- metadata.gz: 88d95a7228008d65a57f13d571370c3fe9a3701319e2e6a801a16659c032646d592345e155a23a8ac4f70b8d87a347b152a72b8447399c73285f2b475e3426d5
7
- data.tar.gz: b3a3a996bfac4705044451fee3ecd7cd29909de05b3a1c9b52f64e9cc9cf14497820b8a74f67f49225c7ab777d87a83e9a0da104fa15219df03a3efb1c054a66
6
+ metadata.gz: 0c8c25dda4cadad88e855c84fa02d42de53c54c87665ca6b5530483a78b57e100b3df9869fe1f451faf16679a5de3ed7c6f630c9568258fdb559fd0d255cb2e2
7
+ data.tar.gz: d0927839957a98673181f2235f8a4e16a6ddfc2fa5bb88259d0cb7723bf925472e8214f98aa5ede40a24d3420af48b8b8e877472278efeb683eba80c171edd92
data/LICENSE.txt CHANGED
@@ -1,21 +1,23 @@
1
- MIT License
1
+ Copyright (c) 2015 Garen J. Torikian
2
+ Copyright (c) 2021 Qiita Inc.
2
3
 
3
- Copyright 2021 Qiita Inc.
4
+ MIT License
4
5
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
11
13
 
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
14
16
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,113 +1,114 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'date'
4
- require 'rake/clean'
5
- require 'rake/extensiontask'
6
- require 'digest/md5'
3
+ require "date"
4
+ require "rake/clean"
5
+ require "rake/extensiontask"
6
+ require "digest/md5"
7
7
 
8
- host_os = RbConfig::CONFIG['host_os']
9
- require 'devkit' if host_os == 'mingw32'
8
+ host_os = RbConfig::CONFIG["host_os"]
9
+ require "devkit" if host_os == "mingw32"
10
10
 
11
11
  task default: [:test]
12
12
 
13
13
  # Gem Spec
14
- gem_spec = Gem::Specification.load('qiita_marker.gemspec')
14
+ gem_spec = Gem::Specification.load("qiita_marker.gemspec")
15
15
 
16
16
  # Ruby Extension
17
- Rake::ExtensionTask.new('qiita_marker', gem_spec) do |ext|
18
- ext.lib_dir = File.join('lib', 'qiita_marker')
17
+ Rake::ExtensionTask.new("qiita_marker", gem_spec) do |ext|
18
+ ext.lib_dir = File.join("lib", "qiita_marker")
19
19
  end
20
20
 
21
21
  # Packaging
22
- require 'bundler/gem_tasks'
22
+ require "bundler/gem_tasks"
23
23
 
24
24
  # Testing
25
- require 'rake/testtask'
25
+ require "rake/testtask"
26
26
 
27
- Rake::TestTask.new('test:unit') do |t|
28
- t.libs << 'lib'
29
- t.libs << 'test'
30
- t.pattern = 'test/test_*.rb'
27
+ Rake::TestTask.new("test:unit") do |t|
28
+ t.libs << "lib"
29
+ t.libs << "test"
30
+ t.pattern = "test/test_*.rb"
31
31
  t.verbose = true
32
32
  t.warning = false
33
33
  end
34
34
 
35
- task 'test:unit' => :compile
35
+ desc "Run unit tests"
36
+ task "test:unit" => :compile
36
37
 
37
- desc 'Run unit and conformance tests'
38
- task test: %w[test:unit]
38
+ desc "Run unit and conformance tests"
39
+ task test: ["test:unit"]
39
40
 
40
- require 'rubocop/rake_task'
41
+ require "rubocop/rake_task"
41
42
 
42
43
  RuboCop::RakeTask.new(:rubocop)
43
44
 
44
- desc 'Run benchmarks'
45
+ desc "Run benchmarks"
45
46
  task :benchmark do
46
- if ENV['FETCH_PROGIT']
47
- `rm -rf test/progit`
48
- `git clone https://github.com/progit/progit.git test/progit`
49
- langs = %w[ar az be ca cs de en eo es es-ni fa fi fr hi hu id it ja ko mk nl no-nb pl pt-br ro ru sr th tr uk vi zh zh-tw]
47
+ if ENV["FETCH_PROGIT"]
48
+ %x(rm -rf test/progit)
49
+ %x(git clone https://github.com/progit/progit.git test/progit)
50
+ langs = ["ar", "az", "be", "ca", "cs", "de", "en", "eo", "es", "es-ni", "fa", "fi", "fr", "hi", "hu", "id", "it", "ja", "ko", "mk", "nl", "no-nb", "pl", "pt-br", "ro", "ru", "sr", "th", "tr", "uk", "vi", "zh", "zh-tw"]
50
51
  langs.each do |lang|
51
- `cat test/progit/#{lang}/*/*.markdown >> test/benchinput.md`
52
+ %x(cat test/progit/#{lang}/*/*.markdown >> test/benchinput.md)
52
53
  end
53
54
  end
54
- $LOAD_PATH.unshift 'lib'
55
- load 'test/benchmark.rb'
55
+ $LOAD_PATH.unshift("lib")
56
+ load "test/benchmark.rb"
56
57
  end
57
58
 
58
- desc 'Match C style of cmark'
59
+ desc "Match C style of cmark"
59
60
  task :format do
60
- sh 'clang-format -style llvm -i ext/qiita_marker/*.c ext/qiita_marker/*.h'
61
+ sh "clang-format -style llvm -i ext/qiita_marker/*.c ext/qiita_marker/*.h"
61
62
  end
62
63
 
63
64
  # Documentation
64
- require 'rdoc/task'
65
+ require "rdoc/task"
65
66
 
66
- desc 'Generate API documentation'
67
+ desc "Generate API documentation"
67
68
  RDoc::Task.new do |rd|
68
- rd.rdoc_dir = 'docs'
69
- rd.main = 'README.md'
70
- rd.rdoc_files.include 'README.md', 'lib/**/*.rb', 'ext/qiita_marker/qiita_marker.c'
71
-
72
- rd.options << '--markup tomdoc'
73
- rd.options << '--inline-source'
74
- rd.options << '--line-numbers'
75
- rd.options << '--all'
76
- rd.options << '--fileboxes'
69
+ rd.rdoc_dir = "docs"
70
+ rd.main = "README.md"
71
+ rd.rdoc_files.include("README.md", "lib/**/*.rb", "ext/qiita_marker/qiita_marker.c")
72
+
73
+ rd.options << "--markup tomdoc"
74
+ rd.options << "--inline-source"
75
+ rd.options << "--line-numbers"
76
+ rd.options << "--all"
77
+ rd.options << "--fileboxes"
77
78
  end
78
79
 
79
- desc 'Generate the documentation and run a web server'
80
+ desc "Generate the documentation and run a web server"
80
81
  task serve: [:rdoc] do
81
- require 'webrick'
82
+ require "webrick"
82
83
 
83
- puts 'Navigate to http://localhost:3000 to see the docs'
84
+ puts "Navigate to http://localhost:3000 to see the docs"
84
85
 
85
- server = WEBrick::HTTPServer.new Port: 3000
86
- server.mount '/', WEBrick::HTTPServlet::FileHandler, 'docs'
87
- trap('INT') { server.stop }
86
+ server = WEBrick::HTTPServer.new(Port: 3000)
87
+ server.mount("/", WEBrick::HTTPServlet::FileHandler, "docs")
88
+ trap("INT") { server.stop }
88
89
  server.start
89
90
  end
90
91
 
91
- desc 'Generate and publish docs to gh-pages'
92
+ desc "Generate and publish docs to gh-pages"
92
93
  task publish: [:rdoc] do
93
- require 'tmpdir'
94
- require 'shellwords'
94
+ require "tmpdir"
95
+ require "shellwords"
95
96
 
96
97
  Dir.mktmpdir do |tmp|
97
98
  system "mv docs/* #{tmp}"
98
- system 'git checkout origin/gh-pages'
99
- system 'rm -rf *'
99
+ system "git checkout origin/gh-pages"
100
+ system "rm -rf *"
100
101
  system "mv #{tmp}/* ."
101
102
  message = Shellwords.escape("Site updated at #{Time.now.utc}")
102
- system 'git add .'
103
+ system "git add ."
103
104
  system "git commit -am #{message}"
104
- system 'git push origin gh-pages --force'
105
- system 'git checkout master'
106
- system 'echo yolo'
105
+ system "git push origin gh-pages --force"
106
+ system "git checkout master"
107
+ system "echo yolo"
107
108
  end
108
109
  end
109
110
 
110
111
  # Custom tasks
111
- Dir.glob('tasks/*.rake').each do |f|
112
+ Dir.glob("tasks/*.rake").each do |f|
112
113
  load f
113
114
  end
data/bin/qiita_marker CHANGED
@@ -2,7 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'optparse'
5
- require 'ostruct'
6
5
 
7
6
  $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
8
7
  require 'qiita_marker'
@@ -11,17 +10,13 @@ root = File.expand_path('..', __dir__)
11
10
  $LOAD_PATH.unshift File.expand_path('lib', root)
12
11
 
13
12
  def parse_options
14
- options = OpenStruct.new
13
+ options = Struct.new(:active_extensions, :active_parse_options, :active_render_options, :output_format, :renderer)
14
+ .new([], [:DEFAULT], [:DEFAULT], :html)
15
15
  extensions = QiitaMarker.extensions
16
16
  parse_options = QiitaMarker::Config::OPTS.fetch(:parse)
17
17
  render_options = QiitaMarker::Config::OPTS.fetch(:render)
18
18
  format_options = QiitaMarker::Config::OPTS.fetch(:format)
19
19
 
20
- options.active_extensions = []
21
- options.active_parse_options = [:DEFAULT]
22
- options.active_render_options = [:DEFAULT]
23
- options.output_format = :html
24
-
25
20
  option_parser = OptionParser.new do |opts|
26
21
  opts.banner = 'Usage: qiita_marker [--html-renderer] [--extension=EXTENSION]'
27
22
  opts.separator ' [--to=FORMAT]'
@@ -22,6 +22,7 @@
22
22
  #include "houdini.h"
23
23
  #include "buffer.h"
24
24
  #include "footnotes.h"
25
+ #include "qfm_custom_block.h"
25
26
 
26
27
  #define CODE_INDENT 4
27
28
  #define TAB_STOP 4
@@ -289,7 +290,9 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
289
290
  b->end_column = parser->last_line_length;
290
291
  } else if (S_type(b) == CMARK_NODE_DOCUMENT ||
291
292
  (S_type(b) == CMARK_NODE_CODE_BLOCK && b->as.code.fenced) ||
292
- (S_type(b) == CMARK_NODE_HEADING && b->as.heading.setext)) {
293
+ (S_type(b) == CMARK_NODE_HEADING && b->as.heading.setext) ||
294
+ /* For make the sourcepos of the `qfm_custom_block` accurate */
295
+ (cmark_node_get_type(b) == CMARK_NODE_QFM_CUSTOM_BLOCK)) {
293
296
  b->end_line = parser->line_number;
294
297
  b->end_column = parser->curline.size;
295
298
  if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\n')
@@ -1,7 +1,7 @@
1
1
  #ifndef CMARK_GFM_VERSION_H
2
2
  #define CMARK_GFM_VERSION_H
3
3
 
4
- #define CMARK_GFM_VERSION ((0 << 24) | (29 << 16) | (0 << 8) | 2)
5
- #define CMARK_GFM_VERSION_STRING "0.29.0.gfm.2"
4
+ #define CMARK_GFM_VERSION ((0 << 24) | (29 << 16) | (0 << 8) | 4)
5
+ #define CMARK_GFM_VERSION_STRING "0.29.0.gfm.4"
6
6
 
7
7
  #endif
@@ -6,14 +6,13 @@
6
6
  #include "houdini.h"
7
7
  #include "qfm_custom_block.h"
8
8
  #include "qfm_scanners.h"
9
- #include "strikethrough.h"
10
9
 
11
10
  cmark_node_type CMARK_NODE_QFM_CUSTOM_BLOCK;
12
11
 
13
12
  typedef struct {
13
+ /* info: Text following the opening custom block fence (optional). This is
14
+ * trimmed of leading and trailing whitespace. */
14
15
  cmark_chunk info;
15
- bool opening;
16
- cmark_strbuf *xml_attr_buff;
17
16
  } node_qfm_custom_block;
18
17
 
19
18
  static void escape_html(cmark_strbuf *dest, const unsigned char *source,
@@ -21,33 +20,6 @@ static void escape_html(cmark_strbuf *dest, const unsigned char *source,
21
20
  houdini_escape_html0(dest, source, length, 0);
22
21
  }
23
22
 
24
- static bool get_qfm_custom_block_opening(cmark_node *node) {
25
- if (node == NULL) {
26
- return false;
27
- }
28
-
29
- cmark_node_type node_type = cmark_node_get_type(node);
30
- if (node_type == CMARK_NODE_QFM_CUSTOM_BLOCK) {
31
- return ((node_qfm_custom_block *)node->as.opaque)->opening;
32
- } else {
33
- return false;
34
- }
35
- }
36
-
37
- static bool set_qfm_custom_block_opening(cmark_node *node, bool opening) {
38
- if (node == NULL) {
39
- return false;
40
- }
41
-
42
- cmark_node_type node_type = cmark_node_get_type(node);
43
- if (node_type == CMARK_NODE_QFM_CUSTOM_BLOCK) {
44
- ((node_qfm_custom_block *)node->as.opaque)->opening = opening;
45
- return true;
46
- } else {
47
- return false;
48
- }
49
- }
50
-
51
23
  static cmark_chunk *get_qfm_custom_block_info(cmark_node *node) {
52
24
  if (node == NULL) {
53
25
  return NULL;
@@ -81,26 +53,21 @@ static void free_node_qfm_custom_block(cmark_mem *mem, void *ptr) {
81
53
  node_qfm_custom_block *cb = (node_qfm_custom_block *)ptr;
82
54
 
83
55
  cmark_chunk_free(mem, &cb->info);
84
- cmark_strbuf_free(cb->xml_attr_buff);
85
56
  mem->free(cb);
86
57
  }
87
58
 
59
+ /* Now, a custom block can contain another custom block, but this behavior is
60
+ * not a specification. */
88
61
  static int matches(cmark_syntax_extension *self, cmark_parser *parser,
89
62
  unsigned char *input, int len,
90
63
  cmark_node *parent_container) {
91
- int res = 0;
92
-
93
- if (get_qfm_custom_block_opening(parent_container)) {
94
- bufsize_t matched = scan_close_qfm_custom_block_fence(
95
- input, len, cmark_parser_get_first_nonspace(parser));
64
+ int res = 1;
65
+ bufsize_t matched = scan_close_qfm_custom_block_fence(
66
+ input, len, cmark_parser_get_first_nonspace(parser));
96
67
 
97
- if (matched > 0) {
98
- set_qfm_custom_block_opening(parent_container, false);
99
- cmark_parser_advance_offset(parser, (char *)input,
100
- len - cmark_parser_get_offset(parser), 0);
101
- } else {
102
- res = 1;
103
- }
68
+ if (matched > 0) {
69
+ cmark_parser_advance_offset(parser, (char *)input, matched, 0);
70
+ res = 0;
104
71
  }
105
72
 
106
73
  return res;
@@ -120,21 +87,34 @@ static cmark_node *try_opening_qfm_custom_block_block(
120
87
 
121
88
  cmark_node *custom_block_node = cmark_parser_add_child(
122
89
  parser, parent_container, CMARK_NODE_QFM_CUSTOM_BLOCK,
123
- parser->first_nonspace_column);
90
+ parser->first_nonspace + 1);
124
91
  custom_block_node->as.opaque = (node_qfm_custom_block *)parser->mem->calloc(
125
92
  1, sizeof(node_qfm_custom_block));
126
93
 
127
94
  cmark_strbuf *info = parser->mem->calloc(1, sizeof(cmark_strbuf));
128
- cmark_strbuf_init(parser->mem, info, len - matched);
129
- cmark_strbuf_put(info, input + matched, len - matched);
130
- cmark_strbuf_trim(info);
95
+ bufsize_t info_startpos = cmark_parser_get_first_nonspace(parser) + matched;
96
+
97
+ /* Length from after opening custom block fence to before newline character.
98
+ */
99
+ bufsize_t info_len = len - info_startpos;
100
+ if (info_len > 0 && input[len - 1] == '\n') {
101
+ info_len -= 1;
102
+ }
103
+ if (info_len > 0 && input[len - 1] == '\r') {
104
+ info_len -= 1;
105
+ }
131
106
 
132
- set_qfm_custom_block_opening(custom_block_node, true);
107
+ cmark_strbuf_init(parser->mem, info, info_len);
108
+ cmark_strbuf_put(info, input + info_startpos, info_len);
109
+ cmark_strbuf_trim(info);
133
110
  set_qfm_custom_block_info(custom_block_node, (char *)info->ptr);
134
111
 
135
112
  cmark_node_set_syntax_extension(custom_block_node, self);
136
113
  cmark_parser_advance_offset(parser, (char *)input,
137
- len - cmark_parser_get_offset(parser), 0);
114
+ cmark_parser_get_first_nonspace(parser) +
115
+ matched + info_len -
116
+ cmark_parser_get_offset(parser),
117
+ 0);
138
118
 
139
119
  return custom_block_node;
140
120
  }
@@ -155,12 +135,14 @@ static const char *get_type_string(cmark_syntax_extension *self,
155
135
 
156
136
  static int can_contain(cmark_syntax_extension *self, cmark_node *node,
157
137
  cmark_node_type child_type) {
138
+ /* Can contain all block nodes */
158
139
  cmark_node_type node_type = cmark_node_get_type(node);
159
140
 
160
141
  return node_type == CMARK_NODE_QFM_CUSTOM_BLOCK;
161
142
  }
162
143
 
163
144
  static int contains_inlines(cmark_syntax_extension *self, cmark_node *node) {
145
+ /* Can contain all inline nodes */
164
146
  cmark_node_type node_type = cmark_node_get_type(node);
165
147
 
166
148
  return node_type == CMARK_NODE_QFM_CUSTOM_BLOCK;
@@ -210,9 +192,8 @@ static const char *xml_attr(cmark_syntax_extension *self, cmark_node *node) {
210
192
  if (node_type == CMARK_NODE_QFM_CUSTOM_BLOCK) {
211
193
  cmark_chunk *info = get_qfm_custom_block_info(node);
212
194
  cmark_mem *mem = node->content.mem;
213
-
214
195
  cmark_strbuf *xml_attr_buff = mem->calloc(1, sizeof(cmark_strbuf));
215
- ((node_qfm_custom_block *)node->as.opaque)->xml_attr_buff = xml_attr_buff;
196
+
216
197
  cmark_strbuf_init(
217
198
  mem, xml_attr_buff,
218
199
  17 + info->len); // `17` is length of ` data-metadata="` and `"`.
@@ -220,7 +201,7 @@ static const char *xml_attr(cmark_syntax_extension *self, cmark_node *node) {
220
201
  cmark_strbuf_puts(xml_attr_buff, (char *)info->data);
221
202
  cmark_strbuf_putc(xml_attr_buff, '"');
222
203
 
223
- return (char *)xml_attr_buff->ptr;
204
+ return (char *)cmark_strbuf_detach(xml_attr_buff);
224
205
  }
225
206
 
226
207
  return NULL;
@@ -115,25 +115,23 @@ static void rb_parent_removed(VALUE val) {
115
115
  RDATA(val)->dfree = rb_free_c_struct;
116
116
  }
117
117
 
118
- static cmark_parser *prepare_parser(VALUE rb_options, VALUE rb_extensions, cmark_mem *mem) {
118
+ static cmark_parser *prepare_parser(VALUE rb_options, VALUE rb_extensions) {
119
119
  int options;
120
- int extensions_len;
121
120
  VALUE rb_ext_name;
122
121
  int i;
123
122
 
124
- Check_Type(rb_options, T_FIXNUM);
123
+ FIXNUM_P(rb_options);
124
+ options = FIX2INT(rb_options);
125
+
125
126
  Check_Type(rb_extensions, T_ARRAY);
126
127
 
127
- options = FIX2INT(rb_options);
128
- extensions_len = RARRAY_LEN(rb_extensions);
128
+ cmark_parser *parser = cmark_parser_new(options);
129
129
 
130
- cmark_parser *parser = cmark_parser_new_with_mem(options, mem);
131
- for (i = 0; i < extensions_len; ++i) {
132
- rb_ext_name = RARRAY_PTR(rb_extensions)[i];
130
+ for (i = 0; i < RARRAY_LEN(rb_extensions); ++i) {
131
+ rb_ext_name = rb_ary_entry(rb_extensions, i);
133
132
 
134
133
  if (!SYMBOL_P(rb_ext_name)) {
135
134
  cmark_parser_free(parser);
136
- cmark_arena_reset();
137
135
  rb_raise(rb_eTypeError, "extension names should be Symbols; got a %"PRIsVALUE"", rb_obj_class(rb_ext_name));
138
136
  }
139
137
 
@@ -142,7 +140,6 @@ static cmark_parser *prepare_parser(VALUE rb_options, VALUE rb_extensions, cmark
142
140
 
143
141
  if (!syntax_extension) {
144
142
  cmark_parser_free(parser);
145
- cmark_arena_reset();
146
143
  rb_raise(rb_eArgError, "extension %s not found", rb_id2name(SYM2ID(rb_ext_name)));
147
144
  }
148
145
 
@@ -157,33 +154,28 @@ static cmark_parser *prepare_parser(VALUE rb_options, VALUE rb_extensions, cmark
157
154
  *
158
155
  */
159
156
  static VALUE rb_markdown_to_html(VALUE self, VALUE rb_text, VALUE rb_options, VALUE rb_extensions) {
160
- char *str, *html;
161
- int len;
157
+ char *html;
162
158
  cmark_parser *parser;
163
159
  cmark_node *doc;
164
- Check_Type(rb_text, T_STRING);
165
- Check_Type(rb_options, T_FIXNUM);
166
160
 
167
- parser = prepare_parser(rb_options, rb_extensions, cmark_get_arena_mem_allocator());
161
+ Check_Type(rb_text, T_STRING);
168
162
 
169
- str = (char *)RSTRING_PTR(rb_text);
170
- len = RSTRING_LEN(rb_text);
163
+ parser = prepare_parser(rb_options, rb_extensions);
171
164
 
172
- cmark_parser_feed(parser, str, len);
165
+ cmark_parser_feed(parser, StringValuePtr(rb_text), RSTRING_LEN(rb_text));
173
166
  doc = cmark_parser_finish(parser);
167
+
174
168
  if (doc == NULL) {
175
- cmark_arena_reset();
169
+ cmark_parser_free(parser);
176
170
  rb_raise(rb_eNodeError, "error parsing document");
177
171
  }
178
172
 
179
- cmark_mem *default_mem = cmark_get_default_mem_allocator();
180
- html = cmark_render_html_with_mem(doc, FIX2INT(rb_options), parser->syntax_extensions, default_mem);
181
- cmark_arena_reset();
173
+ html = cmark_render_html(doc, parser->options, parser->syntax_extensions);
182
174
 
183
- VALUE ruby_html = rb_str_new2(html);
184
- default_mem->free(html);
175
+ cmark_parser_free(parser);
176
+ cmark_node_free(doc);
185
177
 
186
- return ruby_html;
178
+ return rb_utf8_str_new_cstr(html);
187
179
  }
188
180
 
189
181
  /*
@@ -191,33 +183,28 @@ static VALUE rb_markdown_to_html(VALUE self, VALUE rb_text, VALUE rb_options, VA
191
183
  *
192
184
  */
193
185
  static VALUE rb_markdown_to_xml(VALUE self, VALUE rb_text, VALUE rb_options, VALUE rb_extensions) {
194
- char *str, *xml;
195
- int len;
186
+ char *xml;
196
187
  cmark_parser *parser;
197
188
  cmark_node *doc;
198
- Check_Type(rb_text, T_STRING);
199
- Check_Type(rb_options, T_FIXNUM);
200
189
 
201
- parser = prepare_parser(rb_options, rb_extensions, cmark_get_arena_mem_allocator());
190
+ Check_Type(rb_text, T_STRING);
202
191
 
203
- str = (char *)RSTRING_PTR(rb_text);
204
- len = RSTRING_LEN(rb_text);
192
+ parser = prepare_parser(rb_options, rb_extensions);
205
193
 
206
- cmark_parser_feed(parser, str, len);
194
+ cmark_parser_feed(parser, StringValuePtr(rb_text), RSTRING_LEN(rb_text));
207
195
  doc = cmark_parser_finish(parser);
196
+
208
197
  if (doc == NULL) {
209
- cmark_arena_reset();
198
+ cmark_parser_free(parser);
210
199
  rb_raise(rb_eNodeError, "error parsing document");
211
200
  }
212
201
 
213
- cmark_mem *default_mem = cmark_get_default_mem_allocator();
214
- xml = cmark_render_xml_with_mem(doc, FIX2INT(rb_options), default_mem);
215
- cmark_arena_reset();
202
+ xml = cmark_render_xml(doc, parser->options);
216
203
 
217
- VALUE ruby_xml = rb_str_new2(xml);
218
- default_mem->free(xml);
204
+ cmark_parser_free(parser);
205
+ cmark_node_free(doc);
219
206
 
220
- return ruby_xml;
207
+ return rb_utf8_str_new_cstr(xml);
221
208
  }
222
209
 
223
210
  /*
@@ -308,18 +295,17 @@ static VALUE rb_node_new(VALUE self, VALUE type) {
308
295
  static VALUE rb_parse_document(VALUE self, VALUE rb_text, VALUE rb_len,
309
296
  VALUE rb_options, VALUE rb_extensions) {
310
297
  char *text;
311
- int len, options;
298
+ int len;
312
299
  cmark_parser *parser;
313
300
  cmark_node *doc;
314
301
  Check_Type(rb_text, T_STRING);
315
302
  Check_Type(rb_len, T_FIXNUM);
316
303
  Check_Type(rb_options, T_FIXNUM);
317
304
 
318
- parser = prepare_parser(rb_options, rb_extensions, cmark_get_default_mem_allocator());
305
+ parser = prepare_parser(rb_options, rb_extensions);
319
306
 
320
307
  text = (char *)RSTRING_PTR(rb_text);
321
308
  len = FIX2INT(rb_len);
322
- options = FIX2INT(rb_options);
323
309
 
324
310
  cmark_parser_feed(parser, text, len);
325
311
  doc = cmark_parser_finish(parser);
@@ -614,7 +600,6 @@ static VALUE rb_render_html(VALUE self, VALUE rb_options, VALUE rb_extensions) {
614
600
  */
615
601
  static VALUE rb_render_xml(VALUE self, VALUE rb_options) {
616
602
  int options;
617
- int i;
618
603
  cmark_node *node;
619
604
  Check_Type(rb_options, T_FIXNUM);
620
605
 
@@ -1270,6 +1255,7 @@ __attribute__((visibility("default"))) void Init_qiita_marker() {
1270
1255
  rb_define_singleton_method(module, "extensions", rb_extensions, 0);
1271
1256
  rb_eNodeError = rb_define_class_under(module, "NodeError", rb_eStandardError);
1272
1257
  rb_cNode = rb_define_class_under(module, "Node", rb_cObject);
1258
+ rb_undef_alloc_func(rb_cNode);
1273
1259
  rb_define_singleton_method(rb_cNode, "markdown_to_html", rb_markdown_to_html,
1274
1260
  3);
1275
1261
  rb_define_singleton_method(rb_cNode, "markdown_to_xml", rb_markdown_to_xml,