devcenter-parser 2.2.4 → 2.2.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile.lock +14 -14
- data/devcenter-parser.gemspec +2 -2
- data/lib/devcenter-parser.rb +15 -10
- data/lib/devcenter-parser/header_id_generator.rb +7 -1
- data/lib/devcenter-parser/version.rb +1 -1
- data/test/devcenter-parser_test.rb +42 -6
- data/test/header_id_generator_test.rb +6 -0
- metadata +10 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 251949c020f60adc81bbaa2dc0851b5d594486d74620db779cb8030ba8b41c45
|
4
|
+
data.tar.gz: e700ec53adb5a531eaaf93f7c70677aabaa6959e801b6fed79bf5ac7f8c559f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9746c03c129900fbc006b96927cfd5f0ffd50169ffc444490e4f219b1a14aa46c8b764d81e21667b0c07a8d6f17cec5277f5da1956070c9b404c3e9af3b96968
|
7
|
+
data.tar.gz: d41b9cd6f6248178991096e1c2bbb26fdc1a9dfc6b9f02cb4a1e511a2f36de83b60a44b1e7c6a0218b5983713cd7aadb93d2214b0a5cad7e8c2f923dc59b4814
|
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)
|
@@ -42,11 +42,31 @@ describe 'DevcenterParser' do
|
|
42
42
|
assert_parsing_result md, html
|
43
43
|
end
|
44
44
|
|
45
|
-
it 'allows embedding vimeo videos' do
|
46
|
-
src = '<iframe src="https://player.vimeo.com/video/
|
45
|
+
it 'allows embedding vimeo videos when their do-no-track param is set to true' do
|
46
|
+
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>'
|
47
47
|
assert_parsing_result src, src
|
48
48
|
end
|
49
49
|
|
50
|
+
it 'allows embedding youtube videos from its no-cookies domain' do
|
51
|
+
src = '<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/123456ABCDEF" frameborder="0" allowfullscreen=""></iframe>'
|
52
|
+
assert_parsing_result src, src
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'removes youtube videos embedded from the with-cookies domain' do
|
56
|
+
src = '<iframe width="560" height="315" src="https://www.youtube.com/embed/123456ABCDEF" frameborder="0" allowfullscreen=""></iframe>'
|
57
|
+
assert_parsing_result src, ''
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'does not allow embedding vimeo videos when their do-no-track param is set to something different than true' do
|
61
|
+
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>'
|
62
|
+
assert_parsing_result src, ''
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'does not allow embedding vimeo videos when their do-no-track param is not passed' do
|
66
|
+
src = '<iframe src="https://player.vimeo.com/video/143343818?api=1&&title=foo" width="50" height="281" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>'
|
67
|
+
assert_parsing_result src, ''
|
68
|
+
end
|
69
|
+
|
50
70
|
it 'allows images' do
|
51
71
|
src = '<p><img src="http://nav.heroku.com/images/logos/logo.png" alt="image"></p>'
|
52
72
|
assert_parsing_result src, src
|
@@ -234,7 +254,7 @@ And that's it.
|
|
234
254
|
more callout</p>
|
235
255
|
</div>
|
236
256
|
|
237
|
-
<p class="devcenter-parser-special-block-separator" style="display:none"
|
257
|
+
<p class="devcenter-parser-special-block-separator" style="display:none"> </p>
|
238
258
|
|
239
259
|
<blockquote>
|
240
260
|
<p>normal</p>
|
@@ -263,7 +283,7 @@ more callout</p>
|
|
263
283
|
<p>foo</p>
|
264
284
|
</div>
|
265
285
|
|
266
|
-
<p class="devcenter-parser-special-block-separator" style="display:none"
|
286
|
+
<p class="devcenter-parser-special-block-separator" style="display:none"> </p>
|
267
287
|
|
268
288
|
<div class="note">
|
269
289
|
<p>bar</p>
|
@@ -336,13 +356,21 @@ HTML
|
|
336
356
|
end
|
337
357
|
|
338
358
|
it 'converts relative links with missing initial slashes to article links' do
|
339
|
-
['foo', 'foo/bar', 'foo#bar', '123'].each do |href|
|
359
|
+
['foo', 'foo/bar', 'foo#bar', '123', 'categories'].each do |href|
|
340
360
|
md = "[link](#{href})"
|
341
361
|
html = "<p><a href=\"/articles/#{href}\">link</a></p>"
|
342
362
|
assert_parsing_result md, html
|
343
363
|
end
|
344
364
|
end
|
345
365
|
|
366
|
+
it 'ignores links with missing initial slashes IFF they start with `categories/`' do
|
367
|
+
['categories/foo', 'categories/foo/bar', 'categories/foo#bar', 'categories/123'].each do |href|
|
368
|
+
md = "[link](#{href})"
|
369
|
+
html = "<p><a href=\"/#{href}\">link</a></p>"
|
370
|
+
assert_parsing_result md, html
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
346
374
|
it 'converts "articles/foo relative links with missing initial slashes to article links' do
|
347
375
|
md = '[link](articles/foo)'
|
348
376
|
html = '<p><a href="/articles/foo">link</a></p>'
|
@@ -353,6 +381,14 @@ HTML
|
|
353
381
|
assert_parsing_result md, html
|
354
382
|
end
|
355
383
|
|
384
|
+
it 'adds a link prefix from options for relative dev center links' do
|
385
|
+
md = '[link](foo)'
|
386
|
+
expected = '<p><a href="/ja/articles/foo">link</a></p>'
|
387
|
+
|
388
|
+
result = DevcenterParser.to_html(md, { link_prefix: '/ja/articles' })
|
389
|
+
assert_equal expected.strip, result.strip, "Failed when parsing\n#{md}\n.\n\nExpected:\n#{expected}\n\nActual result:\n#{result}\n\n"
|
390
|
+
end
|
391
|
+
|
356
392
|
it 'does not alter relative links with initial slashes nor absolute links nor anchor links to the same doc' do
|
357
393
|
['http://foo.com', 'https://foo.com', '/foo', '/foo/bar', '/foo#bar', '#foo', '/123', 'mailto:foo@foobar.com'].each do |href|
|
358
394
|
md = "[link](#{href})"
|
@@ -380,7 +416,7 @@ HTML
|
|
380
416
|
<p>foo</p>
|
381
417
|
</blockquote>
|
382
418
|
|
383
|
-
<p class="devcenter-parser-special-block-separator" style="display:none"
|
419
|
+
<p class="devcenter-parser-special-block-separator" style="display:none"> </p>
|
384
420
|
|
385
421
|
<blockquote>
|
386
422
|
<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.10
|
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-11-05 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.0.3
|
122
|
+
signing_key:
|
124
123
|
specification_version: 4
|
125
124
|
summary: Parser for Heroku Dev Center's content
|
126
125
|
test_files:
|