qiita-markdown 0.28.0 → 0.29.0
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.
Potentially problematic release.
This version of qiita-markdown might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/qiita/markdown.rb +6 -0
- data/lib/qiita/markdown/embed/gist.rb +9 -0
- data/lib/qiita/markdown/embed/google_slide.rb +9 -0
- data/lib/qiita/markdown/embed/slide_share.rb +9 -0
- data/lib/qiita/markdown/embed/speeker_deck.rb +16 -0
- data/lib/qiita/markdown/embed/youtube.rb +12 -0
- data/lib/qiita/markdown/filters/final_sanitizer.rb +7 -3
- data/lib/qiita/markdown/filters/user_input_sanitizer.rb +14 -2
- data/lib/qiita/markdown/transformers/filter_iframe.rb +50 -0
- data/lib/qiita/markdown/transformers/filter_script.rb +2 -0
- data/lib/qiita/markdown/version.rb +1 -1
- data/spec/qiita/markdown/processor_spec.rb +100 -0
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ba9a61d760c878765f0d56a7b2be4b3d6d9f61eff2d104979ca5af3f0b481e60
|
|
4
|
+
data.tar.gz: 727b673a4c63a45b633f9b5f7331239cea6ff5cd36b7c3c4655089a096026697
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b3d2c8a721f25fa8010eaee9adcded2321e27eaf35c0092bd165e30d86163bfb872fb17962a5438a5233b0e861f7f1ccbcc3831bd0e924422ce8c46445882c35
|
|
7
|
+
data.tar.gz: 5c3fdd91f7656e222050921ec233c24f82c81498ac0e8e42b889e1852af34d9bee113bb5134df702536b50d30202532358204828c46a29d5c57b99a42167f2b7
|
data/CHANGELOG.md
CHANGED
data/lib/qiita/markdown.rb
CHANGED
|
@@ -10,8 +10,14 @@ require "sanitize"
|
|
|
10
10
|
require "qiita/markdown/embed/code_pen"
|
|
11
11
|
require "qiita/markdown/embed/tweet"
|
|
12
12
|
require "qiita/markdown/embed/asciinema"
|
|
13
|
+
require "qiita/markdown/embed/gist"
|
|
14
|
+
require "qiita/markdown/embed/youtube"
|
|
15
|
+
require "qiita/markdown/embed/slide_share"
|
|
16
|
+
require "qiita/markdown/embed/google_slide"
|
|
17
|
+
require "qiita/markdown/embed/speeker_deck"
|
|
13
18
|
require "qiita/markdown/transformers/filter_attributes"
|
|
14
19
|
require "qiita/markdown/transformers/filter_script"
|
|
20
|
+
require "qiita/markdown/transformers/filter_iframe"
|
|
15
21
|
require "qiita/markdown/transformers/strip_invalid_node"
|
|
16
22
|
require "qiita/markdown/filters/checkbox"
|
|
17
23
|
require "qiita/markdown/filters/code_block"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Qiita
|
|
2
|
+
module Markdown
|
|
3
|
+
module Embed
|
|
4
|
+
module SpeekerDeck
|
|
5
|
+
SCRIPT_URLS = [
|
|
6
|
+
"//speakerdeck.com/assets/embed.js",
|
|
7
|
+
].freeze
|
|
8
|
+
CLASS_NAME = %w[speakerdeck-embed].freeze
|
|
9
|
+
DATA_ATTRIBUTES = %w[
|
|
10
|
+
data-id data-ratio
|
|
11
|
+
].freeze
|
|
12
|
+
ATTRIBUTES = %w[class] + DATA_ATTRIBUTES
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -47,7 +47,9 @@ module Qiita
|
|
|
47
47
|
"async",
|
|
48
48
|
"src",
|
|
49
49
|
"type",
|
|
50
|
-
]
|
|
50
|
+
].concat(
|
|
51
|
+
Embed::SpeekerDeck::ATTRIBUTES,
|
|
52
|
+
),
|
|
51
53
|
"span" => [
|
|
52
54
|
"style",
|
|
53
55
|
],
|
|
@@ -137,6 +139,7 @@ module Qiita
|
|
|
137
139
|
"s",
|
|
138
140
|
"samp",
|
|
139
141
|
"script",
|
|
142
|
+
"iframe",
|
|
140
143
|
"span",
|
|
141
144
|
"strike",
|
|
142
145
|
"strong",
|
|
@@ -186,14 +189,15 @@ module Qiita
|
|
|
186
189
|
transformers: [
|
|
187
190
|
Transformers::StripInvalidNode,
|
|
188
191
|
Transformers::FilterScript,
|
|
192
|
+
Transformers::FilterIframe,
|
|
189
193
|
],
|
|
190
194
|
}.freeze
|
|
191
195
|
|
|
192
196
|
SCRIPTABLE_RULE = RULE.dup.tap do |rule|
|
|
193
197
|
rule[:attributes] = RULE[:attributes].dup
|
|
194
198
|
rule[:attributes][:all] = rule[:attributes][:all] + [:data]
|
|
195
|
-
rule[:elements] = RULE[:elements] + ["
|
|
196
|
-
rule[:transformers] = rule[:transformers] - [Transformers::FilterScript]
|
|
199
|
+
rule[:elements] = RULE[:elements] + ["video"]
|
|
200
|
+
rule[:transformers] = rule[:transformers] - [Transformers::FilterScript, Transformers::FilterIframe]
|
|
197
201
|
end
|
|
198
202
|
|
|
199
203
|
def call
|
|
@@ -6,7 +6,7 @@ module Qiita
|
|
|
6
6
|
RULE = {
|
|
7
7
|
elements: %w[
|
|
8
8
|
a b blockquote br code dd del details div dl dt em font h1 h2 h3 h4 h5 h6
|
|
9
|
-
hr i img ins kbd li ol p pre q rp rt ruby s samp script strike strong sub
|
|
9
|
+
hr i img ins kbd li ol p pre q rp rt ruby s samp script iframe strike strong sub
|
|
10
10
|
summary sup table tbody td tfoot th thead tr ul var
|
|
11
11
|
],
|
|
12
12
|
attributes: {
|
|
@@ -26,7 +26,18 @@ module Qiita
|
|
|
26
26
|
"li" => %w[id],
|
|
27
27
|
"p" => Embed::CodePen::ATTRIBUTES,
|
|
28
28
|
"q" => %w[cite],
|
|
29
|
-
"script" => %w[async src id],
|
|
29
|
+
"script" => %w[async src id].concat(Embed::SpeekerDeck::ATTRIBUTES),
|
|
30
|
+
"iframe" => %w[
|
|
31
|
+
allowfullscreen
|
|
32
|
+
frameborder
|
|
33
|
+
height
|
|
34
|
+
marginheight
|
|
35
|
+
marginwidth
|
|
36
|
+
scrolling
|
|
37
|
+
src
|
|
38
|
+
style
|
|
39
|
+
width
|
|
40
|
+
],
|
|
30
41
|
"sup" => %w[id],
|
|
31
42
|
"td" => %w[colspan rowspan style],
|
|
32
43
|
"th" => %w[colspan rowspan style],
|
|
@@ -42,6 +53,7 @@ module Qiita
|
|
|
42
53
|
transformers: [
|
|
43
54
|
Transformers::FilterAttributes,
|
|
44
55
|
Transformers::FilterScript,
|
|
56
|
+
Transformers::FilterIframe,
|
|
45
57
|
],
|
|
46
58
|
}.freeze
|
|
47
59
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Qiita
|
|
2
|
+
module Markdown
|
|
3
|
+
module Transformers
|
|
4
|
+
class FilterIframe
|
|
5
|
+
URL_WHITE_LIST = [
|
|
6
|
+
].flatten.freeze
|
|
7
|
+
|
|
8
|
+
HOST_WHITE_LIST = [
|
|
9
|
+
Embed::Youtube::SCRIPT_HOSTS,
|
|
10
|
+
Embed::SlideShare::SCRIPT_HOST,
|
|
11
|
+
Embed::GoogleSlide::SCRIPT_HOST,
|
|
12
|
+
].flatten.freeze
|
|
13
|
+
|
|
14
|
+
def self.call(*args)
|
|
15
|
+
new(*args).transform
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize(env)
|
|
19
|
+
@env = env
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def transform
|
|
23
|
+
if name == "iframe"
|
|
24
|
+
if URL_WHITE_LIST.include?(node["src"]) || HOST_WHITE_LIST.include?(host_of(node["src"]))
|
|
25
|
+
node.children.unlink
|
|
26
|
+
else
|
|
27
|
+
node.unlink
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def name
|
|
35
|
+
@env[:node_name]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def node
|
|
39
|
+
@env[:node]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def host_of(url)
|
|
43
|
+
Addressable::URI.parse(url).host if url
|
|
44
|
+
rescue Addressable::URI::InvalidURIError
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -5,10 +5,12 @@ module Qiita
|
|
|
5
5
|
URL_WHITE_LIST = [
|
|
6
6
|
Embed::CodePen::SCRIPT_URLS,
|
|
7
7
|
Embed::Tweet::SCRIPT_URL,
|
|
8
|
+
Embed::SpeekerDeck::SCRIPT_URLS,
|
|
8
9
|
].flatten.freeze
|
|
9
10
|
|
|
10
11
|
HOST_WHITE_LIST = [
|
|
11
12
|
Embed::Asciinema::SCRIPT_HOST,
|
|
13
|
+
Embed::Gist::SCRIPT_HOST,
|
|
12
14
|
].flatten.freeze
|
|
13
15
|
|
|
14
16
|
def self.call(*args)
|
|
@@ -1407,6 +1407,106 @@ describe Qiita::Markdown::Processor do
|
|
|
1407
1407
|
end
|
|
1408
1408
|
end
|
|
1409
1409
|
|
|
1410
|
+
context "with HTML embed code for Gist" do
|
|
1411
|
+
let(:markdown) do
|
|
1412
|
+
<<-MARKDOWN.strip_heredoc
|
|
1413
|
+
<script id="example" src="https://gist.github.com/a/example.js"></script>
|
|
1414
|
+
MARKDOWN
|
|
1415
|
+
end
|
|
1416
|
+
|
|
1417
|
+
if allowed
|
|
1418
|
+
it "does not sanitize embed code" do
|
|
1419
|
+
should eq <<-HTML.strip_heredoc
|
|
1420
|
+
<script id="example" src="https://gist.github.com/a/example.js"></script>
|
|
1421
|
+
HTML
|
|
1422
|
+
end
|
|
1423
|
+
else
|
|
1424
|
+
it "forces async attribute on script" do
|
|
1425
|
+
should eq <<-HTML.strip_heredoc
|
|
1426
|
+
<script id="example" src="https://gist.github.com/a/example.js" async="async"></script>
|
|
1427
|
+
HTML
|
|
1428
|
+
end
|
|
1429
|
+
end
|
|
1430
|
+
end
|
|
1431
|
+
|
|
1432
|
+
context "with HTML embed code for Youtube" do
|
|
1433
|
+
let(:markdown) do
|
|
1434
|
+
<<-MARKDOWN.strip_heredoc
|
|
1435
|
+
<iframe width="100" height="100" src="https://www.youtube.com/embed/example"></iframe>
|
|
1436
|
+
MARKDOWN
|
|
1437
|
+
end
|
|
1438
|
+
|
|
1439
|
+
it "does not sanitize embed code" do
|
|
1440
|
+
should eq <<-HTML.strip_heredoc
|
|
1441
|
+
<iframe width="100" height="100" src="https://www.youtube.com/embed/example"></iframe>
|
|
1442
|
+
HTML
|
|
1443
|
+
end
|
|
1444
|
+
|
|
1445
|
+
context "when url is privacy enhanced mode" do
|
|
1446
|
+
let(:markdown) do
|
|
1447
|
+
<<-MARKDOWN.strip_heredoc
|
|
1448
|
+
<iframe width="100" height="100" src="https://www.youtube-nocookie.com/embed/example"></iframe>
|
|
1449
|
+
MARKDOWN
|
|
1450
|
+
end
|
|
1451
|
+
|
|
1452
|
+
it "does not sanitize embed code" do
|
|
1453
|
+
should eq <<-HTML.strip_heredoc
|
|
1454
|
+
<iframe width="100" height="100" src="https://www.youtube-nocookie.com/embed/example"></iframe>
|
|
1455
|
+
HTML
|
|
1456
|
+
end
|
|
1457
|
+
end
|
|
1458
|
+
end
|
|
1459
|
+
|
|
1460
|
+
context "with HTML embed code for SlideShare" do
|
|
1461
|
+
let(:markdown) do
|
|
1462
|
+
<<-MARKDOWN.strip_heredoc
|
|
1463
|
+
<iframe width="100" height="100" src="https://www.slideshare.net/embed/example"></iframe>
|
|
1464
|
+
MARKDOWN
|
|
1465
|
+
end
|
|
1466
|
+
|
|
1467
|
+
it "does not sanitize embed code" do
|
|
1468
|
+
should eq <<-HTML.strip_heredoc
|
|
1469
|
+
<iframe width="100" height="100" src="https://www.slideshare.net/embed/example"></iframe>
|
|
1470
|
+
HTML
|
|
1471
|
+
end
|
|
1472
|
+
end
|
|
1473
|
+
|
|
1474
|
+
context "with HTML embed code for GoogleSlide" do
|
|
1475
|
+
let(:markdown) do
|
|
1476
|
+
<<-MARKDOWN.strip_heredoc
|
|
1477
|
+
<iframe src="https://docs.google.com/presentation/d/example/embed" frameborder="0" width="482" height="300" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
|
|
1478
|
+
MARKDOWN
|
|
1479
|
+
end
|
|
1480
|
+
|
|
1481
|
+
it "does not sanitize embed code" do
|
|
1482
|
+
should eq <<-HTML.strip_heredoc
|
|
1483
|
+
<iframe src="https://docs.google.com/presentation/d/example/embed" frameborder="0" width="482" height="300" allowfullscreen="true"></iframe>
|
|
1484
|
+
HTML
|
|
1485
|
+
end
|
|
1486
|
+
end
|
|
1487
|
+
|
|
1488
|
+
context "with HTML embed code for SpeekerDeck" do
|
|
1489
|
+
let(:markdown) do
|
|
1490
|
+
<<-MARKDOWN.strip_heredoc
|
|
1491
|
+
<script async class="speakerdeck-embed" data-id="example" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
|
|
1492
|
+
MARKDOWN
|
|
1493
|
+
end
|
|
1494
|
+
|
|
1495
|
+
if allowed
|
|
1496
|
+
it "does not sanitize embed code" do
|
|
1497
|
+
should eq <<-HTML.strip_heredoc
|
|
1498
|
+
<script async class="speakerdeck-embed" data-id="example" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
|
|
1499
|
+
HTML
|
|
1500
|
+
end
|
|
1501
|
+
else
|
|
1502
|
+
it "forces async attribute on script" do
|
|
1503
|
+
should eq <<-HTML.strip_heredoc
|
|
1504
|
+
<script async class="speakerdeck-embed" data-id="example" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
|
|
1505
|
+
HTML
|
|
1506
|
+
end
|
|
1507
|
+
end
|
|
1508
|
+
end
|
|
1509
|
+
|
|
1410
1510
|
context "with embed code for Tweet" do
|
|
1411
1511
|
let(:markdown) do
|
|
1412
1512
|
<<-MARKDOWN.strip_heredoc
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: qiita-markdown
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.29.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryo Nakamura
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-02-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: gemoji
|
|
@@ -258,7 +258,12 @@ files:
|
|
|
258
258
|
- lib/qiita/markdown/base_processor.rb
|
|
259
259
|
- lib/qiita/markdown/embed/asciinema.rb
|
|
260
260
|
- lib/qiita/markdown/embed/code_pen.rb
|
|
261
|
+
- lib/qiita/markdown/embed/gist.rb
|
|
262
|
+
- lib/qiita/markdown/embed/google_slide.rb
|
|
263
|
+
- lib/qiita/markdown/embed/slide_share.rb
|
|
264
|
+
- lib/qiita/markdown/embed/speeker_deck.rb
|
|
261
265
|
- lib/qiita/markdown/embed/tweet.rb
|
|
266
|
+
- lib/qiita/markdown/embed/youtube.rb
|
|
262
267
|
- lib/qiita/markdown/filters/checkbox.rb
|
|
263
268
|
- lib/qiita/markdown/filters/code_block.rb
|
|
264
269
|
- lib/qiita/markdown/filters/emoji.rb
|
|
@@ -281,6 +286,7 @@ files:
|
|
|
281
286
|
- lib/qiita/markdown/processor.rb
|
|
282
287
|
- lib/qiita/markdown/summary_processor.rb
|
|
283
288
|
- lib/qiita/markdown/transformers/filter_attributes.rb
|
|
289
|
+
- lib/qiita/markdown/transformers/filter_iframe.rb
|
|
284
290
|
- lib/qiita/markdown/transformers/filter_script.rb
|
|
285
291
|
- lib/qiita/markdown/transformers/strip_invalid_node.rb
|
|
286
292
|
- lib/qiita/markdown/version.rb
|