devcenter-parser 2.2.5 → 2.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +14 -14
- data/devcenter-parser.gemspec +2 -2
- data/lib/devcenter-parser.rb +15 -10
- data/lib/devcenter-parser/github_parser.rb +1 -1
- data/lib/devcenter-parser/header_id_generator.rb +7 -1
- data/lib/devcenter-parser/version.rb +1 -1
- data/test/devcenter-parser_test.rb +53 -12
- data/test/header_id_generator_test.rb +6 -0
- metadata +10 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfd75f1b30669185f61feb1051ca91a23a19e6552b4a8f14c6ec60a57205f858
|
4
|
+
data.tar.gz: 13929cf26ab3771a28e7f887f0a70dd2e6bf79a922259284c5874da8bff65816
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 699004a8938e09580e9f3a3d5f355d88dbea868b207992400d299e1ec073d29ebd3ccf2ff7fb3b42d00ea9da8aa5386d268c8b05a028ea50635f18afec04922b
|
7
|
+
data.tar.gz: 1c0a5f037d378b78315e1497cac388074aae7fa3c391b510768eb0ee683b35ac10aec7936bb0b212df15f275727cf4b265ef43eb48c2cc04b1b6b3c056f880f2
|
data/Gemfile.lock
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
devcenter-parser (2.2.
|
4
|
+
devcenter-parser (2.2.10)
|
5
5
|
nokogiri (>= 1.7.1)
|
6
|
-
redcarpet (= 3.
|
7
|
-
sanitize (~>
|
6
|
+
redcarpet (= 3.5.0)
|
7
|
+
sanitize (~> 5.2.1)
|
8
8
|
|
9
9
|
GEM
|
10
10
|
remote: http://rubygems.org/
|
11
11
|
specs:
|
12
|
-
crass (1.0.
|
13
|
-
mini_portile2 (2.
|
12
|
+
crass (1.0.6)
|
13
|
+
mini_portile2 (2.4.0)
|
14
14
|
minitest (5.10.1)
|
15
|
-
nokogiri (1.
|
16
|
-
mini_portile2 (~> 2.
|
17
|
-
nokogumbo (
|
18
|
-
nokogiri
|
15
|
+
nokogiri (1.10.10)
|
16
|
+
mini_portile2 (~> 2.4.0)
|
17
|
+
nokogumbo (2.0.2)
|
18
|
+
nokogiri (~> 1.8, >= 1.8.4)
|
19
19
|
rake (12.0.0)
|
20
|
-
redcarpet (3.
|
21
|
-
sanitize (
|
20
|
+
redcarpet (3.5.0)
|
21
|
+
sanitize (5.2.1)
|
22
22
|
crass (~> 1.0.2)
|
23
|
-
nokogiri (>= 1.
|
24
|
-
nokogumbo (~>
|
23
|
+
nokogiri (>= 1.8.0)
|
24
|
+
nokogumbo (~> 2.0)
|
25
25
|
|
26
26
|
PLATFORMS
|
27
27
|
ruby
|
@@ -32,4 +32,4 @@ DEPENDENCIES
|
|
32
32
|
rake
|
33
33
|
|
34
34
|
BUNDLED WITH
|
35
|
-
1.
|
35
|
+
1.17.2
|
data/devcenter-parser.gemspec
CHANGED
@@ -15,8 +15,8 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.require_paths = %w{ lib }
|
16
16
|
|
17
17
|
gem.add_runtime_dependency 'nokogiri', '>= 1.7.1'
|
18
|
-
gem.add_runtime_dependency 'redcarpet', '3.
|
19
|
-
gem.add_runtime_dependency 'sanitize', '~>
|
18
|
+
gem.add_runtime_dependency 'redcarpet', '3.5.0'
|
19
|
+
gem.add_runtime_dependency 'sanitize', '~>5.2.1'
|
20
20
|
|
21
21
|
gem.add_development_dependency 'minitest', '>2.0'
|
22
22
|
gem.add_development_dependency 'rake'
|
data/lib/devcenter-parser.rb
CHANGED
@@ -10,14 +10,14 @@ module DevcenterParser
|
|
10
10
|
class InvalidMarkdownError < Exception; end
|
11
11
|
class InvalidRawHTMLError < Exception; end
|
12
12
|
|
13
|
-
def self.to_html(markdown)
|
14
|
-
sanitize to_unsanitized_html(markdown)
|
13
|
+
def self.to_html(markdown, options = {})
|
14
|
+
sanitize to_unsanitized_html(markdown, options)
|
15
15
|
end
|
16
16
|
|
17
|
-
def self.to_unsanitized_html(markdown)
|
17
|
+
def self.to_unsanitized_html(markdown, options = {})
|
18
18
|
markdown = normalize_markdown(markdown)
|
19
19
|
doc = GitHubParser.parse(markdown)
|
20
|
-
doc_to_html(doc)
|
20
|
+
doc_to_html(doc, options)
|
21
21
|
rescue InvalidRawHTMLError => e
|
22
22
|
raise InvalidMarkdownError, e.message
|
23
23
|
end
|
@@ -28,9 +28,9 @@ module DevcenterParser
|
|
28
28
|
|
29
29
|
private
|
30
30
|
|
31
|
-
def self.doc_to_html(doc)
|
31
|
+
def self.doc_to_html(doc, options = {})
|
32
32
|
HeaderIdGenerator.apply!(doc)
|
33
|
-
convert_to_article_links_all_relative_links_with_missing_initial_slashes(doc)
|
33
|
+
convert_to_article_links_all_relative_links_with_missing_initial_slashes(doc, options)
|
34
34
|
html = doc.to_html(:encoding => 'utf-8')
|
35
35
|
verify_raw_html(html)
|
36
36
|
html
|
@@ -92,10 +92,15 @@ module DevcenterParser
|
|
92
92
|
@@sanitize_config = config.merge({remove_contents: true, allow_comments: true})
|
93
93
|
end
|
94
94
|
|
95
|
-
def self.convert_to_article_links_all_relative_links_with_missing_initial_slashes(doc)
|
95
|
+
def self.convert_to_article_links_all_relative_links_with_missing_initial_slashes(doc, options = {})
|
96
|
+
link_prefix = options[:link_prefix] || '/articles'
|
96
97
|
doc.css('a').each do |node|
|
97
|
-
|
98
|
-
|
98
|
+
next if node['href'].nil? || node['href'] =~ /\Ahttp|\A\/|\Amailto\:|\A#/
|
99
|
+
|
100
|
+
if node['href'].start_with? 'categories/'
|
101
|
+
node['href'] = "/#{node['href']}"
|
102
|
+
else
|
103
|
+
node['href'] = "#{link_prefix}/#{node['href']}".gsub('/articles/articles/', '/articles/')
|
99
104
|
end
|
100
105
|
end
|
101
106
|
end
|
@@ -124,7 +129,7 @@ module DevcenterParser
|
|
124
129
|
end
|
125
130
|
|
126
131
|
def self.iframe_has_invalid_src?(node)
|
127
|
-
node.attributes['src'].value !~
|
132
|
+
node.attributes['src'].value !~ /https:\/\/player.vimeo.com(.+)(&|\?)dnt=true/i && node.attributes['src'].value !~ /\Ahttps:\/\/www\.youtube-nocookie\.com\/embed/i
|
128
133
|
end
|
129
134
|
|
130
135
|
def self.iframe?(node)
|
@@ -72,7 +72,13 @@ class HeaderIdGenerator
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def add_default_ids
|
75
|
-
@nodes_ids.each
|
75
|
+
@nodes_ids.each do |node, _|
|
76
|
+
if node['id'].to_s.empty?
|
77
|
+
@nodes_ids[node] = subheader_id(node.content)
|
78
|
+
else
|
79
|
+
@nodes_ids[node] = node['id']
|
80
|
+
end
|
81
|
+
end
|
76
82
|
end
|
77
83
|
|
78
84
|
def subheader_id(content)
|
@@ -18,6 +18,10 @@ describe 'DevcenterParser' do
|
|
18
18
|
assert_parsing_unsanitized_result '<toolbelt />', '<p><toolbelt></toolbelt></p>'
|
19
19
|
end
|
20
20
|
|
21
|
+
it 'keeps html entities' do
|
22
|
+
assert_parsing_unsanitized_result '<p> </p>', '<p> </p>'
|
23
|
+
end
|
24
|
+
|
21
25
|
end
|
22
26
|
|
23
27
|
describe '.to_html' do
|
@@ -26,6 +30,10 @@ describe 'DevcenterParser' do
|
|
26
30
|
assert_parsing_result nil, ''
|
27
31
|
end
|
28
32
|
|
33
|
+
it 'keeps html entities' do
|
34
|
+
assert_parsing_result '<p> </p>', '<p> </p>'
|
35
|
+
end
|
36
|
+
|
29
37
|
it 'does not create <em>s inside words' do
|
30
38
|
assert_parsing_result 'foo_bar_baz', '<p>foo_bar_baz</p>'
|
31
39
|
end
|
@@ -42,11 +50,31 @@ describe 'DevcenterParser' do
|
|
42
50
|
assert_parsing_result md, html
|
43
51
|
end
|
44
52
|
|
45
|
-
it 'allows embedding vimeo videos' do
|
46
|
-
src = '<iframe src="https://player.vimeo.com/video/
|
53
|
+
it 'allows embedding vimeo videos when their do-no-track param is set to true' do
|
54
|
+
src = '<iframe src="https://player.vimeo.com/video/143343818?api=1&dnt=true&title=foo" width="50" height="281" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>'
|
55
|
+
assert_parsing_result src, src
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'allows embedding youtube videos from its no-cookies domain' do
|
59
|
+
src = '<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/123456ABCDEF" frameborder="0" allowfullscreen=""></iframe>'
|
47
60
|
assert_parsing_result src, src
|
48
61
|
end
|
49
62
|
|
63
|
+
it 'removes youtube videos embedded from the with-cookies domain' do
|
64
|
+
src = '<iframe width="560" height="315" src="https://www.youtube.com/embed/123456ABCDEF" frameborder="0" allowfullscreen=""></iframe>'
|
65
|
+
assert_parsing_result src, ''
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'does not allow embedding vimeo videos when their do-no-track param is set to something different than true' do
|
69
|
+
src = '<iframe src="https://player.vimeo.com/video/143343818?api=1&dnt=foo&title=foo" width="50" height="281" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>'
|
70
|
+
assert_parsing_result src, ''
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'does not allow embedding vimeo videos when their do-no-track param is not passed' do
|
74
|
+
src = '<iframe src="https://player.vimeo.com/video/143343818?api=1&&title=foo" width="50" height="281" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>'
|
75
|
+
assert_parsing_result src, ''
|
76
|
+
end
|
77
|
+
|
50
78
|
it 'allows images' do
|
51
79
|
src = '<p><img src="http://nav.heroku.com/images/logos/logo.png" alt="image"></p>'
|
52
80
|
assert_parsing_result src, src
|
@@ -234,7 +262,7 @@ And that's it.
|
|
234
262
|
more callout</p>
|
235
263
|
</div>
|
236
264
|
|
237
|
-
<p class="devcenter-parser-special-block-separator" style="display:none"
|
265
|
+
<p class="devcenter-parser-special-block-separator" style="display:none"> </p>
|
238
266
|
|
239
267
|
<blockquote>
|
240
268
|
<p>normal</p>
|
@@ -263,7 +291,7 @@ more callout</p>
|
|
263
291
|
<p>foo</p>
|
264
292
|
</div>
|
265
293
|
|
266
|
-
<p class="devcenter-parser-special-block-separator" style="display:none"
|
294
|
+
<p class="devcenter-parser-special-block-separator" style="display:none"> </p>
|
267
295
|
|
268
296
|
<div class="note">
|
269
297
|
<p>bar</p>
|
@@ -282,14 +310,12 @@ more callout</p>
|
|
282
310
|
MARKDOWN
|
283
311
|
|
284
312
|
html = <<-HTML
|
285
|
-
<table>
|
286
|
-
<thead>
|
313
|
+
<table><thead>
|
287
314
|
<tr>
|
288
315
|
<th>A</th>
|
289
316
|
<th>B</th>
|
290
317
|
</tr>
|
291
|
-
</thead>
|
292
|
-
<tbody>
|
318
|
+
</thead><tbody>
|
293
319
|
<tr>
|
294
320
|
<td>1</td>
|
295
321
|
<td>2</td>
|
@@ -298,8 +324,7 @@ more callout</p>
|
|
298
324
|
<td>3</td>
|
299
325
|
<td>4</td>
|
300
326
|
</tr>
|
301
|
-
</tbody>
|
302
|
-
</table>
|
327
|
+
</tbody></table>
|
303
328
|
HTML
|
304
329
|
|
305
330
|
assert_parsing_result md, html
|
@@ -336,13 +361,21 @@ HTML
|
|
336
361
|
end
|
337
362
|
|
338
363
|
it 'converts relative links with missing initial slashes to article links' do
|
339
|
-
['foo', 'foo/bar', 'foo#bar', '123'].each do |href|
|
364
|
+
['foo', 'foo/bar', 'foo#bar', '123', 'categories'].each do |href|
|
340
365
|
md = "[link](#{href})"
|
341
366
|
html = "<p><a href=\"/articles/#{href}\">link</a></p>"
|
342
367
|
assert_parsing_result md, html
|
343
368
|
end
|
344
369
|
end
|
345
370
|
|
371
|
+
it 'ignores links with missing initial slashes IFF they start with `categories/`' do
|
372
|
+
['categories/foo', 'categories/foo/bar', 'categories/foo#bar', 'categories/123'].each do |href|
|
373
|
+
md = "[link](#{href})"
|
374
|
+
html = "<p><a href=\"/#{href}\">link</a></p>"
|
375
|
+
assert_parsing_result md, html
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
346
379
|
it 'converts "articles/foo relative links with missing initial slashes to article links' do
|
347
380
|
md = '[link](articles/foo)'
|
348
381
|
html = '<p><a href="/articles/foo">link</a></p>'
|
@@ -353,6 +386,14 @@ HTML
|
|
353
386
|
assert_parsing_result md, html
|
354
387
|
end
|
355
388
|
|
389
|
+
it 'adds a link prefix from options for relative dev center links' do
|
390
|
+
md = '[link](foo)'
|
391
|
+
expected = '<p><a href="/ja/articles/foo">link</a></p>'
|
392
|
+
|
393
|
+
result = DevcenterParser.to_html(md, { link_prefix: '/ja/articles' })
|
394
|
+
assert_equal expected.strip, result.strip, "Failed when parsing\n#{md}\n.\n\nExpected:\n#{expected}\n\nActual result:\n#{result}\n\n"
|
395
|
+
end
|
396
|
+
|
356
397
|
it 'does not alter relative links with initial slashes nor absolute links nor anchor links to the same doc' do
|
357
398
|
['http://foo.com', 'https://foo.com', '/foo', '/foo/bar', '/foo#bar', '#foo', '/123', 'mailto:foo@foobar.com'].each do |href|
|
358
399
|
md = "[link](#{href})"
|
@@ -380,7 +421,7 @@ HTML
|
|
380
421
|
<p>foo</p>
|
381
422
|
</blockquote>
|
382
423
|
|
383
|
-
<p class="devcenter-parser-special-block-separator" style="display:none"
|
424
|
+
<p class="devcenter-parser-special-block-separator" style="display:none"> </p>
|
384
425
|
|
385
426
|
<blockquote>
|
386
427
|
<p>bar</p>
|
@@ -13,6 +13,12 @@ describe 'HeaderIdGeneratorTest' do
|
|
13
13
|
assert_id result(html), 'h2', 'foo-bar-header-123'
|
14
14
|
end
|
15
15
|
|
16
|
+
it 'does not replace existing ids' do
|
17
|
+
html = '<h2 id="foo">Foo Bar</h2><p>Content</p><h3>Baz</h3>'
|
18
|
+
assert_id result(html), 'h2', 'foo'
|
19
|
+
assert_id result(html), 'h3', 'baz'
|
20
|
+
end
|
21
|
+
|
16
22
|
it 'generates ids replacing inner non-alphanum chars with dashes' do
|
17
23
|
['Foo Bar', 'Foo-Bar', 'Foo#bar', 'Foo##Bar', 'Foo##Bar', '-$Foo##Bar$-'].each do |title|
|
18
24
|
html = "<h2>#{title}</h2>"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devcenter-parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Heroku
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -30,28 +30,28 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 3.
|
33
|
+
version: 3.5.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 3.
|
40
|
+
version: 3.5.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: sanitize
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 5.2.1
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 5.2.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: minitest
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -103,7 +103,7 @@ files:
|
|
103
103
|
homepage: https://devcenter.heroku.com
|
104
104
|
licenses: []
|
105
105
|
metadata: {}
|
106
|
-
post_install_message:
|
106
|
+
post_install_message:
|
107
107
|
rdoc_options: []
|
108
108
|
require_paths:
|
109
109
|
- lib
|
@@ -118,9 +118,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
118
|
- !ruby/object:Gem::Version
|
119
119
|
version: '0'
|
120
120
|
requirements: []
|
121
|
-
|
122
|
-
|
123
|
-
signing_key:
|
121
|
+
rubygems_version: 3.1.4
|
122
|
+
signing_key:
|
124
123
|
specification_version: 4
|
125
124
|
summary: Parser for Heroku Dev Center's content
|
126
125
|
test_files:
|