qiita-markdown 0.31.0 → 0.36.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 +20 -0
- data/lib/qiita/markdown.rb +1 -1
- data/lib/qiita/markdown/filters/custom_block.rb +63 -0
- data/lib/qiita/markdown/filters/greenmat.rb +1 -0
- 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 +6 -2
- data/lib/qiita/markdown/transformers/filter_script.rb +5 -3
- data/lib/qiita/markdown/version.rb +1 -1
- data/qiita-markdown.gemspec +1 -1
- data/spec/qiita/markdown/processor_spec.rb +274 -52
- metadata +6 -6
- 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: c87f030f51598557770e12094601817c916a8e468cd030aeead44855b982dd14
|
4
|
+
data.tar.gz: 93a458246834fe89530ae20396dbffc98436be494331df2505359727e4fea92d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c94ef6737d7881c6ab6ebb7078eb9b24be05d3804362cdde38d37f16397cb2a635f1b1d7a215d61e57effa0f1043eb2c6f901d70dff6b70ae2595e2c446208e0
|
7
|
+
data.tar.gz: 7e8941da6683eb93716e05ecb89528b6208ceac2f02107c43aa3792ff6ddc302ed0fba27a7bf8a0cd488e8c66e27dc53a7c6432981e7c9b7961e24c41094cee3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
|
+
## 0.36.0
|
4
|
+
- Support message notation
|
5
|
+
|
6
|
+
## 0.35.0
|
7
|
+
|
8
|
+
- Allow Relative URL in iframe src attributes
|
9
|
+
|
10
|
+
## 0.34.0
|
11
|
+
|
12
|
+
- Delete gist embed rule to avoid XSS
|
13
|
+
|
14
|
+
## 0.33.0
|
15
|
+
|
16
|
+
- Fix XSS possibility bug
|
17
|
+
|
18
|
+
## 0.32.0
|
19
|
+
|
20
|
+
- Fix XSS possibility bug
|
21
|
+
- Fix iframe width to be fixed at 100%
|
22
|
+
|
3
23
|
## 0.31.0
|
4
24
|
|
5
25
|
- Use greenmat 3.5.1.1
|
data/lib/qiita/markdown.rb
CHANGED
@@ -10,7 +10,6 @@ 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
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 = %(message).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 Message
|
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"] = "message #{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,
|
@@ -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],
|
@@ -22,6 +22,7 @@ module Qiita
|
|
22
22
|
def transform
|
23
23
|
if name == "iframe"
|
24
24
|
if URL_WHITE_LIST.include?(node["src"]) || HOST_WHITE_LIST.include?(host_of(node["src"]))
|
25
|
+
node["width"] = "100%"
|
25
26
|
node.children.unlink
|
26
27
|
else
|
27
28
|
node.unlink
|
@@ -40,8 +41,11 @@ module Qiita
|
|
40
41
|
end
|
41
42
|
|
42
43
|
def host_of(url)
|
43
|
-
|
44
|
-
|
44
|
+
if url
|
45
|
+
scheme = URI.parse(url).scheme
|
46
|
+
Addressable::URI.parse(url).host if ["http", "https", nil].include? scheme
|
47
|
+
end
|
48
|
+
rescue Addressable::URI::InvalidURIError, URI::InvalidURIError
|
45
49
|
nil
|
46
50
|
end
|
47
51
|
end
|
@@ -10,7 +10,6 @@ module Qiita
|
|
10
10
|
|
11
11
|
HOST_WHITE_LIST = [
|
12
12
|
Embed::Asciinema::SCRIPT_HOST,
|
13
|
-
Embed::Gist::SCRIPT_HOST,
|
14
13
|
].flatten.freeze
|
15
14
|
|
16
15
|
def self.call(*args)
|
@@ -43,8 +42,11 @@ module Qiita
|
|
43
42
|
end
|
44
43
|
|
45
44
|
def host_of(url)
|
46
|
-
|
47
|
-
|
45
|
+
if url
|
46
|
+
scheme = URI.parse(url).scheme
|
47
|
+
Addressable::URI.parse(url).host if ["http", "https"].include? scheme
|
48
|
+
end
|
49
|
+
rescue Addressable::URI::InvalidURIError, URI::InvalidURIError
|
48
50
|
nil
|
49
51
|
end
|
50
52
|
end
|
data/qiita-markdown.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_dependency "html-pipeline", "~> 2.0"
|
24
24
|
spec.add_dependency "mem"
|
25
25
|
spec.add_dependency "pygments.rb", "~> 1.0"
|
26
|
-
spec.add_dependency "greenmat", "3.5.1.
|
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"
|
@@ -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,81 +1466,137 @@ 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
|
-
|
1522
|
+
context "without scheme" do
|
1523
|
+
let(:scheme) { "" }
|
1524
|
+
|
1525
|
+
include_examples "embed code youtube example"
|
1487
1526
|
end
|
1527
|
+
end
|
1488
1528
|
|
1489
|
-
|
1529
|
+
context "with HTML embed code for SlideShare" do
|
1530
|
+
shared_examples "embed code slideshare example" do
|
1490
1531
|
let(:markdown) do
|
1491
1532
|
<<-MARKDOWN.strip_heredoc
|
1492
|
-
<iframe width="100" height="100" src="
|
1533
|
+
<iframe width="100" height="100" src="#{url}"></iframe>
|
1493
1534
|
MARKDOWN
|
1494
1535
|
end
|
1536
|
+
let(:url) { "#{scheme}//www.slideshare.net/embed/example" }
|
1495
1537
|
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1538
|
+
if allowed
|
1539
|
+
it "does not sanitize embed code" do
|
1540
|
+
should eq <<-HTML.strip_heredoc
|
1541
|
+
<iframe width="100" height="100" src="#{url}"></iframe>
|
1542
|
+
HTML
|
1543
|
+
end
|
1544
|
+
else
|
1545
|
+
it "forces width attribute on iframe" do
|
1546
|
+
should eq <<-HTML.strip_heredoc
|
1547
|
+
<iframe width="100%" height="100" src="#{url}"></iframe>
|
1548
|
+
HTML
|
1549
|
+
end
|
1500
1550
|
end
|
1501
1551
|
end
|
1502
|
-
end
|
1503
1552
|
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
MARKDOWN
|
1553
|
+
context "with scheme" do
|
1554
|
+
let(:scheme) { "https:" }
|
1555
|
+
|
1556
|
+
include_examples "embed code slideshare example"
|
1509
1557
|
end
|
1510
1558
|
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1559
|
+
context "without scheme" do
|
1560
|
+
let(:scheme) { "" }
|
1561
|
+
|
1562
|
+
include_examples "embed code slideshare example"
|
1515
1563
|
end
|
1516
1564
|
end
|
1517
1565
|
|
1518
1566
|
context "with HTML embed code for GoogleSlide" do
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
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
|
1572
|
+
end
|
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
|
1587
|
+
end
|
1523
1588
|
end
|
1524
1589
|
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
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"
|
1529
1600
|
end
|
1530
1601
|
end
|
1531
1602
|
|
@@ -1566,6 +1637,153 @@ describe Qiita::Markdown::Processor do
|
|
1566
1637
|
HTML
|
1567
1638
|
end
|
1568
1639
|
end
|
1640
|
+
|
1641
|
+
context "with embed script code with xss" do
|
1642
|
+
let(:markdown) do
|
1643
|
+
<<-MARKDOWN.strip_heredoc
|
1644
|
+
<script async class="speakerdeck-embed" data-id="example" data-ratio="1.33333333333333" src="javascript://speakerdeck.com/assets/embed.js"></script>
|
1645
|
+
MARKDOWN
|
1646
|
+
end
|
1647
|
+
|
1648
|
+
if allowed
|
1649
|
+
it "does not sanitize embed code" do
|
1650
|
+
should eq markdown
|
1651
|
+
end
|
1652
|
+
else
|
1653
|
+
it "forces width attribute on iframe" do
|
1654
|
+
should eq "\n"
|
1655
|
+
end
|
1656
|
+
end
|
1657
|
+
end
|
1658
|
+
|
1659
|
+
context "with embed iframe code with xss" do
|
1660
|
+
let(:markdown) do
|
1661
|
+
<<-MARKDOWN.strip_heredoc
|
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>
|
1663
|
+
MARKDOWN
|
1664
|
+
end
|
1665
|
+
|
1666
|
+
if allowed
|
1667
|
+
it "does not sanitize embed code" do
|
1668
|
+
should eq <<-HTML.strip_heredoc
|
1669
|
+
<iframe src="javascript://docs.google.com:80/%0d%0aalert(document.domain)" frameborder="0" width="482" height="300" allowfullscreen="true"></iframe>
|
1670
|
+
HTML
|
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 message" do
|
1714
|
+
let(:type) { "message" }
|
1715
|
+
|
1716
|
+
context "when subtype is empty" do
|
1717
|
+
if allowed
|
1718
|
+
it "returns info message block with class including icon as default type" do
|
1719
|
+
should eq <<-HTML.strip_heredoc
|
1720
|
+
<div data-type="customblock" data-metadata="message" class="message 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 message block with class including icon" do
|
1728
|
+
should eq <<-HTML.strip_heredoc
|
1729
|
+
<div class="message 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 message block with class including icon" do
|
1743
|
+
should eq <<-HTML.strip_heredoc
|
1744
|
+
<div data-type="customblock" data-metadata="message warn" class="message 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 message block with class including icon" do
|
1752
|
+
should eq <<-HTML.strip_heredoc
|
1753
|
+
<div class="message 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 message block with class including icon" do
|
1767
|
+
should eq <<-HTML.strip_heredoc
|
1768
|
+
<div data-type="customblock" data-metadata="message alert" class="message 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 message block with class including icon" do
|
1776
|
+
should eq <<-HTML.strip_heredoc
|
1777
|
+
<div class="message 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
|
1785
|
+
end
|
1786
|
+
end
|
1569
1787
|
end
|
1570
1788
|
|
1571
1789
|
context "without script and strict context" do
|
@@ -1582,6 +1800,7 @@ describe Qiita::Markdown::Processor do
|
|
1582
1800
|
include_examples "class attribute", allowed: true
|
1583
1801
|
include_examples "background-color", allowed: true
|
1584
1802
|
include_examples "override embed code attributes", allowed: false
|
1803
|
+
include_examples "custom block", allowed: false
|
1585
1804
|
end
|
1586
1805
|
|
1587
1806
|
context "with script context" do
|
@@ -1598,6 +1817,7 @@ describe Qiita::Markdown::Processor do
|
|
1598
1817
|
include_examples "class attribute", allowed: true
|
1599
1818
|
include_examples "background-color", allowed: true
|
1600
1819
|
include_examples "override embed code attributes", allowed: true
|
1820
|
+
include_examples "custom block", allowed: true
|
1601
1821
|
end
|
1602
1822
|
|
1603
1823
|
context "with strict context" do
|
@@ -1614,6 +1834,7 @@ describe Qiita::Markdown::Processor do
|
|
1614
1834
|
include_examples "class attribute", allowed: false
|
1615
1835
|
include_examples "background-color", allowed: false
|
1616
1836
|
include_examples "override embed code attributes", allowed: false
|
1837
|
+
include_examples "custom block", allowed: false
|
1617
1838
|
end
|
1618
1839
|
|
1619
1840
|
context "with script and strict context" do
|
@@ -1630,6 +1851,7 @@ describe Qiita::Markdown::Processor do
|
|
1630
1851
|
include_examples "class attribute", allowed: false
|
1631
1852
|
include_examples "background-color", allowed: false
|
1632
1853
|
include_examples "override embed code attributes", allowed: false
|
1854
|
+
include_examples "custom block", allowed: true
|
1633
1855
|
end
|
1634
1856
|
end
|
1635
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.36.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-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gemoji
|
@@ -86,14 +86,14 @@ dependencies:
|
|
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
|
@@ -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
|
@@ -316,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
316
316
|
- !ruby/object:Gem::Version
|
317
317
|
version: '0'
|
318
318
|
requirements: []
|
319
|
-
rubygems_version: 3.
|
319
|
+
rubygems_version: 3.1.4
|
320
320
|
signing_key:
|
321
321
|
specification_version: 4
|
322
322
|
summary: Qiita-specified markdown processor.
|