qiita-markdown 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.

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