commonmarker 0.19.0 → 0.21.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of commonmarker might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/README.md +2 -3
- data/Rakefile +16 -4
- data/bin/commonmarker +82 -44
- data/commonmarker.gemspec +9 -12
- data/ext/commonmarker/blocks.c +89 -29
- data/ext/commonmarker/buffer.c +0 -1
- data/ext/commonmarker/chunk.h +0 -1
- data/ext/commonmarker/cmark-gfm-core-extensions.h +24 -1
- data/ext/commonmarker/cmark-gfm.h +14 -8
- data/ext/commonmarker/cmark-gfm_version.h +2 -2
- data/ext/commonmarker/commonmark.c +9 -4
- data/ext/commonmarker/commonmarker.c +120 -78
- data/ext/commonmarker/html.c +4 -4
- data/ext/commonmarker/inlines.c +21 -14
- data/ext/commonmarker/iterator.h +0 -1
- data/ext/commonmarker/map.h +0 -1
- data/ext/commonmarker/node.h +2 -0
- data/ext/commonmarker/parser.h +2 -1
- data/ext/commonmarker/render.c +16 -14
- data/ext/commonmarker/render.h +0 -1
- data/ext/commonmarker/scanners.c +777 -951
- data/ext/commonmarker/scanners.h +0 -2
- data/ext/commonmarker/table.c +52 -13
- data/ext/commonmarker/tasklist.c +34 -13
- data/lib/commonmarker.rb +5 -4
- data/lib/commonmarker/config.rb +5 -4
- data/lib/commonmarker/node.rb +1 -1
- data/lib/commonmarker/node/inspect.rb +12 -12
- data/lib/commonmarker/renderer.rb +7 -7
- data/lib/commonmarker/renderer/html_renderer.rb +22 -35
- data/lib/commonmarker/version.rb +1 -1
- data/test/benchmark.rb +1 -5
- data/test/fixtures/strong.md +1 -0
- data/test/fixtures/table.md +10 -0
- data/test/test_attributes.rb +3 -3
- data/test/test_commands.rb +31 -0
- data/test/test_commonmark.rb +11 -11
- data/test/test_encoding.rb +1 -2
- data/test/test_extensions.rb +40 -52
- data/test/test_footnotes.rb +9 -9
- data/test/test_gc.rb +2 -0
- data/test/test_helper.rb +15 -8
- data/test/test_maliciousness.rb +192 -190
- data/test/test_node.rb +10 -12
- data/test/test_options.rb +15 -15
- data/test/test_pathological_inputs.rb +2 -2
- data/test/test_plaintext.rb +21 -21
- data/test/test_renderer.rb +9 -9
- data/test/test_spec.rb +3 -2
- data/test/test_tasklists.rb +22 -6
- metadata +51 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1a1380e99f120ae24a27bae6244ffeab5b0b3fe828155828cf8c092d8c83471a
|
4
|
+
data.tar.gz: 92c85125c0e4d6f8673312e64e67feda6993a4fc1250661fad3714836bc96454
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f136c3413348cea8e3a0f3e8b0242ffc8bba92b9004278170ee7d2532e87b6c5d6af73c952d2c31d509143ae2cfe63d96aeca6ff4749a599fefbcad7580214e
|
7
|
+
data.tar.gz: 4d33d9cb161d0b484ed9bc353c9c01dd3f8715f533c05a2f7f61a16792433153d19324d1b62a0ae6b6750441917843495349a1140e93d2b1960794ea0346e444
|
data/README.md
CHANGED
@@ -112,10 +112,8 @@ class MyHtmlRenderer < CommonMarker::HtmlRenderer
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
-
# this renderer prints directly to STDOUT, instead
|
116
|
-
# of returning a string
|
117
115
|
myrenderer = MyHtmlRenderer.new
|
118
|
-
|
116
|
+
puts myrenderer.render(doc)
|
119
117
|
|
120
118
|
# Print any warnings to STDERR
|
121
119
|
renderer.warnings.each do |w|
|
@@ -176,6 +174,7 @@ Both `render_html` and `render_doc` take an optional third argument defining the
|
|
176
174
|
The available extensions are:
|
177
175
|
|
178
176
|
* `:table` - This provides support for tables.
|
177
|
+
* `:tasklist` - This provides support for task list items.
|
179
178
|
* `:strikethrough` - This provides support for strikethroughs.
|
180
179
|
* `:autolink` - This provides support for automatically converting URLs to anchor tags.
|
181
180
|
* `:tagfilter` - This escapes [several "unsafe" HTML tags](https://github.github.com/gfm/#disallowed-raw-html-extension-), causing them to not have any effect.
|
data/Rakefile
CHANGED
@@ -5,7 +5,6 @@ require 'rake/clean'
|
|
5
5
|
require 'rake/extensiontask'
|
6
6
|
require 'digest/md5'
|
7
7
|
|
8
|
-
|
9
8
|
host_os = RbConfig::CONFIG['host_os']
|
10
9
|
require 'devkit' if host_os == 'mingw32'
|
11
10
|
|
@@ -36,7 +35,7 @@ end
|
|
36
35
|
task 'test:unit' => :compile
|
37
36
|
|
38
37
|
desc 'Run unit and conformance tests'
|
39
|
-
task test: %w
|
38
|
+
task test: %w[test:unit]
|
40
39
|
|
41
40
|
require 'rubocop/rake_task'
|
42
41
|
|
@@ -47,7 +46,7 @@ task :benchmark do
|
|
47
46
|
if ENV['FETCH_PROGIT']
|
48
47
|
`rm -rf test/progit`
|
49
48
|
`git clone https://github.com/progit/progit.git test/progit`
|
50
|
-
langs = %w
|
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]
|
51
50
|
langs.each do |lang|
|
52
51
|
`cat test/progit/#{lang}/*/*.markdown >> test/benchinput.md`
|
53
52
|
end
|
@@ -77,13 +76,26 @@ RDoc::Task.new do |rd|
|
|
77
76
|
rd.options << '--fileboxes'
|
78
77
|
end
|
79
78
|
|
79
|
+
desc 'Generate the documentation and run a web server'
|
80
|
+
task serve: [:rdoc] do
|
81
|
+
require 'webrick'
|
82
|
+
|
83
|
+
puts 'Navigate to http://localhost:3000 to see the docs'
|
84
|
+
|
85
|
+
server = WEBrick::HTTPServer.new Port: 3000
|
86
|
+
server.mount '/', WEBrick::HTTPServlet::FileHandler, 'docs'
|
87
|
+
trap('INT') { server.stop }
|
88
|
+
server.start
|
89
|
+
end
|
90
|
+
|
80
91
|
desc 'Generate and publish docs to gh-pages'
|
81
92
|
task publish: [:rdoc] do
|
93
|
+
require 'tmpdir'
|
82
94
|
require 'shellwords'
|
83
95
|
|
84
96
|
Dir.mktmpdir do |tmp|
|
85
97
|
system "mv docs/* #{tmp}"
|
86
|
-
system 'git checkout gh-pages'
|
98
|
+
system 'git checkout origin/gh-pages'
|
87
99
|
system 'rm -rf *'
|
88
100
|
system "mv #{tmp}/* ."
|
89
101
|
message = Shellwords.escape("Site updated at #{Time.now.utc}")
|
data/bin/commonmarker
CHANGED
@@ -1,60 +1,98 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
# If no FILE argument is provided, text will be read from STDIN.
|
7
|
-
# With --html-renderer, use the HtmlRenderer renderer rather than the native C
|
8
|
-
# renderer.
|
9
|
-
# With --extension=EXTENSION, EXTENSION will be used for parsing, and HTML
|
10
|
-
# output unless --html-renderer is specified.
|
11
|
-
if ARGV.include?('--help') or ARGV.include?('-h')
|
12
|
-
File.read(__FILE__).split("\n").grep(/^# /).each do |line|
|
13
|
-
puts line[2..-1]
|
14
|
-
end
|
15
|
-
exit 0
|
16
|
-
end
|
4
|
+
require 'optparse'
|
5
|
+
require 'ostruct'
|
17
6
|
|
18
7
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
19
8
|
require 'commonmarker'
|
20
9
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
10
|
+
root = File.expand_path('..', __dir__)
|
11
|
+
$LOAD_PATH.unshift File.expand_path('lib', root)
|
12
|
+
|
13
|
+
def parse_options
|
14
|
+
options = OpenStruct.new
|
15
|
+
extensions = CommonMarker.extensions
|
16
|
+
parse_options = CommonMarker::Config::Parse
|
17
|
+
render_options = CommonMarker::Config::Render
|
18
|
+
|
19
|
+
options.active_extensions = []
|
20
|
+
options.active_parse_options = [:DEFAULT]
|
21
|
+
options.active_render_options = [:DEFAULT]
|
22
|
+
|
23
|
+
option_parser = OptionParser.new do |opts|
|
24
|
+
opts.banner = 'Usage: commonmarker [--html-renderer] [--extension=EXTENSION]'
|
25
|
+
opts.separator ' [--parse-option=OPTION]'
|
26
|
+
opts.separator ' [--render-option=OPTION]'
|
27
|
+
opts.separator ' [FILE..]'
|
28
|
+
opts.separator ''
|
29
|
+
opts.separator 'Convert one or more CommonMark files to HTML and write to standard output.'
|
30
|
+
opts.separator 'If no FILE argument is provided, text will be read from STDIN.'
|
31
|
+
opts.separator ''
|
32
|
+
|
33
|
+
opts.on('--extension=EXTENSION', Array, 'Use EXTENSION for parsing and HTML output (unless --html-renderer is specified)') do |values|
|
34
|
+
values.each do |value|
|
35
|
+
if extensions.include?(value)
|
36
|
+
options.active_extensions << value.to_sym
|
37
|
+
else
|
38
|
+
abort("extension '#{value}' not found")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on('-h', '--help', 'Prints this help') do
|
44
|
+
puts opts
|
45
|
+
puts
|
46
|
+
puts "Available extentions: #{extensions.join(', ')}"
|
47
|
+
puts "Available parse options: #{parse_options.keys.join(', ')}"
|
48
|
+
puts "Available render options: #{render_options.keys.join(', ')}"
|
49
|
+
puts
|
50
|
+
puts 'See the README for more information on these.'
|
51
|
+
exit
|
52
|
+
end
|
25
53
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
54
|
+
opts.on('--html-renderer', 'Use the HtmlRenderer renderer rather than the native C renderer') do
|
55
|
+
options.renderer = true
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.on('--parse-option=OPTION', Array, 'OPTION passed during parsing') do |values|
|
59
|
+
values.each do |value|
|
60
|
+
if parse_options.key?(value.to_sym)
|
61
|
+
options.active_parse_options << value.to_sym
|
62
|
+
else
|
63
|
+
abort("parse-option '#{value}' not found")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
opts.on('--render-option=OPTION', Array, 'OPTION passed during rendering') do |values|
|
69
|
+
values.each do |value|
|
70
|
+
if render_options.key?(value.to_sym)
|
71
|
+
options.active_render_options << value.to_sym
|
72
|
+
else
|
73
|
+
abort("render-option '#{value}' not found")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
opts.on('-v', '--version', 'Version information') do
|
79
|
+
puts "commonmarker #{CommonMarker::VERSION}"
|
80
|
+
exit
|
46
81
|
end
|
47
|
-
true
|
48
|
-
else
|
49
|
-
false
|
50
82
|
end
|
83
|
+
|
84
|
+
option_parser.parse!
|
85
|
+
|
86
|
+
options
|
51
87
|
end
|
52
88
|
|
53
|
-
|
89
|
+
options = parse_options
|
90
|
+
|
91
|
+
doc = CommonMarker.render_doc(ARGF.read, options.active_parse_options, options.active_extensions)
|
54
92
|
|
55
|
-
if renderer
|
56
|
-
renderer = CommonMarker::HtmlRenderer.new(extensions: active_extensions)
|
93
|
+
if options.renderer
|
94
|
+
renderer = CommonMarker::HtmlRenderer.new(extensions: options.active_extensions)
|
57
95
|
STDOUT.write(renderer.render(doc))
|
58
96
|
else
|
59
|
-
STDOUT.write(doc.to_html(
|
97
|
+
STDOUT.write(doc.to_html(options.active_render_options, options.active_extensions))
|
60
98
|
end
|
data/commonmarker.gemspec
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
|
-
lib = File.expand_path('
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
5
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
5
|
require 'commonmarker/version'
|
7
6
|
|
@@ -10,32 +9,30 @@ Gem::Specification.new do |s|
|
|
10
9
|
s.version = CommonMarker::VERSION
|
11
10
|
s.summary = 'CommonMark parser and renderer. Written in C, wrapped in Ruby.'
|
12
11
|
s.description = 'A fast, safe, extensible parser for CommonMark. This wraps the official libcmark library.'
|
13
|
-
s.authors
|
12
|
+
s.authors = ['Garen Torikian', 'Ashe Connor']
|
14
13
|
s.homepage = 'https://github.com/gjtorikian/commonmarker'
|
15
14
|
s.license = 'MIT'
|
16
|
-
s.required_ruby_version = '>= 2.0.0'
|
17
15
|
|
18
|
-
s.files = %w
|
16
|
+
s.files = %w[LICENSE.txt README.md Rakefile commonmarker.gemspec bin/commonmarker]
|
19
17
|
s.files += Dir.glob('lib/**/*.rb')
|
20
18
|
s.files += Dir.glob('ext/commonmarker/*.*')
|
21
|
-
s.test_files = Dir.glob('test/**/*')
|
19
|
+
s.test_files = Dir.glob('test/**/*').reject { |f| f == 'test/benchinput.md' || f.start_with?('test/progit/') }
|
22
20
|
s.extensions = ['ext/commonmarker/extconf.rb']
|
23
21
|
|
24
|
-
s.test_files = s.files.grep(%r{^test/})
|
25
22
|
s.executables = ['commonmarker']
|
26
|
-
s.require_paths = %w
|
23
|
+
s.require_paths = %w[lib ext]
|
27
24
|
|
28
25
|
s.rdoc_options += ['-x', 'ext/commonmarker/cmark/.*']
|
29
26
|
|
30
27
|
s.add_dependency 'ruby-enum', '~> 0.5'
|
31
28
|
|
29
|
+
s.add_development_dependency 'awesome_print'
|
30
|
+
s.add_development_dependency 'json', '~> 2.3'
|
32
31
|
s.add_development_dependency 'minitest', '~> 5.6'
|
33
32
|
s.add_development_dependency 'minitest-focus', '~> 1.1'
|
34
|
-
s.add_development_dependency 'rake-compiler', '~> 0.9'
|
35
|
-
s.add_development_dependency 'json', '~> 1.8.1'
|
36
|
-
s.add_development_dependency 'awesome_print'
|
37
33
|
s.add_development_dependency 'rake'
|
38
|
-
s.add_development_dependency '
|
34
|
+
s.add_development_dependency 'rake-compiler', '~> 0.9'
|
35
|
+
s.add_development_dependency 'rdoc', '~> 6.2'
|
39
36
|
s.add_development_dependency 'rubocop'
|
40
37
|
s.add_development_dependency 'rubocop-standard'
|
41
38
|
end
|
data/ext/commonmarker/blocks.c
CHANGED
@@ -36,6 +36,10 @@ static bool S_last_line_blank(const cmark_node *node) {
|
|
36
36
|
return (node->flags & CMARK_NODE__LAST_LINE_BLANK) != 0;
|
37
37
|
}
|
38
38
|
|
39
|
+
static bool S_last_line_checked(const cmark_node *node) {
|
40
|
+
return (node->flags & CMARK_NODE__LAST_LINE_CHECKED) != 0;
|
41
|
+
}
|
42
|
+
|
39
43
|
static CMARK_INLINE cmark_node_type S_type(const cmark_node *node) {
|
40
44
|
return (cmark_node_type)node->type;
|
41
45
|
}
|
@@ -47,6 +51,10 @@ static void S_set_last_line_blank(cmark_node *node, bool is_blank) {
|
|
47
51
|
node->flags &= ~CMARK_NODE__LAST_LINE_BLANK;
|
48
52
|
}
|
49
53
|
|
54
|
+
static void S_set_last_line_checked(cmark_node *node) {
|
55
|
+
node->flags |= CMARK_NODE__LAST_LINE_CHECKED;
|
56
|
+
}
|
57
|
+
|
50
58
|
static CMARK_INLINE bool S_is_line_end_char(char c) {
|
51
59
|
return (c == '\n' || c == '\r');
|
52
60
|
}
|
@@ -121,8 +129,6 @@ static void cmark_parser_reset(cmark_parser *parser) {
|
|
121
129
|
parser->root = document;
|
122
130
|
parser->current = document;
|
123
131
|
|
124
|
-
parser->last_buffer_ended_with_cr = false;
|
125
|
-
|
126
132
|
parser->syntax_extensions = saved_exts;
|
127
133
|
parser->inline_syntax_extensions = saved_inline_exts;
|
128
134
|
parser->options = saved_options;
|
@@ -234,19 +240,35 @@ static void remove_trailing_blank_lines(cmark_strbuf *ln) {
|
|
234
240
|
|
235
241
|
// Check to see if a node ends with a blank line, descending
|
236
242
|
// if needed into lists and sublists.
|
237
|
-
static bool
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
}
|
243
|
+
static bool S_ends_with_blank_line(cmark_node *node) {
|
244
|
+
if (S_last_line_checked(node)) {
|
245
|
+
return(S_last_line_blank(node));
|
246
|
+
} else if ((S_type(node) == CMARK_NODE_LIST ||
|
247
|
+
S_type(node) == CMARK_NODE_ITEM) && node->last_child) {
|
248
|
+
S_set_last_line_checked(node);
|
249
|
+
return(S_ends_with_blank_line(node->last_child));
|
250
|
+
} else {
|
251
|
+
S_set_last_line_checked(node);
|
252
|
+
return (S_last_line_blank(node));
|
248
253
|
}
|
249
|
-
|
254
|
+
}
|
255
|
+
|
256
|
+
// returns true if content remains after link defs are resolved.
|
257
|
+
static bool resolve_reference_link_definitions(
|
258
|
+
cmark_parser *parser,
|
259
|
+
cmark_node *b) {
|
260
|
+
bufsize_t pos;
|
261
|
+
cmark_strbuf *node_content = &b->content;
|
262
|
+
cmark_chunk chunk = {node_content->ptr, node_content->size, 0};
|
263
|
+
while (chunk.len && chunk.data[0] == '[' &&
|
264
|
+
(pos = cmark_parse_reference_inline(parser->mem, &chunk,
|
265
|
+
parser->refmap))) {
|
266
|
+
|
267
|
+
chunk.data += pos;
|
268
|
+
chunk.len -= pos;
|
269
|
+
}
|
270
|
+
cmark_strbuf_drop(node_content, (node_content->size - chunk.len));
|
271
|
+
return !is_blank(&b->content, 0);
|
250
272
|
}
|
251
273
|
|
252
274
|
static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
|
@@ -254,6 +276,7 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
|
|
254
276
|
cmark_node *item;
|
255
277
|
cmark_node *subitem;
|
256
278
|
cmark_node *parent;
|
279
|
+
bool has_content;
|
257
280
|
|
258
281
|
parent = b->parent;
|
259
282
|
assert(b->flags &
|
@@ -283,15 +306,8 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
|
|
283
306
|
switch (S_type(b)) {
|
284
307
|
case CMARK_NODE_PARAGRAPH:
|
285
308
|
{
|
286
|
-
|
287
|
-
|
288
|
-
(pos = cmark_parse_reference_inline(parser->mem, &chunk, parser->refmap))) {
|
289
|
-
|
290
|
-
chunk.data += pos;
|
291
|
-
chunk.len -= pos;
|
292
|
-
}
|
293
|
-
cmark_strbuf_drop(node_content, (node_content->size - chunk.len));
|
294
|
-
if (is_blank(node_content, 0)) {
|
309
|
+
has_content = resolve_reference_link_definitions(parser, b);
|
310
|
+
if (!has_content) {
|
295
311
|
// remove blank node (former reference def)
|
296
312
|
cmark_node_free(b);
|
297
313
|
}
|
@@ -343,7 +359,8 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
|
|
343
359
|
// spaces between them:
|
344
360
|
subitem = item->first_child;
|
345
361
|
while (subitem) {
|
346
|
-
if (
|
362
|
+
if ((item->next || subitem->next) &&
|
363
|
+
S_ends_with_blank_line(subitem)) {
|
347
364
|
b->as.list.tight = false;
|
348
365
|
break;
|
349
366
|
}
|
@@ -748,6 +765,40 @@ static void chop_trailing_hashtags(cmark_chunk *ch) {
|
|
748
765
|
}
|
749
766
|
}
|
750
767
|
|
768
|
+
// Check for thematic break. On failure, return 0 and update
|
769
|
+
// thematic_break_kill_pos with the index at which the
|
770
|
+
// parse fails. On success, return length of match.
|
771
|
+
// "...three or more hyphens, asterisks,
|
772
|
+
// or underscores on a line by themselves. If you wish, you may use
|
773
|
+
// spaces between the hyphens or asterisks."
|
774
|
+
static int S_scan_thematic_break(cmark_parser *parser, cmark_chunk *input,
|
775
|
+
bufsize_t offset) {
|
776
|
+
bufsize_t i;
|
777
|
+
char c;
|
778
|
+
char nextc = '\0';
|
779
|
+
int count;
|
780
|
+
i = offset;
|
781
|
+
c = peek_at(input, i);
|
782
|
+
if (!(c == '*' || c == '_' || c == '-')) {
|
783
|
+
parser->thematic_break_kill_pos = i;
|
784
|
+
return 0;
|
785
|
+
}
|
786
|
+
count = 1;
|
787
|
+
while ((nextc = peek_at(input, ++i))) {
|
788
|
+
if (nextc == c) {
|
789
|
+
count++;
|
790
|
+
} else if (nextc != ' ' && nextc != '\t') {
|
791
|
+
break;
|
792
|
+
}
|
793
|
+
}
|
794
|
+
if (count >= 3 && (nextc == '\r' || nextc == '\n')) {
|
795
|
+
return (i - offset) + 1;
|
796
|
+
} else {
|
797
|
+
parser->thematic_break_kill_pos = i;
|
798
|
+
return 0;
|
799
|
+
}
|
800
|
+
}
|
801
|
+
|
751
802
|
// Find first nonspace character from current offset, setting
|
752
803
|
// parser->first_nonspace, parser->first_nonspace_column,
|
753
804
|
// parser->indent, and parser->blank. Does not advance parser->offset.
|
@@ -1040,6 +1091,7 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
|
|
1040
1091
|
bufsize_t matched = 0;
|
1041
1092
|
int lev = 0;
|
1042
1093
|
bool save_partially_consumed_tab;
|
1094
|
+
bool has_content;
|
1043
1095
|
int save_offset;
|
1044
1096
|
int save_column;
|
1045
1097
|
|
@@ -1112,13 +1164,20 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
|
|
1112
1164
|
} else if (!indented && cont_type == CMARK_NODE_PARAGRAPH &&
|
1113
1165
|
(lev =
|
1114
1166
|
scan_setext_heading_line(input, parser->first_nonspace))) {
|
1115
|
-
|
1116
|
-
(*container)
|
1117
|
-
|
1118
|
-
|
1167
|
+
// finalize paragraph, resolving reference links
|
1168
|
+
has_content = resolve_reference_link_definitions(parser, *container);
|
1169
|
+
|
1170
|
+
if (has_content) {
|
1171
|
+
|
1172
|
+
(*container)->type = (uint16_t)CMARK_NODE_HEADING;
|
1173
|
+
(*container)->as.heading.level = lev;
|
1174
|
+
(*container)->as.heading.setext = true;
|
1175
|
+
S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
|
1176
|
+
}
|
1119
1177
|
} else if (!indented &&
|
1120
1178
|
!(cont_type == CMARK_NODE_PARAGRAPH && !all_matched) &&
|
1121
|
-
|
1179
|
+
(parser->thematic_break_kill_pos <= parser->first_nonspace) &&
|
1180
|
+
(matched = S_scan_thematic_break(parser, input, parser->first_nonspace))) {
|
1122
1181
|
// it's only now that we know the line is not part of a setext heading:
|
1123
1182
|
*container = add_child(parser, *container, CMARK_NODE_THEMATIC_BREAK,
|
1124
1183
|
parser->first_nonspace + 1);
|
@@ -1377,6 +1436,7 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
|
|
1377
1436
|
parser->column = 0;
|
1378
1437
|
parser->first_nonspace = 0;
|
1379
1438
|
parser->first_nonspace_column = 0;
|
1439
|
+
parser->thematic_break_kill_pos = 0;
|
1380
1440
|
parser->indent = 0;
|
1381
1441
|
parser->blank = false;
|
1382
1442
|
parser->partially_consumed_tab = false;
|