qiita_marker 0.23.2.1 → 0.23.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +19 -17
  3. data/README.md +2 -0
  4. data/Rakefile +57 -56
  5. data/bin/qiita_marker +2 -7
  6. data/ext/qiita_marker/autolink.c +57 -10
  7. data/ext/qiita_marker/cmark-gfm_version.h +2 -2
  8. data/ext/qiita_marker/html.c +1 -1
  9. data/ext/qiita_marker/qfm.h +3 -0
  10. data/ext/qiita_marker/qfm_custom_block.c +1 -14
  11. data/ext/qiita_marker/qfm_mention_no_emphasis.c +1 -1
  12. data/ext/qiita_marker/qiita_marker.c +30 -44
  13. data/ext/qiita_marker/scanners.c +2438 -2450
  14. data/ext/qiita_marker/table.c +28 -2
  15. data/lib/qiita_marker/config.rb +5 -3
  16. data/lib/qiita_marker/node/inspect.rb +8 -18
  17. data/lib/qiita_marker/node.rb +6 -6
  18. data/lib/qiita_marker/renderer/html_renderer.rb +39 -39
  19. data/lib/qiita_marker/renderer.rb +5 -5
  20. data/lib/qiita_marker/version.rb +1 -1
  21. data/lib/qiita_marker.rb +9 -11
  22. data/qiita_marker.gemspec +27 -29
  23. metadata +3 -61
  24. data/test/benchmark.rb +0 -32
  25. data/test/fixtures/curly.md +0 -1
  26. data/test/fixtures/dingus.md +0 -10
  27. data/test/fixtures/strong.md +0 -1
  28. data/test/fixtures/table.md +0 -10
  29. data/test/test_attributes.rb +0 -24
  30. data/test/test_basics.rb +0 -35
  31. data/test/test_commands.rb +0 -72
  32. data/test/test_commonmark.rb +0 -36
  33. data/test/test_doc.rb +0 -130
  34. data/test/test_encoding.rb +0 -23
  35. data/test/test_extensions.rb +0 -116
  36. data/test/test_footnotes.rb +0 -60
  37. data/test/test_gc.rb +0 -47
  38. data/test/test_helper.rb +0 -71
  39. data/test/test_linebreaks.rb +0 -15
  40. data/test/test_maliciousness.rb +0 -262
  41. data/test/test_node.rb +0 -89
  42. data/test/test_options.rb +0 -37
  43. data/test/test_pathological_inputs.rb +0 -94
  44. data/test/test_plaintext.rb +0 -46
  45. data/test/test_qfm_code_data_metadata.rb +0 -26
  46. data/test/test_qfm_custom_block.rb +0 -23
  47. data/test/test_qfm_mention_no_emphasis.rb +0 -60
  48. data/test/test_renderer.rb +0 -47
  49. data/test/test_smartpunct.rb +0 -27
  50. data/test/test_spec.rb +0 -30
  51. data/test/test_tasklists.rb +0 -43
  52. data/test/test_xml.rb +0 -107
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0579157ad4abb4038246ef4dc4752fd1de6cd281daa619b2ef42adec5b147982'
4
- data.tar.gz: c671815ff61ab460fcf6c3a42a614018a250c62ceaa41ee0aa3e899f34c12b16
3
+ metadata.gz: 15bfc4813af77558d6c0b4ffbb931229e00d558d0c417048b636ce7c27ac31a7
4
+ data.tar.gz: af9febe461508838d294f9d2d20dfe896c30c467b82b50b36924040c7287c070
5
5
  SHA512:
6
- metadata.gz: 32f16ce193b82d6a7214c851fdd81126d42d872fdd4508b798ccfc4faba4668793274f88f9ef25e61ae57545041d1062c65169b05cd756eec55df0aa042d0140
7
- data.tar.gz: da050452749a3eee8d998db24aa45d6a8b1a282672283e427f8deca374405bfaebe572e954c7906ceb84bea2ff08ad737da05707b2ed5d378158d2738ac0e318
6
+ metadata.gz: 2fc608ddea2a044b4c64b9f32e8dbc44cf838213f6c67e9457f36fa303b7223a20c932a261e3f21fac256ceab34d018b9c6d9757ce86eecf250a3aefa585407b
7
+ data.tar.gz: 66b65a1652e9a0904423490cb8999de85d21928f169f72965ca2b90bc32cfadda46193662ebdae70dea6bcb5819a349256a24911f53c65d168bd9285db107968
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/README.md CHANGED
@@ -20,6 +20,7 @@ In addition to CommonMarker's options and extensions, the following are availabl
20
20
  | Name | Description |
21
21
  | --- | --- |
22
22
  | `:MENTION_NO_EMPHASIS` | Prevent parsing mentions as emphasis. |
23
+ | `:AUTOLINK_CLASS_NAME` | Append `class="autolink"` to extension's autolinks. |
23
24
 
24
25
  #### Render options
25
26
 
@@ -27,6 +28,7 @@ In addition to CommonMarker's options and extensions, the following are availabl
27
28
  | --- | --- |
28
29
  | `:CODE_DATA_METADATA` | Use `<code data-metadata>` for fenced code blocks. |
29
30
  | `:MENTION_NO_EMPHASIS` | Prevent parsing mentions as emphasis. |
31
+ | `:AUTOLINK_CLASS_NAME` | Append `class="autolink"` to extension's autolinks. |
30
32
 
31
33
  ### Original extensions
32
34
 
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]'
@@ -1,5 +1,9 @@
1
1
  #include "autolink.h"
2
+ #include "houdini.h"
3
+ #include "qfm.h"
4
+ #include "scanners.h"
2
5
  #include <parser.h>
6
+ #include <render.h>
3
7
  #include <string.h>
4
8
  #include <utf8.h>
5
9
 
@@ -9,6 +13,11 @@
9
13
  #include <strings.h>
10
14
  #endif
11
15
 
16
+ static void escape_html(cmark_strbuf *dest, const unsigned char *source,
17
+ bufsize_t length) {
18
+ houdini_escape_html0(dest, source, length, 0);
19
+ }
20
+
12
21
  static int is_valid_hostchar(const uint8_t *link, size_t link_len) {
13
22
  int32_t ch;
14
23
  int r = cmark_utf8proc_iterate(link, (bufsize_t)link_len, &ch);
@@ -144,7 +153,8 @@ static size_t check_domain(uint8_t *data, size_t size, int allow_short) {
144
153
  }
145
154
 
146
155
  static cmark_node *www_match(cmark_parser *parser, cmark_node *parent,
147
- cmark_inline_parser *inline_parser) {
156
+ cmark_inline_parser *inline_parser,
157
+ cmark_syntax_extension *ext) {
148
158
  cmark_chunk *chunk = cmark_inline_parser_get_chunk(inline_parser);
149
159
  size_t max_rewind = cmark_inline_parser_get_offset(inline_parser);
150
160
  uint8_t *data = chunk->data + max_rewind;
@@ -176,6 +186,9 @@ static cmark_node *www_match(cmark_parser *parser, cmark_node *parent,
176
186
  cmark_inline_parser_set_offset(inline_parser, (int)(max_rewind + link_end));
177
187
 
178
188
  cmark_node *node = cmark_node_new_with_mem(CMARK_NODE_LINK, parser->mem);
189
+ if (parser->options & CMARK_OPT_AUTOLINK_CLASS_NAME) {
190
+ cmark_node_set_syntax_extension(node, ext);
191
+ }
179
192
 
180
193
  cmark_strbuf buf;
181
194
  cmark_strbuf_init(parser->mem, &buf, 10);
@@ -199,7 +212,8 @@ static cmark_node *www_match(cmark_parser *parser, cmark_node *parent,
199
212
  }
200
213
 
201
214
  static cmark_node *url_match(cmark_parser *parser, cmark_node *parent,
202
- cmark_inline_parser *inline_parser) {
215
+ cmark_inline_parser *inline_parser,
216
+ cmark_syntax_extension *ext) {
203
217
  size_t link_end, domain_len;
204
218
  int rewind = 0;
205
219
 
@@ -237,6 +251,9 @@ static cmark_node *url_match(cmark_parser *parser, cmark_node *parent,
237
251
  cmark_node_unput(parent, rewind);
238
252
 
239
253
  cmark_node *node = cmark_node_new_with_mem(CMARK_NODE_LINK, parser->mem);
254
+ if (parser->options & CMARK_OPT_AUTOLINK_CLASS_NAME) {
255
+ cmark_node_set_syntax_extension(node, ext);
256
+ }
240
257
 
241
258
  cmark_chunk url = cmark_chunk_dup(chunk, max_rewind - rewind,
242
259
  (bufsize_t)(link_end + rewind));
@@ -257,10 +274,10 @@ static cmark_node *match(cmark_syntax_extension *ext, cmark_parser *parser,
257
274
  return NULL;
258
275
 
259
276
  if (c == ':')
260
- return url_match(parser, parent, inline_parser);
277
+ return url_match(parser, parent, inline_parser, ext);
261
278
 
262
279
  if (c == 'w')
263
- return www_match(parser, parent, inline_parser);
280
+ return www_match(parser, parent, inline_parser, ext);
264
281
 
265
282
  return NULL;
266
283
 
@@ -269,7 +286,8 @@ static cmark_node *match(cmark_syntax_extension *ext, cmark_parser *parser,
269
286
  // inline was finished in inlines.c.
270
287
  }
271
288
 
272
- static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset, int depth) {
289
+ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
290
+ int depth, cmark_syntax_extension *ext) {
273
291
  // postprocess_text can recurse very deeply if there is a very long line of
274
292
  // '@' only. Stop at a reasonable depth to ensure it cannot crash.
275
293
  if (depth > 1000) return;
@@ -311,7 +329,7 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
311
329
  }
312
330
 
313
331
  if (rewind == 0 || ns > 0) {
314
- postprocess_text(parser, text, max_rewind + 1 + offset, depth + 1);
332
+ postprocess_text(parser, text, max_rewind + 1 + offset, depth + 1, ext);
315
333
  return;
316
334
  }
317
335
 
@@ -331,20 +349,23 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
331
349
 
332
350
  if (link_end < 2 || nb != 1 || np == 0 ||
333
351
  (!cmark_isalpha(data[link_end - 1]) && data[link_end - 1] != '.')) {
334
- postprocess_text(parser, text, max_rewind + 1 + offset, depth + 1);
352
+ postprocess_text(parser, text, max_rewind + 1 + offset, depth + 1, ext);
335
353
  return;
336
354
  }
337
355
 
338
356
  link_end = autolink_delim(data, link_end);
339
357
 
340
358
  if (link_end == 0) {
341
- postprocess_text(parser, text, max_rewind + 1 + offset, depth + 1);
359
+ postprocess_text(parser, text, max_rewind + 1 + offset, depth + 1, ext);
342
360
  return;
343
361
  }
344
362
 
345
363
  cmark_chunk_to_cstr(parser->mem, &text->as.literal);
346
364
 
347
365
  cmark_node *link_node = cmark_node_new_with_mem(CMARK_NODE_LINK, parser->mem);
366
+ if (parser->options & CMARK_OPT_AUTOLINK_CLASS_NAME) {
367
+ cmark_node_set_syntax_extension(link_node, ext);
368
+ }
348
369
  cmark_strbuf buf;
349
370
  cmark_strbuf_init(parser->mem, &buf, 10);
350
371
  cmark_strbuf_puts(&buf, "mailto:");
@@ -373,7 +394,7 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
373
394
  text->as.literal.len = offset + max_rewind - rewind;
374
395
  text->as.literal.data[text->as.literal.len] = 0;
375
396
 
376
- postprocess_text(parser, post, 0, depth + 1);
397
+ postprocess_text(parser, post, 0, depth + 1, ext);
377
398
  }
378
399
 
379
400
  static cmark_node *postprocess(cmark_syntax_extension *ext, cmark_parser *parser, cmark_node *root) {
@@ -400,7 +421,7 @@ static cmark_node *postprocess(cmark_syntax_extension *ext, cmark_parser *parser
400
421
  }
401
422
 
402
423
  if (ev == CMARK_EVENT_ENTER && node->type == CMARK_NODE_TEXT) {
403
- postprocess_text(parser, node, 0, /*depth*/0);
424
+ postprocess_text(parser, node, 0, /*depth*/ 0, ext);
404
425
  }
405
426
  }
406
427
 
@@ -409,12 +430,38 @@ static cmark_node *postprocess(cmark_syntax_extension *ext, cmark_parser *parser
409
430
  return root;
410
431
  }
411
432
 
433
+ static void html_render(cmark_syntax_extension *extension,
434
+ cmark_html_renderer *renderer, cmark_node *node,
435
+ cmark_event_type ev_type, int options) {
436
+ bool entering = (ev_type == CMARK_EVENT_ENTER);
437
+ cmark_strbuf *html = renderer->html;
438
+
439
+ if (entering) {
440
+ cmark_strbuf_puts(html, "<a href=\"");
441
+ if ((options & CMARK_OPT_UNSAFE) ||
442
+ !(scan_dangerous_url(&node->as.link.url, 0))) {
443
+ houdini_escape_href(html, node->as.link.url.data, node->as.link.url.len);
444
+ }
445
+ if (node->as.link.title.len) {
446
+ cmark_strbuf_puts(html, "\" title=\"");
447
+ escape_html(html, node->as.link.title.data, node->as.link.title.len);
448
+ }
449
+ if (options & CMARK_OPT_AUTOLINK_CLASS_NAME) {
450
+ cmark_strbuf_puts(html, "\" class=\"autolink");
451
+ }
452
+ cmark_strbuf_puts(html, "\">");
453
+ } else {
454
+ cmark_strbuf_puts(html, "</a>");
455
+ }
456
+ }
457
+
412
458
  cmark_syntax_extension *create_autolink_extension(void) {
413
459
  cmark_syntax_extension *ext = cmark_syntax_extension_new("autolink");
414
460
  cmark_llist *special_chars = NULL;
415
461
 
416
462
  cmark_syntax_extension_set_match_inline_func(ext, match);
417
463
  cmark_syntax_extension_set_postprocess_func(ext, postprocess);
464
+ cmark_syntax_extension_set_html_render_func(ext, html_render);
418
465
 
419
466
  cmark_mem *mem = cmark_get_default_mem_allocator();
420
467
  special_chars = cmark_llist_append(mem, special_chars, (void *)':');
@@ -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
@@ -227,7 +227,7 @@ static int S_render_node(cmark_html_renderer *renderer, cmark_node *node,
227
227
  cmark_strbuf_puts(html, "<pre");
228
228
  cmark_html_render_sourcepos(node, html, options);
229
229
  cmark_strbuf_puts(html, "><code data-metadata=\"");
230
- escape_html(html, node->as.code.info.data, first_tag);
230
+ escape_html(html, node->as.code.info.data, node->as.code.info.len);
231
231
  if (first_tag < node->as.code.info.len &&
232
232
  (options & CMARK_OPT_FULL_INFO_STRING)) {
233
233
  cmark_strbuf_puts(html, "\" data-meta=\"");
@@ -12,6 +12,9 @@ extern "C" {
12
12
  /* Prevent parsing Qiita-style Mentions as emphasis. */
13
13
  #define CMARK_OPT_MENTION_NO_EMPHASIS (1 << 26)
14
14
 
15
+ /* Render autolinks with class name */
16
+ #define CMARK_OPT_AUTOLINK_CLASS_NAME (1 << 27)
17
+
15
18
  #ifdef __cplusplus
16
19
  }
17
20
  #endif
@@ -157,20 +157,7 @@ static int can_contain(cmark_syntax_extension *self, cmark_node *node,
157
157
  cmark_node_type child_type) {
158
158
  cmark_node_type node_type = cmark_node_get_type(node);
159
159
 
160
- if (node_type == CMARK_NODE_QFM_CUSTOM_BLOCK) {
161
- return
162
- // Block
163
- child_type == CMARK_NODE_LIST || child_type == CMARK_NODE_PARAGRAPH ||
164
- // Inline
165
- child_type == CMARK_NODE_TEXT || child_type == CMARK_NODE_CODE ||
166
- child_type == CMARK_NODE_HTML_INLINE || child_type == CMARK_NODE_EMPH ||
167
- child_type == CMARK_NODE_STRONG || child_type == CMARK_NODE_LINK ||
168
- child_type == CMARK_NODE_IMAGE ||
169
- child_type == CMARK_NODE_FOOTNOTE_REFERENCE ||
170
- child_type == CMARK_NODE_STRIKETHROUGH;
171
- }
172
-
173
- return 0;
160
+ return node_type == CMARK_NODE_QFM_CUSTOM_BLOCK;
174
161
  }
175
162
 
176
163
  static int contains_inlines(cmark_syntax_extension *self, cmark_node *node) {
@@ -1,5 +1,5 @@
1
- #include "cmark_ctype.h"
2
1
  #include "cmark-gfm.h"
2
+ #include "cmark_ctype.h"
3
3
  #include "config.h"
4
4
 
5
5
  static bool is_wordchar(char c) {