Skip to content

Allow HTML embed code for CodePen #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Style/MutableConstant:
- 'lib/qiita/markdown/filters/sanitize.rb'
- 'lib/qiita/markdown/filters/simplify.rb'
- 'lib/qiita/markdown/filters/syntax_highlight.rb'
- 'lib/qiita/markdown/code_pen.rb'
- 'lib/qiita/markdown/processor.rb'
- 'lib/qiita/markdown/summary_processor.rb'
- 'lib/qiita/markdown/version.rb'
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Unreleased

- Support embed CodePen

## 0.21.0

- Rename `Code` to `CodeBlock`
Expand Down
4 changes: 4 additions & 0 deletions lib/qiita/markdown.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
require "pygments"
require "sanitize"

require "qiita/markdown/code_pen"
require "qiita/markdown/transformers/filter_attributes"
require "qiita/markdown/transformers/filter_script"
require "qiita/markdown/transformers/strip_invalid_node"
require "qiita/markdown/filters/checkbox"
require "qiita/markdown/filters/code_block"
require "qiita/markdown/filters/emoji"
Expand Down
8 changes: 8 additions & 0 deletions lib/qiita/markdown/code_pen.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Qiita
module Markdown
module CodePen
SCRIPT_URL = "https://production-assets.codepen.io/assets/embed/ei.js"
ATTRIBUTES = %w[class data-embed-version data-slug-hash]
end
end
end
49 changes: 6 additions & 43 deletions lib/qiita/markdown/filters/final_sanitizer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,6 @@ module Filters
#
# @see Qiita::Markdown::Filters::UserInputSanitizerr
class FinalSanitizer < HTML::Pipeline::Filter
# Wraps a node env to transform invalid node.
class TransformableNode
def self.call(*args)
new(*args).transform
end

def initialize(env)
@env = env
end

def transform
if has_invalid_list_node? || has_invalid_table_node?
node.replace(node.children)
end
end

private

def has_invalid_list_node?
name == "li" && node.ancestors.none? do |ancestor|
%w[ol ul].include?(ancestor.name)
end
end

def has_invalid_table_node?
%w[thead tbody tfoot tr td th].include?(name) && node.ancestors.none? do |ancestor|
ancestor.name == "table"
end
end

def name
@env[:node_name]
end

def node
@env[:node]
end
end

RULE = {
attributes: {
"a" => [
Expand Down Expand Up @@ -80,6 +41,7 @@ def node
"itemscope",
"itemtype",
],
"p" => CodePen::ATTRIBUTES,
"script" => [
"async",
"src",
Expand Down Expand Up @@ -173,6 +135,7 @@ def node
"ruby",
"s",
"samp",
"script",
"span",
"strike",
"strong",
Expand Down Expand Up @@ -219,17 +182,17 @@ def node
],
},
},
remove_contents: [
"script",
transformers: [
Transformers::StripInvalidNode,
Transformers::FilterScript,
],
transformers: TransformableNode,
}.freeze

SCRIPTABLE_RULE = RULE.dup.tap do |rule|
rule[:attributes] = RULE[:attributes].dup
rule[:attributes][:all] = rule[:attributes][:all] + [:data]
rule[:elements] = RULE[:elements] + ["iframe", "script", "video"]
rule[:remove_contents] = []
rule[:transformers] = rule[:transformers] - [Transformers::FilterScript]
end

def call
Expand Down
65 changes: 6 additions & 59 deletions lib/qiita/markdown/filters/user_input_sanitizer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,65 +3,10 @@ module Markdown
module Filters
# Sanitizes user input if :strict context is given.
class UserInputSanitizer < HTML::Pipeline::Filter
class AttributeFilter
FILTERS = {
"a" => {
"class" => %w[autolink],
"rel" => %w[footnote url],
"rev" => %w[footnote],
},
"blockquote" => {
"class" => %w[twitter-tweet],
},
"div" => {
"class" => %w[footnotes],
},
"sup" => {
"id" => /\Afnref\d+\z/,
},
"li" => {
"id" => /\Afn\d+\z/,
},
}.freeze

DELIMITER = " ".freeze

def self.call(*args)
new(*args).transform
end

def initialize(env)
@env = env
end

def transform
return unless FILTERS.key?(name)
FILTERS[name].each_pair do |attr, pattern|
filter_attribute(attr, pattern) if node.attributes.key?(attr)
end
end

private

def filter_attribute(attr, pattern)
node[attr] = node[attr].split(DELIMITER).select do |value|
pattern.is_a?(Array) ? pattern.include?(value) : (pattern =~ value)
end.join(DELIMITER)
end

def name
@env[:node_name]
end

def node
@env[:node]
end
end

RULE = {
elements: %w[
a b blockquote br code dd del details div dl dt em font h1 h2 h3 h4 h5 h6
hr i img ins kbd li ol p pre q rp rt ruby s samp strike strong sub
hr i img ins kbd li ol p pre q rp rt ruby s samp script strike strong sub
summary sup table tbody td tfoot th thead tr ul var
],
attributes: {
Expand All @@ -79,7 +24,9 @@ def node
"img" => %w[alt height src title width],
"ins" => %w[cite datetime],
"li" => %w[id],
"p" => CodePen::ATTRIBUTES,
"q" => %w[cite],
"script" => %w[async src],
"sup" => %w[id],
"td" => %w[colspan rowspan style],
"th" => %w[colspan rowspan style],
Expand All @@ -92,10 +39,10 @@ def node
css: {
properties: %w[text-align],
},
remove_contents: %w[
script
transformers: [
Transformers::FilterAttributes,
Transformers::FilterScript,
],
transformers: AttributeFilter,
}.freeze

def call
Expand Down
63 changes: 63 additions & 0 deletions lib/qiita/markdown/transformers/filter_attributes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
module Qiita
module Markdown
module Transformers
class FilterAttributes
FILTERS = {
"a" => {
"class" => %w[autolink],
"rel" => %w[footnote url],
"rev" => %w[footnote],
},
"blockquote" => {
"class" => %w[twitter-tweet],
},
"div" => {
"class" => %w[footnotes],
},
"p" => {
"class" => %w[codepen],
},
"sup" => {
"id" => /\Afnref\d+\z/,
},
"li" => {
"id" => /\Afn\d+\z/,
},
}.freeze

DELIMITER = " ".freeze

def self.call(*args)
new(*args).transform
end

def initialize(env)
@env = env
end

def transform
return unless FILTERS.key?(name)
FILTERS[name].each_pair do |attr, pattern|
filter_attribute(attr, pattern) if node.attributes.key?(attr)
end
end

private

def filter_attribute(attr, pattern)
node[attr] = node[attr].split(DELIMITER).select do |value|
pattern.is_a?(Array) ? pattern.include?(value) : (pattern =~ value)
end.join(DELIMITER)
end

def name
@env[:node_name]
end

def node
@env[:node]
end
end
end
end
end
40 changes: 40 additions & 0 deletions lib/qiita/markdown/transformers/filter_script.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module Qiita
module Markdown
module Transformers
class FilterScript
WHITE_LIST = [
CodePen::SCRIPT_URL,
].freeze

def self.call(*args)
new(*args).transform
end

def initialize(env)
@env = env
end

def transform
if name == "script"
if WHITE_LIST.include?(node["src"])
node["async"] = "async" unless node.attributes.key?("async")
node.children.unlink
else
node.unlink
end
end
end

private

def name
@env[:node_name]
end

def node
@env[:node]
end
end
end
end
end
44 changes: 44 additions & 0 deletions lib/qiita/markdown/transformers/strip_invalid_node.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module Qiita
module Markdown
module Transformers
# Wraps a node env to transform invalid node.
class StripInvalidNode
def self.call(*args)
new(*args).transform
end

def initialize(env)
@env = env
end

def transform
if has_invalid_list_node? || has_invalid_table_node?
node.replace(node.children)
end
end

private

def has_invalid_list_node?
name == "li" && node.ancestors.none? do |ancestor|
%w[ol ul].include?(ancestor.name)
end
end

def has_invalid_table_node?
%w[thead tbody tfoot tr td th].include?(name) && node.ancestors.none? do |ancestor|
ancestor.name == "table"
end
end

def name
@env[:node_name]
end

def node
@env[:node]
end
end
end
end
end
Loading