qiita-markdown 0.21.0 → 0.22.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f4ebdec684801c23c2b2183ea2498383180d4382
4
- data.tar.gz: ebaf06c2afa12f825f6b21a122e36705da59bf13
3
+ metadata.gz: ff3cf2974ec3776febf776a8509ea134b7e6b94d
4
+ data.tar.gz: 16d059b677b0cf622be0d3c85e4ad9e293ffcdef
5
5
  SHA512:
6
- metadata.gz: e237616c63dfb7d0a6f332c4b8327afcf39bfa3ea285767890efb49fcb43ffa1b7563b8943248fd5f8948abc4875d462c3382268f53b27214bd6e2d42a318dcb
7
- data.tar.gz: 7c7d5e9a117e28d883ec45c2e7cab9dba35b39ad468ca16a372f7403a6b2f9c74fd74b2e151f42e1b497d525701a46c6c224e46a548fb481ccc7374f54473fe6
6
+ metadata.gz: ab3e0be1351d8872fc3cc8d75502a3f8bd95f24a9870af84c164676b52e84f0ee34a72f7321db28c3889d133d167ec14c1ef32d0de9da3a918b0f4cdc4c43496
7
+ data.tar.gz: b91800c0d2282cc001d7fa9df45f1688f721c47d82ab5a01b62e656a10f2ccb7d8a18901076261bbc0ef88945ba87f042fd9cc54001b2638def2ebbfa83fe47e
data/.rubocop_todo.yml CHANGED
@@ -57,6 +57,7 @@ Style/MutableConstant:
57
57
  - 'lib/qiita/markdown/filters/sanitize.rb'
58
58
  - 'lib/qiita/markdown/filters/simplify.rb'
59
59
  - 'lib/qiita/markdown/filters/syntax_highlight.rb'
60
+ - 'lib/qiita/markdown/code_pen.rb'
60
61
  - 'lib/qiita/markdown/processor.rb'
61
62
  - 'lib/qiita/markdown/summary_processor.rb'
62
63
  - 'lib/qiita/markdown/version.rb'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## Unreleased
2
2
 
3
+ ## 0.22.0
4
+
5
+ - Support embed CodePen
6
+
3
7
  ## 0.21.0
4
8
 
5
9
  - Rename `Code` to `CodeBlock`
@@ -7,6 +7,10 @@ require "nokogiri"
7
7
  require "pygments"
8
8
  require "sanitize"
9
9
 
10
+ require "qiita/markdown/code_pen"
11
+ require "qiita/markdown/transformers/filter_attributes"
12
+ require "qiita/markdown/transformers/filter_script"
13
+ require "qiita/markdown/transformers/strip_invalid_node"
10
14
  require "qiita/markdown/filters/checkbox"
11
15
  require "qiita/markdown/filters/code_block"
12
16
  require "qiita/markdown/filters/emoji"
@@ -0,0 +1,8 @@
1
+ module Qiita
2
+ module Markdown
3
+ module CodePen
4
+ SCRIPT_URL = "https://production-assets.codepen.io/assets/embed/ei.js"
5
+ ATTRIBUTES = %w[class data-embed-version data-slug-hash]
6
+ end
7
+ end
8
+ end
@@ -10,45 +10,6 @@ module Qiita
10
10
  #
11
11
  # @see Qiita::Markdown::Filters::UserInputSanitizerr
12
12
  class FinalSanitizer < HTML::Pipeline::Filter
13
- # Wraps a node env to transform invalid node.
14
- class TransformableNode
15
- def self.call(*args)
16
- new(*args).transform
17
- end
18
-
19
- def initialize(env)
20
- @env = env
21
- end
22
-
23
- def transform
24
- if has_invalid_list_node? || has_invalid_table_node?
25
- node.replace(node.children)
26
- end
27
- end
28
-
29
- private
30
-
31
- def has_invalid_list_node?
32
- name == "li" && node.ancestors.none? do |ancestor|
33
- %w[ol ul].include?(ancestor.name)
34
- end
35
- end
36
-
37
- def has_invalid_table_node?
38
- %w[thead tbody tfoot tr td th].include?(name) && node.ancestors.none? do |ancestor|
39
- ancestor.name == "table"
40
- end
41
- end
42
-
43
- def name
44
- @env[:node_name]
45
- end
46
-
47
- def node
48
- @env[:node]
49
- end
50
- end
51
-
52
13
  RULE = {
53
14
  attributes: {
54
15
  "a" => [
@@ -80,6 +41,7 @@ module Qiita
80
41
  "itemscope",
81
42
  "itemtype",
82
43
  ],
44
+ "p" => CodePen::ATTRIBUTES,
83
45
  "script" => [
84
46
  "async",
85
47
  "src",
@@ -173,6 +135,7 @@ module Qiita
173
135
  "ruby",
174
136
  "s",
175
137
  "samp",
138
+ "script",
176
139
  "span",
177
140
  "strike",
178
141
  "strong",
@@ -219,17 +182,17 @@ module Qiita
219
182
  ],
220
183
  },
221
184
  },
222
- remove_contents: [
223
- "script",
185
+ transformers: [
186
+ Transformers::StripInvalidNode,
187
+ Transformers::FilterScript,
224
188
  ],
225
- transformers: TransformableNode,
226
189
  }.freeze
227
190
 
228
191
  SCRIPTABLE_RULE = RULE.dup.tap do |rule|
229
192
  rule[:attributes] = RULE[:attributes].dup
230
193
  rule[:attributes][:all] = rule[:attributes][:all] + [:data]
231
194
  rule[:elements] = RULE[:elements] + ["iframe", "script", "video"]
232
- rule[:remove_contents] = []
195
+ rule[:transformers] = rule[:transformers] - [Transformers::FilterScript]
233
196
  end
234
197
 
235
198
  def call
@@ -3,65 +3,10 @@ module Qiita
3
3
  module Filters
4
4
  # Sanitizes user input if :strict context is given.
5
5
  class UserInputSanitizer < HTML::Pipeline::Filter
6
- class AttributeFilter
7
- FILTERS = {
8
- "a" => {
9
- "class" => %w[autolink],
10
- "rel" => %w[footnote url],
11
- "rev" => %w[footnote],
12
- },
13
- "blockquote" => {
14
- "class" => %w[twitter-tweet],
15
- },
16
- "div" => {
17
- "class" => %w[footnotes],
18
- },
19
- "sup" => {
20
- "id" => /\Afnref\d+\z/,
21
- },
22
- "li" => {
23
- "id" => /\Afn\d+\z/,
24
- },
25
- }.freeze
26
-
27
- DELIMITER = " ".freeze
28
-
29
- def self.call(*args)
30
- new(*args).transform
31
- end
32
-
33
- def initialize(env)
34
- @env = env
35
- end
36
-
37
- def transform
38
- return unless FILTERS.key?(name)
39
- FILTERS[name].each_pair do |attr, pattern|
40
- filter_attribute(attr, pattern) if node.attributes.key?(attr)
41
- end
42
- end
43
-
44
- private
45
-
46
- def filter_attribute(attr, pattern)
47
- node[attr] = node[attr].split(DELIMITER).select do |value|
48
- pattern.is_a?(Array) ? pattern.include?(value) : (pattern =~ value)
49
- end.join(DELIMITER)
50
- end
51
-
52
- def name
53
- @env[:node_name]
54
- end
55
-
56
- def node
57
- @env[:node]
58
- end
59
- end
60
-
61
6
  RULE = {
62
7
  elements: %w[
63
8
  a b blockquote br code dd del details div dl dt em font h1 h2 h3 h4 h5 h6
64
- hr i img ins kbd li ol p pre q rp rt ruby s samp strike strong sub
9
+ hr i img ins kbd li ol p pre q rp rt ruby s samp script strike strong sub
65
10
  summary sup table tbody td tfoot th thead tr ul var
66
11
  ],
67
12
  attributes: {
@@ -79,7 +24,9 @@ module Qiita
79
24
  "img" => %w[alt height src title width],
80
25
  "ins" => %w[cite datetime],
81
26
  "li" => %w[id],
27
+ "p" => CodePen::ATTRIBUTES,
82
28
  "q" => %w[cite],
29
+ "script" => %w[async src],
83
30
  "sup" => %w[id],
84
31
  "td" => %w[colspan rowspan style],
85
32
  "th" => %w[colspan rowspan style],
@@ -92,10 +39,10 @@ module Qiita
92
39
  css: {
93
40
  properties: %w[text-align],
94
41
  },
95
- remove_contents: %w[
96
- script
42
+ transformers: [
43
+ Transformers::FilterAttributes,
44
+ Transformers::FilterScript,
97
45
  ],
98
- transformers: AttributeFilter,
99
46
  }.freeze
100
47
 
101
48
  def call
@@ -0,0 +1,63 @@
1
+ module Qiita
2
+ module Markdown
3
+ module Transformers
4
+ class FilterAttributes
5
+ FILTERS = {
6
+ "a" => {
7
+ "class" => %w[autolink],
8
+ "rel" => %w[footnote url],
9
+ "rev" => %w[footnote],
10
+ },
11
+ "blockquote" => {
12
+ "class" => %w[twitter-tweet],
13
+ },
14
+ "div" => {
15
+ "class" => %w[footnotes],
16
+ },
17
+ "p" => {
18
+ "class" => %w[codepen],
19
+ },
20
+ "sup" => {
21
+ "id" => /\Afnref\d+\z/,
22
+ },
23
+ "li" => {
24
+ "id" => /\Afn\d+\z/,
25
+ },
26
+ }.freeze
27
+
28
+ DELIMITER = " ".freeze
29
+
30
+ def self.call(*args)
31
+ new(*args).transform
32
+ end
33
+
34
+ def initialize(env)
35
+ @env = env
36
+ end
37
+
38
+ def transform
39
+ return unless FILTERS.key?(name)
40
+ FILTERS[name].each_pair do |attr, pattern|
41
+ filter_attribute(attr, pattern) if node.attributes.key?(attr)
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def filter_attribute(attr, pattern)
48
+ node[attr] = node[attr].split(DELIMITER).select do |value|
49
+ pattern.is_a?(Array) ? pattern.include?(value) : (pattern =~ value)
50
+ end.join(DELIMITER)
51
+ end
52
+
53
+ def name
54
+ @env[:node_name]
55
+ end
56
+
57
+ def node
58
+ @env[:node]
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,40 @@
1
+ module Qiita
2
+ module Markdown
3
+ module Transformers
4
+ class FilterScript
5
+ WHITE_LIST = [
6
+ CodePen::SCRIPT_URL,
7
+ ].freeze
8
+
9
+ def self.call(*args)
10
+ new(*args).transform
11
+ end
12
+
13
+ def initialize(env)
14
+ @env = env
15
+ end
16
+
17
+ def transform
18
+ if name == "script"
19
+ if WHITE_LIST.include?(node["src"])
20
+ node["async"] = "async" unless node.attributes.key?("async")
21
+ node.children.unlink
22
+ else
23
+ node.unlink
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def name
31
+ @env[:node_name]
32
+ end
33
+
34
+ def node
35
+ @env[:node]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,44 @@
1
+ module Qiita
2
+ module Markdown
3
+ module Transformers
4
+ # Wraps a node env to transform invalid node.
5
+ class StripInvalidNode
6
+ def self.call(*args)
7
+ new(*args).transform
8
+ end
9
+
10
+ def initialize(env)
11
+ @env = env
12
+ end
13
+
14
+ def transform
15
+ if has_invalid_list_node? || has_invalid_table_node?
16
+ node.replace(node.children)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def has_invalid_list_node?
23
+ name == "li" && node.ancestors.none? do |ancestor|
24
+ %w[ol ul].include?(ancestor.name)
25
+ end
26
+ end
27
+
28
+ def has_invalid_table_node?
29
+ %w[thead tbody tfoot tr td th].include?(name) && node.ancestors.none? do |ancestor|
30
+ ancestor.name == "table"
31
+ end
32
+ end
33
+
34
+ def name
35
+ @env[:node_name]
36
+ end
37
+
38
+ def node
39
+ @env[:node]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,5 +1,5 @@
1
1
  module Qiita
2
2
  module Markdown
3
- VERSION = "0.21.0"
3
+ VERSION = "0.22.0"
4
4
  end
5
5
  end
@@ -1140,7 +1140,7 @@ describe Qiita::Markdown::Processor do
1140
1140
  end
1141
1141
 
1142
1142
  shared_examples_for "data-attributes" do |allowed:|
1143
- context "with data-attributes" do
1143
+ context "with data-attributes for general tags" do
1144
1144
  let(:markdown) do
1145
1145
  <<-EOS.strip_heredoc
1146
1146
  <div data-a="b"></div>
@@ -1161,6 +1161,28 @@ describe Qiita::Markdown::Processor do
1161
1161
  end
1162
1162
  end
1163
1163
  end
1164
+
1165
+ context "with data-attributes for <p> tag" do
1166
+ let(:markdown) do
1167
+ <<-EOS.strip_heredoc
1168
+ <p data-slug-hash="a" data-malicious="b"></p>
1169
+ EOS
1170
+ end
1171
+
1172
+ if allowed
1173
+ it "does not sanitize data-attributes" do
1174
+ should eq <<-EOS.strip_heredoc
1175
+ <p data-slug-hash="a" data-malicious="b"></p>
1176
+ EOS
1177
+ end
1178
+ else
1179
+ it "sanitizes data-attributes except the attributes used by codepen" do
1180
+ should eq <<-EOS.strip_heredoc
1181
+ <p data-slug-hash="a"></p>
1182
+ EOS
1183
+ end
1184
+ end
1185
+ end
1164
1186
  end
1165
1187
 
1166
1188
  shared_examples_for "class attribute" do |allowed:|
@@ -1248,6 +1270,28 @@ describe Qiita::Markdown::Processor do
1248
1270
  end
1249
1271
  end
1250
1272
  end
1273
+
1274
+ context "with class attribute for <p> tag" do
1275
+ let(:markdown) do
1276
+ <<-EOS.strip_heredoc
1277
+ <p class="codepen malicious-class">foo</p>
1278
+ EOS
1279
+ end
1280
+
1281
+ if allowed
1282
+ it "does not sanitize the classes" do
1283
+ should eq <<-EOS.strip_heredoc
1284
+ <p class="codepen malicious-class">foo</p>
1285
+ EOS
1286
+ end
1287
+ else
1288
+ it "sanitizes classes except `codepen`" do
1289
+ should eq <<-EOS.strip_heredoc
1290
+ <p class="codepen">foo</p>
1291
+ EOS
1292
+ end
1293
+ end
1294
+ end
1251
1295
  end
1252
1296
 
1253
1297
  shared_examples_for "background-color" do |allowed:|
@@ -1268,6 +1312,33 @@ describe Qiita::Markdown::Processor do
1268
1312
  end
1269
1313
  end
1270
1314
 
1315
+ shared_examples_for "override codepen attributes" do |allowed:|
1316
+ context "with HTML embed code for CodePen" do
1317
+ let(:markdown) do
1318
+ <<-EOS.strip_heredoc
1319
+ <p data-height="1" data-theme-id="0" data-slug-hash="foo" data-default-tab="bar" data-user="baz" data-embed-version="2" data-pen-title="qux" class="codepen"></p>
1320
+ <script src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
1321
+ EOS
1322
+ end
1323
+
1324
+ if allowed
1325
+ it "does not sanitize embed code" do
1326
+ should eq <<-EOS.strip_heredoc
1327
+ <p data-height="1" data-theme-id="0" data-slug-hash="foo" data-default-tab="bar" data-user="baz" data-embed-version="2" data-pen-title="qux" class="codepen"></p>\n
1328
+ <script src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
1329
+ EOS
1330
+ end
1331
+ else
1332
+ it "sanitizes data-attributes except the minimum attributes and force async attribute" do
1333
+ should eq <<-EOS.strip_heredoc
1334
+ <p data-slug-hash="foo" data-embed-version="2" class="codepen"></p>\n
1335
+ <script src="https://production-assets.codepen.io/assets/embed/ei.js" async="async"></script>
1336
+ EOS
1337
+ end
1338
+ end
1339
+ end
1340
+ end
1341
+
1271
1342
  context "without script and strict context" do
1272
1343
  let(:context) do
1273
1344
  super().merge(script: false, strict: false)
@@ -1281,6 +1352,7 @@ describe Qiita::Markdown::Processor do
1281
1352
  include_examples "data-attributes", allowed: false
1282
1353
  include_examples "class attribute", allowed: true
1283
1354
  include_examples "background-color", allowed: true
1355
+ include_examples "override codepen attributes", allowed: false
1284
1356
  end
1285
1357
 
1286
1358
  context "with script context" do
@@ -1296,6 +1368,7 @@ describe Qiita::Markdown::Processor do
1296
1368
  include_examples "data-attributes", allowed: true
1297
1369
  include_examples "class attribute", allowed: true
1298
1370
  include_examples "background-color", allowed: true
1371
+ include_examples "override codepen attributes", allowed: true
1299
1372
  end
1300
1373
 
1301
1374
  context "with strict context" do
@@ -1311,6 +1384,7 @@ describe Qiita::Markdown::Processor do
1311
1384
  include_examples "data-attributes", allowed: false
1312
1385
  include_examples "class attribute", allowed: false
1313
1386
  include_examples "background-color", allowed: false
1387
+ include_examples "override codepen attributes", allowed: false
1314
1388
  end
1315
1389
 
1316
1390
  context "with script and strict context" do
@@ -1326,6 +1400,7 @@ describe Qiita::Markdown::Processor do
1326
1400
  include_examples "data-attributes", allowed: false
1327
1401
  include_examples "class attribute", allowed: false
1328
1402
  include_examples "background-color", allowed: false
1403
+ include_examples "override codepen attributes", allowed: false
1329
1404
  end
1330
1405
  end
1331
1406
  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.21.0
4
+ version: 0.22.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: 2017-11-13 00:00:00.000000000 Z
11
+ date: 2017-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gemoji
@@ -256,6 +256,7 @@ files:
256
256
  - lib/qiita-markdown.rb
257
257
  - lib/qiita/markdown.rb
258
258
  - lib/qiita/markdown/base_processor.rb
259
+ - lib/qiita/markdown/code_pen.rb
259
260
  - lib/qiita/markdown/filters/checkbox.rb
260
261
  - lib/qiita/markdown/filters/code_block.rb
261
262
  - lib/qiita/markdown/filters/emoji.rb
@@ -277,6 +278,9 @@ files:
277
278
  - lib/qiita/markdown/greenmat/html_toc_renderer.rb
278
279
  - lib/qiita/markdown/processor.rb
279
280
  - lib/qiita/markdown/summary_processor.rb
281
+ - lib/qiita/markdown/transformers/filter_attributes.rb
282
+ - lib/qiita/markdown/transformers/filter_script.rb
283
+ - lib/qiita/markdown/transformers/strip_invalid_node.rb
280
284
  - lib/qiita/markdown/version.rb
281
285
  - qiita-markdown.gemspec
282
286
  - spec/qiita/markdown/filters/greenmat_spec.rb