qiita-markdown 0.33.0 → 0.38.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/lib/qiita/markdown.rb +2 -2
- data/lib/qiita/markdown/filters/custom_block.rb +63 -0
- data/lib/qiita/markdown/filters/greenmat.rb +1 -0
- data/lib/qiita/markdown/filters/syntax_highlight.rb +3 -10
- data/lib/qiita/markdown/filters/user_input_sanitizer.rb +1 -1
- data/lib/qiita/markdown/processor.rb +1 -0
- data/lib/qiita/markdown/transformers/filter_iframe.rb +1 -1
- data/lib/qiita/markdown/transformers/filter_script.rb +0 -1
- data/lib/qiita/markdown/version.rb +1 -1
- data/qiita-markdown.gemspec +2 -2
- data/spec/qiita/markdown/processor_spec.rb +261 -99
- metadata +14 -14
- data/lib/qiita/markdown/embed/gist.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0133d912562a9dcb693c507e7ec0caadb6ca0c509da6af2c57773d87a2af745
|
4
|
+
data.tar.gz: 997e0e521830183eccc1f009634352379a7697a8a9e95edb9bae1a9d4f4f7c78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44318b683d2df089695d572a037ec393c495dd23a3d48f82be77287165eff54d3e7d1fb68143f4ad7004eca337df8ed83cfcdd921de6fe7133aaaddeaffe7248
|
7
|
+
data.tar.gz: 883a123e2dad403e8da8d87457be977270ac7dad837e2502d873aa3208e024e2593d784ae0105923658243771d497232e6776a5011a4e354df995447d8fe7c49
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
|
+
## 0.38.0
|
4
|
+
- Change default syntax highlighter from pygments to rouge
|
5
|
+
|
6
|
+
## 0.37.0
|
7
|
+
- Change keyword of notation
|
8
|
+
|
9
|
+
## 0.36.0
|
10
|
+
- Support message notation
|
11
|
+
|
12
|
+
## 0.35.0
|
13
|
+
|
14
|
+
- Allow Relative URL in iframe src attributes
|
15
|
+
|
16
|
+
## 0.34.0
|
17
|
+
|
18
|
+
- Delete gist embed rule to avoid XSS
|
19
|
+
|
3
20
|
## 0.33.0
|
4
21
|
|
5
22
|
- Fix XSS possibility bug
|
data/lib/qiita/markdown.rb
CHANGED
@@ -4,13 +4,12 @@ require "html/pipeline"
|
|
4
4
|
require "linguist"
|
5
5
|
require "mem"
|
6
6
|
require "nokogiri"
|
7
|
-
require "
|
7
|
+
require "rouge"
|
8
8
|
require "sanitize"
|
9
9
|
|
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
13
|
require "qiita/markdown/embed/youtube"
|
15
14
|
require "qiita/markdown/embed/slide_share"
|
16
15
|
require "qiita/markdown/embed/google_slide"
|
@@ -21,6 +20,7 @@ require "qiita/markdown/transformers/filter_iframe"
|
|
21
20
|
require "qiita/markdown/transformers/strip_invalid_node"
|
22
21
|
require "qiita/markdown/filters/checkbox"
|
23
22
|
require "qiita/markdown/filters/code_block"
|
23
|
+
require "qiita/markdown/filters/custom_block"
|
24
24
|
require "qiita/markdown/filters/emoji"
|
25
25
|
require "qiita/markdown/filters/external_link"
|
26
26
|
require "qiita/markdown/filters/final_sanitizer"
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Qiita
|
2
|
+
module Markdown
|
3
|
+
module Filters
|
4
|
+
class CustomBlock < HTML::Pipeline::Filter
|
5
|
+
ALLOWED_TYPES = %w[note].freeze
|
6
|
+
|
7
|
+
def call
|
8
|
+
doc.search('div[data-type="customblock"]').each do |div|
|
9
|
+
metadata = Metadata.new(div["data-metadata"])
|
10
|
+
next unless ALLOWED_TYPES.include?(metadata.type)
|
11
|
+
klass = Object.const_get("#{self.class}::#{metadata.type.capitalize}")
|
12
|
+
klass.new(div, metadata.subtype).convert
|
13
|
+
end
|
14
|
+
doc
|
15
|
+
end
|
16
|
+
|
17
|
+
class Metadata
|
18
|
+
attr_reader :type, :subtype
|
19
|
+
|
20
|
+
# @param text [String, nil]
|
21
|
+
def initialize(text)
|
22
|
+
# Discared after the second word.
|
23
|
+
@type, @subtype = text.split(" ")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Note
|
28
|
+
attr_reader :node, :type
|
29
|
+
|
30
|
+
ALLOWED_TYPES = %w[info warn alert].freeze
|
31
|
+
DEFAULT_TYPE = "info".freeze
|
32
|
+
|
33
|
+
# @param node [Nokogiri::XML::Node]
|
34
|
+
# @param type [String, nil]
|
35
|
+
def initialize(node, type)
|
36
|
+
@node = node
|
37
|
+
@type = ALLOWED_TYPES.include?(type) ? type : DEFAULT_TYPE
|
38
|
+
end
|
39
|
+
|
40
|
+
def convert
|
41
|
+
node.inner_html = message
|
42
|
+
node["class"] = "note #{type}"
|
43
|
+
node.children.first.add_previous_sibling(icon) if icon
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def message
|
49
|
+
"<p>#{node.text}</p>"
|
50
|
+
end
|
51
|
+
|
52
|
+
def icon
|
53
|
+
{
|
54
|
+
info: %(<span class="fa fa-fw fa-check-circle"></span>),
|
55
|
+
warn: %(<span class="fa fa-fw fa-exclamation-circle"></span>),
|
56
|
+
alert: %(<span class="fa fa-fw fa-times-circle"></span>),
|
57
|
+
}[type.to_sym]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -20,6 +20,7 @@ module Qiita
|
|
20
20
|
Qiita::Markdown::Greenmat::HTMLRenderer.new(hard_wrap: true, with_toc_data: true),
|
21
21
|
autolink: true,
|
22
22
|
fenced_code_blocks: true,
|
23
|
+
fenced_custom_blocks: true,
|
23
24
|
footnotes: options[:footnotes],
|
24
25
|
no_intra_emphasis: true,
|
25
26
|
no_mention_emphasis: true,
|
@@ -4,6 +4,7 @@ module Qiita
|
|
4
4
|
class SyntaxHighlight < HTML::Pipeline::Filter
|
5
5
|
DEFAULT_LANGUAGE = "text"
|
6
6
|
DEFAULT_TIMEOUT = Float::INFINITY
|
7
|
+
DEFAULT_OPTION = "html_legacy"
|
7
8
|
|
8
9
|
def call
|
9
10
|
elapsed = 0
|
@@ -79,11 +80,11 @@ module Qiita
|
|
79
80
|
end
|
80
81
|
|
81
82
|
def highlight(language)
|
82
|
-
|
83
|
+
Rouge.highlight(code, language, DEFAULT_OPTION)
|
83
84
|
end
|
84
85
|
|
85
86
|
def highlighted_node
|
86
|
-
if specific_language &&
|
87
|
+
if specific_language && Rouge::Lexer.find(specific_language)
|
87
88
|
begin
|
88
89
|
highlight(specific_language).presence or raise
|
89
90
|
rescue
|
@@ -102,14 +103,6 @@ module Qiita
|
|
102
103
|
Nokogiri::HTML.fragment(%Q[<div class="code-frame" data-lang="#{language}"></div>])
|
103
104
|
end
|
104
105
|
|
105
|
-
def pygments_options
|
106
|
-
@pygments_options ||= begin
|
107
|
-
options = { encoding: "utf-8", stripnl: false }
|
108
|
-
options[:startinline] = true if has_inline_php?
|
109
|
-
options
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
106
|
def specific_language
|
114
107
|
@specific_language || @node["lang"]
|
115
108
|
end
|
@@ -13,7 +13,7 @@ module Qiita
|
|
13
13
|
"a" => %w[class href rel title],
|
14
14
|
"blockquote" => %w[cite] + Embed::Tweet::ATTRIBUTES,
|
15
15
|
"code" => %w[data-metadata],
|
16
|
-
"div" => %w[class],
|
16
|
+
"div" => %w[class data-type data-metadata],
|
17
17
|
"font" => %w[color],
|
18
18
|
"h1" => %w[id],
|
19
19
|
"h2" => %w[id],
|
@@ -43,7 +43,7 @@ module Qiita
|
|
43
43
|
def host_of(url)
|
44
44
|
if url
|
45
45
|
scheme = URI.parse(url).scheme
|
46
|
-
Addressable::URI.parse(url).host if ["http", "https"].include? scheme
|
46
|
+
Addressable::URI.parse(url).host if ["http", "https", nil].include? scheme
|
47
47
|
end
|
48
48
|
rescue Addressable::URI::InvalidURIError, URI::InvalidURIError
|
49
49
|
nil
|
data/qiita-markdown.gemspec
CHANGED
@@ -22,8 +22,8 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_dependency "github-linguist", "~> 4.0"
|
23
23
|
spec.add_dependency "html-pipeline", "~> 2.0"
|
24
24
|
spec.add_dependency "mem"
|
25
|
-
spec.add_dependency "
|
26
|
-
spec.add_dependency "greenmat", "3.5.1.
|
25
|
+
spec.add_dependency "rouge", "3.26.0"
|
26
|
+
spec.add_dependency "greenmat", "3.5.1.2"
|
27
27
|
spec.add_dependency "sanitize"
|
28
28
|
spec.add_dependency "addressable"
|
29
29
|
spec.add_development_dependency "activesupport", "4.2.6"
|
@@ -149,8 +149,8 @@ describe Qiita::Markdown::Processor do
|
|
149
149
|
should eq <<-HTML.strip_heredoc
|
150
150
|
<div class="code-frame" data-lang="ruby">
|
151
151
|
<div class="code-lang"><span class="bold">example.rb</span></div>
|
152
|
-
<div class="highlight"><pre><
|
153
|
-
</pre></div>
|
152
|
+
<div class="highlight"><pre class="codehilite"><code><span class="mi">1</span>
|
153
|
+
</code></pre></div>
|
154
154
|
</div>
|
155
155
|
HTML
|
156
156
|
end
|
@@ -169,8 +169,8 @@ describe Qiita::Markdown::Processor do
|
|
169
169
|
should eq <<-HTML.strip_heredoc
|
170
170
|
<div class="code-frame" data-lang="php">
|
171
171
|
<div class="code-lang"><span class="bold">example.php</span></div>
|
172
|
-
<div class="highlight"><pre><
|
173
|
-
</pre></div>
|
172
|
+
<div class="highlight"><pre class="codehilite"><code><span class="mi">1</span>
|
173
|
+
</code></pre></div>
|
174
174
|
</div>
|
175
175
|
HTML
|
176
176
|
end
|
@@ -187,8 +187,8 @@ describe Qiita::Markdown::Processor do
|
|
187
187
|
|
188
188
|
it "returns code-frame and highlighted pre element" do
|
189
189
|
should eq <<-HTML.strip_heredoc
|
190
|
-
<div class="code-frame" data-lang="ruby"><div class="highlight"><pre><
|
191
|
-
</pre></div></div>
|
190
|
+
<div class="code-frame" data-lang="ruby"><div class="highlight"><pre class="codehilite"><code><span class="mi">1</span>
|
191
|
+
</code></pre></div></div>
|
192
192
|
HTML
|
193
193
|
end
|
194
194
|
end
|
@@ -226,10 +226,10 @@ describe Qiita::Markdown::Processor do
|
|
226
226
|
|
227
227
|
it "does not strip the newlines" do
|
228
228
|
should eq <<-HTML.strip_heredoc
|
229
|
-
<div class="code-frame" data-lang="text"><div class="highlight"><pre><
|
229
|
+
<div class="code-frame" data-lang="text"><div class="highlight"><pre class="codehilite"><code>
|
230
230
|
foo
|
231
231
|
|
232
|
-
</pre></div></div>
|
232
|
+
</code></pre></div></div>
|
233
233
|
HTML
|
234
234
|
end
|
235
235
|
end
|
@@ -311,8 +311,8 @@ describe Qiita::Markdown::Processor do
|
|
311
311
|
should include(<<-HTML.strip_heredoc.rstrip)
|
312
312
|
<div class="code-frame" data-lang="ruby">
|
313
313
|
<div class="code-lang"><span class="bold">@alice</span></div>
|
314
|
-
<div class="highlight"><pre><
|
315
|
-
</pre></div>
|
314
|
+
<div class="highlight"><pre class="codehilite"><code><span class="mi">1</span>
|
315
|
+
</code></pre></div>
|
316
316
|
</div>
|
317
317
|
HTML
|
318
318
|
end
|
@@ -659,9 +659,9 @@ describe Qiita::Markdown::Processor do
|
|
659
659
|
|
660
660
|
it "does not replace checkbox" do
|
661
661
|
should eq <<-HTML.strip_heredoc
|
662
|
-
<div class="code-frame" data-lang="text"><div class="highlight"><pre><
|
662
|
+
<div class="code-frame" data-lang="text"><div class="highlight"><pre class="codehilite"><code>- [ ] a
|
663
663
|
- [x] b
|
664
|
-
</pre></div></div>
|
664
|
+
</code></pre></div></div>
|
665
665
|
HTML
|
666
666
|
end
|
667
667
|
end
|
@@ -768,9 +768,9 @@ describe Qiita::Markdown::Processor do
|
|
768
768
|
|
769
769
|
it "generates only code blocks without footnotes" do
|
770
770
|
should eq <<-HTML.strip_heredoc
|
771
|
-
<div class="code-frame" data-lang="text"><div class="highlight"><pre><
|
771
|
+
<div class="code-frame" data-lang="text"><div class="highlight"><pre class="codehilite"><code>[^1]
|
772
772
|
[^1]: test
|
773
|
-
</pre></div></div>
|
773
|
+
</code></pre></div></div>
|
774
774
|
HTML
|
775
775
|
end
|
776
776
|
end
|
@@ -1067,8 +1067,8 @@ describe Qiita::Markdown::Processor do
|
|
1067
1067
|
expect(subject).to eq <<-HTML.strip_heredoc
|
1068
1068
|
<p><details><summary>Folding sample</summary><div>
|
1069
1069
|
|
1070
|
-
<div class="code-frame" data-lang="rb"><div class="highlight"><pre><
|
1071
|
-
</pre></div></div>
|
1070
|
+
<div class="code-frame" data-lang="rb"><div class="highlight"><pre class="codehilite"><code><span class="nb">puts</span> <span class="s2">"Hello, World"</span>
|
1071
|
+
</code></pre></div></div>
|
1072
1072
|
|
1073
1073
|
<p></p>
|
1074
1074
|
</div></details></p>
|
@@ -1124,8 +1124,8 @@ describe Qiita::Markdown::Processor do
|
|
1124
1124
|
should eq <<-HTML.strip_heredoc
|
1125
1125
|
<div class="code-frame" data-lang="js">
|
1126
1126
|
<div class="code-lang"><span class="bold">test<script>alert(1)</script></span></div>
|
1127
|
-
<div class="highlight"><pre><
|
1128
|
-
</pre></div>
|
1127
|
+
<div class="highlight"><pre class="codehilite"><code><span class="mi">1</span>
|
1128
|
+
</code></pre></div>
|
1129
1129
|
</div>
|
1130
1130
|
HTML
|
1131
1131
|
end
|
@@ -1134,8 +1134,8 @@ describe Qiita::Markdown::Processor do
|
|
1134
1134
|
should eq <<-HTML.strip_heredoc
|
1135
1135
|
<div class="code-frame" data-lang="js">
|
1136
1136
|
<div class="code-lang"><span class="bold">test</span></div>
|
1137
|
-
<div class="highlight"><pre><
|
1138
|
-
</pre></div>
|
1137
|
+
<div class="highlight"><pre class="codehilite"><code><span class="mi">1</span>
|
1138
|
+
</code></pre></div>
|
1139
1139
|
</div>
|
1140
1140
|
HTML
|
1141
1141
|
end
|
@@ -1144,12 +1144,13 @@ describe Qiita::Markdown::Processor do
|
|
1144
1144
|
end
|
1145
1145
|
|
1146
1146
|
shared_examples_for "iframe element" do |allowed:|
|
1147
|
-
|
1147
|
+
shared_examples "iframe element example" do
|
1148
1148
|
let(:markdown) do
|
1149
1149
|
<<-MARKDOWN.strip_heredoc
|
1150
|
-
<iframe width="1" height="2" src="
|
1150
|
+
<iframe width="1" height="2" src="#{url}" frameborder="0" allowfullscreen></iframe>
|
1151
1151
|
MARKDOWN
|
1152
1152
|
end
|
1153
|
+
let(:url) { "#{scheme}//example.com" }
|
1153
1154
|
|
1154
1155
|
if allowed
|
1155
1156
|
it "allows iframe with some attributes" do
|
@@ -1161,6 +1162,20 @@ describe Qiita::Markdown::Processor do
|
|
1161
1162
|
end
|
1162
1163
|
end
|
1163
1164
|
end
|
1165
|
+
|
1166
|
+
context "with iframe" do
|
1167
|
+
context "with scheme" do
|
1168
|
+
let(:scheme) { "https:" }
|
1169
|
+
|
1170
|
+
include_examples "iframe element example"
|
1171
|
+
end
|
1172
|
+
|
1173
|
+
context "without scheme" do
|
1174
|
+
let(:scheme) { "" }
|
1175
|
+
|
1176
|
+
include_examples "iframe element example"
|
1177
|
+
end
|
1178
|
+
end
|
1164
1179
|
end
|
1165
1180
|
|
1166
1181
|
shared_examples_for "input element" do |allowed:|
|
@@ -1451,114 +1466,138 @@ describe Qiita::Markdown::Processor do
|
|
1451
1466
|
end
|
1452
1467
|
end
|
1453
1468
|
|
1454
|
-
context "with HTML embed code for
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1469
|
+
context "with HTML embed code for Youtube" do
|
1470
|
+
shared_examples "embed code youtube example" do
|
1471
|
+
let(:markdown) do
|
1472
|
+
<<-MARKDOWN.strip_heredoc
|
1473
|
+
<iframe width="100" height="100" src="#{url}"></iframe>
|
1474
|
+
MARKDOWN
|
1475
|
+
end
|
1476
|
+
let(:url) { "#{scheme}//www.youtube.com/embed/example" }
|
1460
1477
|
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1478
|
+
if allowed
|
1479
|
+
it "does not sanitize embed code" do
|
1480
|
+
should eq <<-HTML.strip_heredoc
|
1481
|
+
<iframe width="100" height="100" src="#{url}"></iframe>
|
1482
|
+
HTML
|
1483
|
+
end
|
1484
|
+
else
|
1485
|
+
it "forces width attribute on iframe" do
|
1486
|
+
should eq <<-HTML.strip_heredoc
|
1487
|
+
<iframe width="100%" height="100" src="#{url}"></iframe>
|
1488
|
+
HTML
|
1489
|
+
end
|
1466
1490
|
end
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1491
|
+
|
1492
|
+
context "when url is privacy enhanced mode" do
|
1493
|
+
let(:markdown) do
|
1494
|
+
<<-MARKDOWN.strip_heredoc
|
1495
|
+
<iframe width="100" height="100" src="#{url}"></iframe>
|
1496
|
+
MARKDOWN
|
1497
|
+
end
|
1498
|
+
let(:url) { "#{scheme}//www.youtube-nocookie.com/embed/example" }
|
1499
|
+
|
1500
|
+
if allowed
|
1501
|
+
it "does not sanitize embed code" do
|
1502
|
+
should eq <<-HTML.strip_heredoc
|
1503
|
+
<iframe width="100" height="100" src="#{url}"></iframe>
|
1504
|
+
HTML
|
1505
|
+
end
|
1506
|
+
else
|
1507
|
+
it "forces width attribute on iframe" do
|
1508
|
+
should eq <<-HTML.strip_heredoc
|
1509
|
+
<iframe width="100%" height="100" src="#{url}"></iframe>
|
1510
|
+
HTML
|
1511
|
+
end
|
1512
|
+
end
|
1472
1513
|
end
|
1473
1514
|
end
|
1474
|
-
end
|
1475
1515
|
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
MARKDOWN
|
1516
|
+
context "with scheme" do
|
1517
|
+
let(:scheme) { "https:" }
|
1518
|
+
|
1519
|
+
include_examples "embed code youtube example"
|
1481
1520
|
end
|
1482
1521
|
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
HTML
|
1488
|
-
end
|
1489
|
-
else
|
1490
|
-
it "forces width attribute on iframe" do
|
1491
|
-
should eq <<-HTML.strip_heredoc
|
1492
|
-
<iframe width="100%" height="100" src="https://www.youtube.com/embed/example"></iframe>
|
1493
|
-
HTML
|
1494
|
-
end
|
1522
|
+
context "without scheme" do
|
1523
|
+
let(:scheme) { "" }
|
1524
|
+
|
1525
|
+
include_examples "embed code youtube example"
|
1495
1526
|
end
|
1527
|
+
end
|
1496
1528
|
|
1497
|
-
|
1529
|
+
context "with HTML embed code for SlideShare" do
|
1530
|
+
shared_examples "embed code slideshare example" do
|
1498
1531
|
let(:markdown) do
|
1499
1532
|
<<-MARKDOWN.strip_heredoc
|
1500
|
-
<iframe width="100" height="100" src="
|
1533
|
+
<iframe width="100" height="100" src="#{url}"></iframe>
|
1501
1534
|
MARKDOWN
|
1502
1535
|
end
|
1536
|
+
let(:url) { "#{scheme}//www.slideshare.net/embed/example" }
|
1503
1537
|
|
1504
1538
|
if allowed
|
1505
1539
|
it "does not sanitize embed code" do
|
1506
1540
|
should eq <<-HTML.strip_heredoc
|
1507
|
-
<iframe width="100" height="100" src="
|
1541
|
+
<iframe width="100" height="100" src="#{url}"></iframe>
|
1508
1542
|
HTML
|
1509
1543
|
end
|
1510
1544
|
else
|
1511
1545
|
it "forces width attribute on iframe" do
|
1512
1546
|
should eq <<-HTML.strip_heredoc
|
1513
|
-
<iframe width="100%" height="100" src="
|
1547
|
+
<iframe width="100%" height="100" src="#{url}"></iframe>
|
1514
1548
|
HTML
|
1515
1549
|
end
|
1516
1550
|
end
|
1517
1551
|
end
|
1518
|
-
end
|
1519
1552
|
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
MARKDOWN
|
1553
|
+
context "with scheme" do
|
1554
|
+
let(:scheme) { "https:" }
|
1555
|
+
|
1556
|
+
include_examples "embed code slideshare example"
|
1525
1557
|
end
|
1526
1558
|
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
HTML
|
1532
|
-
end
|
1533
|
-
else
|
1534
|
-
it "forces width attribute on iframe" do
|
1535
|
-
should eq <<-HTML.strip_heredoc
|
1536
|
-
<iframe width="100%" height="100" src="https://www.slideshare.net/embed/example"></iframe>
|
1537
|
-
HTML
|
1538
|
-
end
|
1559
|
+
context "without scheme" do
|
1560
|
+
let(:scheme) { "" }
|
1561
|
+
|
1562
|
+
include_examples "embed code slideshare example"
|
1539
1563
|
end
|
1540
1564
|
end
|
1541
1565
|
|
1542
1566
|
context "with HTML embed code for GoogleSlide" do
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
if allowed
|
1550
|
-
it "does not sanitize embed code" do
|
1551
|
-
should eq <<-HTML.strip_heredoc
|
1552
|
-
<iframe src="https://docs.google.com/presentation/d/example/embed" frameborder="0" width="482" height="300" allowfullscreen="true"></iframe>
|
1553
|
-
HTML
|
1567
|
+
shared_examples "embed code googleslide example" do
|
1568
|
+
let(:markdown) do
|
1569
|
+
<<-MARKDOWN.strip_heredoc
|
1570
|
+
<iframe src="#{url}" frameborder="0" width="482" height="300" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
|
1571
|
+
MARKDOWN
|
1554
1572
|
end
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1573
|
+
let(:url) { "#{scheme}//docs.google.com/presentation/d/example/embed" }
|
1574
|
+
|
1575
|
+
if allowed
|
1576
|
+
it "does not sanitize embed code" do
|
1577
|
+
should eq <<-HTML.strip_heredoc
|
1578
|
+
<iframe src="#{url}" frameborder="0" width="482" height="300" allowfullscreen="true"></iframe>
|
1579
|
+
HTML
|
1580
|
+
end
|
1581
|
+
else
|
1582
|
+
it "forces width attribute on iframe" do
|
1583
|
+
should eq <<-HTML.strip_heredoc
|
1584
|
+
<iframe src="#{url}" frameborder="0" width="100%" height="300" allowfullscreen="true"></iframe>
|
1585
|
+
HTML
|
1586
|
+
end
|
1560
1587
|
end
|
1561
1588
|
end
|
1589
|
+
|
1590
|
+
context "with scheme" do
|
1591
|
+
let(:scheme) { "https:" }
|
1592
|
+
|
1593
|
+
include_examples "embed code googleslide example"
|
1594
|
+
end
|
1595
|
+
|
1596
|
+
context "without scheme" do
|
1597
|
+
let(:scheme) { "" }
|
1598
|
+
|
1599
|
+
include_examples "embed code googleslide example"
|
1600
|
+
end
|
1562
1601
|
end
|
1563
1602
|
|
1564
1603
|
context "with HTML embed code for SpeekerDeck" do
|
@@ -1604,11 +1643,15 @@ describe Qiita::Markdown::Processor do
|
|
1604
1643
|
<<-MARKDOWN.strip_heredoc
|
1605
1644
|
<script async class="speakerdeck-embed" data-id="example" data-ratio="1.33333333333333" src="javascript://speakerdeck.com/assets/embed.js"></script>
|
1606
1645
|
MARKDOWN
|
1646
|
+
end
|
1607
1647
|
|
1648
|
+
if allowed
|
1649
|
+
it "does not sanitize embed code" do
|
1650
|
+
should eq markdown
|
1651
|
+
end
|
1652
|
+
else
|
1608
1653
|
it "forces width attribute on iframe" do
|
1609
|
-
should eq
|
1610
|
-
\n
|
1611
|
-
HTML
|
1654
|
+
should eq "\n"
|
1612
1655
|
end
|
1613
1656
|
end
|
1614
1657
|
end
|
@@ -1618,12 +1661,127 @@ describe Qiita::Markdown::Processor do
|
|
1618
1661
|
<<-MARKDOWN.strip_heredoc
|
1619
1662
|
<iframe src="javascript://docs.google.com:80/%0d%0aalert(document.domain)" frameborder="0" width="482" height="300" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
|
1620
1663
|
MARKDOWN
|
1664
|
+
end
|
1621
1665
|
|
1622
|
-
|
1666
|
+
if allowed
|
1667
|
+
it "does not sanitize embed code" do
|
1623
1668
|
should eq <<-HTML.strip_heredoc
|
1624
|
-
|
1669
|
+
<iframe src="javascript://docs.google.com:80/%0d%0aalert(document.domain)" frameborder="0" width="482" height="300" allowfullscreen="true"></iframe>
|
1625
1670
|
HTML
|
1626
1671
|
end
|
1672
|
+
else
|
1673
|
+
it "forces width attribute on iframe" do
|
1674
|
+
should eq "\n"
|
1675
|
+
end
|
1676
|
+
end
|
1677
|
+
end
|
1678
|
+
end
|
1679
|
+
|
1680
|
+
shared_examples_for "custom block" do |allowed:|
|
1681
|
+
context "with custom block" do
|
1682
|
+
let(:type) { "" }
|
1683
|
+
let(:subtype) { "" }
|
1684
|
+
|
1685
|
+
let(:markdown) do
|
1686
|
+
<<-MARKDOWN.strip_heredoc
|
1687
|
+
:::#{[type, subtype].join(' ').rstrip}
|
1688
|
+
Some kind of text is here.
|
1689
|
+
:::
|
1690
|
+
MARKDOWN
|
1691
|
+
end
|
1692
|
+
|
1693
|
+
context "when type is not allowed" do
|
1694
|
+
let(:type) { "anytype" }
|
1695
|
+
|
1696
|
+
if allowed
|
1697
|
+
it "returns simple div element" do
|
1698
|
+
should eq <<-HTML.strip_heredoc
|
1699
|
+
<div data-type="customblock" data-metadata="anytype">Some kind of text is here.
|
1700
|
+
</div>
|
1701
|
+
HTML
|
1702
|
+
end
|
1703
|
+
else
|
1704
|
+
it "returns simple div element" do
|
1705
|
+
should eq <<-HTML.strip_heredoc
|
1706
|
+
<div>Some kind of text is here.
|
1707
|
+
</div>
|
1708
|
+
HTML
|
1709
|
+
end
|
1710
|
+
end
|
1711
|
+
end
|
1712
|
+
|
1713
|
+
context "when type is note" do
|
1714
|
+
let(:type) { "note" }
|
1715
|
+
|
1716
|
+
context "when subtype is empty" do
|
1717
|
+
if allowed
|
1718
|
+
it "returns info note block with class including icon as default type" do
|
1719
|
+
should eq <<-HTML.strip_heredoc
|
1720
|
+
<div data-type="customblock" data-metadata="note" class="note info">
|
1721
|
+
<span class="fa fa-fw fa-check-circle"></span><p>Some kind of text is here.
|
1722
|
+
</p>
|
1723
|
+
</div>
|
1724
|
+
HTML
|
1725
|
+
end
|
1726
|
+
else
|
1727
|
+
it "returns note block with class including icon" do
|
1728
|
+
should eq <<-HTML.strip_heredoc
|
1729
|
+
<div class="note info">
|
1730
|
+
<span class="fa fa-fw fa-check-circle"></span><p>Some kind of text is here.
|
1731
|
+
</p>
|
1732
|
+
</div>
|
1733
|
+
HTML
|
1734
|
+
end
|
1735
|
+
end
|
1736
|
+
end
|
1737
|
+
|
1738
|
+
context "when subtype is warn" do
|
1739
|
+
let(:subtype) { "warn" }
|
1740
|
+
|
1741
|
+
if allowed
|
1742
|
+
it "returns warning note block with class including icon" do
|
1743
|
+
should eq <<-HTML.strip_heredoc
|
1744
|
+
<div data-type="customblock" data-metadata="note warn" class="note warn">
|
1745
|
+
<span class="fa fa-fw fa-exclamation-circle"></span><p>Some kind of text is here.
|
1746
|
+
</p>
|
1747
|
+
</div>
|
1748
|
+
HTML
|
1749
|
+
end
|
1750
|
+
else
|
1751
|
+
it "returns note block with class including icon" do
|
1752
|
+
should eq <<-HTML.strip_heredoc
|
1753
|
+
<div class="note warn">
|
1754
|
+
<span class="fa fa-fw fa-exclamation-circle"></span><p>Some kind of text is here.
|
1755
|
+
</p>
|
1756
|
+
</div>
|
1757
|
+
HTML
|
1758
|
+
end
|
1759
|
+
end
|
1760
|
+
end
|
1761
|
+
|
1762
|
+
context "when subtype is alert" do
|
1763
|
+
let(:subtype) { "alert" }
|
1764
|
+
|
1765
|
+
if allowed
|
1766
|
+
it "returns alerting note block with class including icon" do
|
1767
|
+
should eq <<-HTML.strip_heredoc
|
1768
|
+
<div data-type="customblock" data-metadata="note alert" class="note alert">
|
1769
|
+
<span class="fa fa-fw fa-times-circle"></span><p>Some kind of text is here.
|
1770
|
+
</p>
|
1771
|
+
</div>
|
1772
|
+
HTML
|
1773
|
+
end
|
1774
|
+
else
|
1775
|
+
it "returns note block with class including icon" do
|
1776
|
+
should eq <<-HTML.strip_heredoc
|
1777
|
+
<div class="note alert">
|
1778
|
+
<span class="fa fa-fw fa-times-circle"></span><p>Some kind of text is here.
|
1779
|
+
</p>
|
1780
|
+
</div>
|
1781
|
+
HTML
|
1782
|
+
end
|
1783
|
+
end
|
1784
|
+
end
|
1627
1785
|
end
|
1628
1786
|
end
|
1629
1787
|
end
|
@@ -1642,6 +1800,7 @@ describe Qiita::Markdown::Processor do
|
|
1642
1800
|
include_examples "class attribute", allowed: true
|
1643
1801
|
include_examples "background-color", allowed: true
|
1644
1802
|
include_examples "override embed code attributes", allowed: false
|
1803
|
+
include_examples "custom block", allowed: false
|
1645
1804
|
end
|
1646
1805
|
|
1647
1806
|
context "with script context" do
|
@@ -1658,6 +1817,7 @@ describe Qiita::Markdown::Processor do
|
|
1658
1817
|
include_examples "class attribute", allowed: true
|
1659
1818
|
include_examples "background-color", allowed: true
|
1660
1819
|
include_examples "override embed code attributes", allowed: true
|
1820
|
+
include_examples "custom block", allowed: true
|
1661
1821
|
end
|
1662
1822
|
|
1663
1823
|
context "with strict context" do
|
@@ -1674,6 +1834,7 @@ describe Qiita::Markdown::Processor do
|
|
1674
1834
|
include_examples "class attribute", allowed: false
|
1675
1835
|
include_examples "background-color", allowed: false
|
1676
1836
|
include_examples "override embed code attributes", allowed: false
|
1837
|
+
include_examples "custom block", allowed: false
|
1677
1838
|
end
|
1678
1839
|
|
1679
1840
|
context "with script and strict context" do
|
@@ -1690,6 +1851,7 @@ describe Qiita::Markdown::Processor do
|
|
1690
1851
|
include_examples "class attribute", allowed: false
|
1691
1852
|
include_examples "background-color", allowed: false
|
1692
1853
|
include_examples "override embed code attributes", allowed: false
|
1854
|
+
include_examples "custom block", allowed: true
|
1693
1855
|
end
|
1694
1856
|
end
|
1695
1857
|
end
|
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.38.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Nakamura
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gemoji
|
@@ -67,33 +67,33 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rouge
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 3.26.0
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 3.26.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: greenmat
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - '='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 3.5.1.
|
89
|
+
version: 3.5.1.2
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 3.5.1.
|
96
|
+
version: 3.5.1.2
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: sanitize
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -234,7 +234,7 @@ dependencies:
|
|
234
234
|
- - '='
|
235
235
|
- !ruby/object:Gem::Version
|
236
236
|
version: 0.49.1
|
237
|
-
description:
|
237
|
+
description:
|
238
238
|
email:
|
239
239
|
- r7kamura@gmail.com
|
240
240
|
executables: []
|
@@ -258,7 +258,6 @@ 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
261
|
- lib/qiita/markdown/embed/google_slide.rb
|
263
262
|
- lib/qiita/markdown/embed/slide_share.rb
|
264
263
|
- lib/qiita/markdown/embed/speeker_deck.rb
|
@@ -266,6 +265,7 @@ files:
|
|
266
265
|
- lib/qiita/markdown/embed/youtube.rb
|
267
266
|
- lib/qiita/markdown/filters/checkbox.rb
|
268
267
|
- lib/qiita/markdown/filters/code_block.rb
|
268
|
+
- lib/qiita/markdown/filters/custom_block.rb
|
269
269
|
- lib/qiita/markdown/filters/emoji.rb
|
270
270
|
- lib/qiita/markdown/filters/external_link.rb
|
271
271
|
- lib/qiita/markdown/filters/final_sanitizer.rb
|
@@ -301,7 +301,7 @@ homepage: https://github.com/increments/qiita-markdown
|
|
301
301
|
licenses:
|
302
302
|
- MIT
|
303
303
|
metadata: {}
|
304
|
-
post_install_message:
|
304
|
+
post_install_message:
|
305
305
|
rdoc_options: []
|
306
306
|
require_paths:
|
307
307
|
- lib
|
@@ -317,7 +317,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
317
317
|
version: '0'
|
318
318
|
requirements: []
|
319
319
|
rubygems_version: 3.0.3
|
320
|
-
signing_key:
|
320
|
+
signing_key:
|
321
321
|
specification_version: 4
|
322
322
|
summary: Qiita-specified markdown processor.
|
323
323
|
test_files:
|