qiita-markdown 0.32.0 → 0.37.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -1
- 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 +3 -3
- data/lib/qiita/markdown/transformers/filter_script.rb +3 -4
- data/lib/qiita/markdown/version.rb +1 -1
- data/qiita-markdown.gemspec +1 -1
- data/spec/qiita/markdown/processor_spec.rb +242 -80
- metadata +9 -9
- 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: a632599e029a2372e999818df8cf19474233cdafe5b0454b944d6fe93d4423ca
|
4
|
+
data.tar.gz: 6ee085f30d1b6008fe9ada38b62c91f6a7d5b68e0f656f20afdc69b5aa067c96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7d84a2dd88cd53380b8b7c5ec3264ae3cbcdf29c718031dfb9d22038d7349ffeaa2cba6e6a8654b3d357c4c7a28994fecdc51f8381cdbff276930a4238ab866
|
7
|
+
data.tar.gz: 78bcee81ab1f08a311e7bf73f9bcbe6c79234c0ed999da679c285f10d69d482bf9c6e3373b2eb39896e2b8cdcd0890631539adf9fe6bfe69250f84ddcd1f4df1
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,26 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
|
+
## 0.37.0
|
4
|
+
- Change keyword of notation
|
5
|
+
|
6
|
+
## 0.36.0
|
7
|
+
- Support message notation
|
8
|
+
|
9
|
+
## 0.35.0
|
10
|
+
|
11
|
+
- Allow Relative URL in iframe src attributes
|
12
|
+
|
13
|
+
## 0.34.0
|
14
|
+
|
15
|
+
- Delete gist embed rule to avoid XSS
|
16
|
+
|
17
|
+
## 0.33.0
|
18
|
+
|
19
|
+
- Fix XSS possibility bug
|
20
|
+
|
3
21
|
## 0.32.0
|
4
22
|
|
5
|
-
-
|
23
|
+
- Fix XSS possibility bug
|
6
24
|
- Fix iframe width to be fixed at 100%
|
7
25
|
|
8
26
|
## 0.31.0
|
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 = %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,
|
@@ -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],
|
@@ -42,10 +42,10 @@ module Qiita
|
|
42
42
|
|
43
43
|
def host_of(url)
|
44
44
|
if url
|
45
|
-
|
46
|
-
Addressable::URI.parse(url).host if [
|
45
|
+
scheme = URI.parse(url).scheme
|
46
|
+
Addressable::URI.parse(url).host if ["http", "https", nil].include? scheme
|
47
47
|
end
|
48
|
-
rescue Addressable::URI::InvalidURIError
|
48
|
+
rescue Addressable::URI::InvalidURIError, URI::InvalidURIError
|
49
49
|
nil
|
50
50
|
end
|
51
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)
|
@@ -44,10 +43,10 @@ module Qiita
|
|
44
43
|
|
45
44
|
def host_of(url)
|
46
45
|
if url
|
47
|
-
|
48
|
-
Addressable::URI.parse(url).host if [
|
46
|
+
scheme = URI.parse(url).scheme
|
47
|
+
Addressable::URI.parse(url).host if ["http", "https"].include? scheme
|
49
48
|
end
|
50
|
-
rescue Addressable::URI::InvalidURIError
|
49
|
+
rescue Addressable::URI::InvalidURIError, URI::InvalidURIError
|
51
50
|
nil
|
52
51
|
end
|
53
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,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
|
@@ -1616,14 +1659,129 @@ describe Qiita::Markdown::Processor do
|
|
1616
1659
|
context "with embed iframe code with xss" do
|
1617
1660
|
let(:markdown) do
|
1618
1661
|
<<-MARKDOWN.strip_heredoc
|
1619
|
-
<iframe src="javascript://docs.google.com
|
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.37.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
|
@@ -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
|
@@ -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:
|