motion-html-pipeline 0.1
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 +7 -0
- data/README.md +379 -0
- data/lib/motion-html-pipeline.rb +14 -0
- data/lib/motion-html-pipeline/document_fragment.rb +27 -0
- data/lib/motion-html-pipeline/pipeline.rb +153 -0
- data/lib/motion-html-pipeline/pipeline/absolute_source_filter.rb +45 -0
- data/lib/motion-html-pipeline/pipeline/body_content.rb +42 -0
- data/lib/motion-html-pipeline/pipeline/disabled/@mention_filter.rb +140 -0
- data/lib/motion-html-pipeline/pipeline/disabled/autolink_filter.rb +27 -0
- data/lib/motion-html-pipeline/pipeline/disabled/camo_filter.rb +93 -0
- data/lib/motion-html-pipeline/pipeline/disabled/email_reply_filter.rb +66 -0
- data/lib/motion-html-pipeline/pipeline/disabled/emoji_filter.rb +125 -0
- data/lib/motion-html-pipeline/pipeline/disabled/markdown_filter.rb +37 -0
- data/lib/motion-html-pipeline/pipeline/disabled/plain_text_input_filter.rb +13 -0
- data/lib/motion-html-pipeline/pipeline/disabled/sanitization_filter.rb +137 -0
- data/lib/motion-html-pipeline/pipeline/disabled/syntax_highlight_filter.rb +44 -0
- data/lib/motion-html-pipeline/pipeline/disabled/toc_filter.rb +67 -0
- data/lib/motion-html-pipeline/pipeline/filter.rb +163 -0
- data/lib/motion-html-pipeline/pipeline/https_filter.rb +27 -0
- data/lib/motion-html-pipeline/pipeline/image_filter.rb +17 -0
- data/lib/motion-html-pipeline/pipeline/image_max_width_filter.rb +37 -0
- data/lib/motion-html-pipeline/pipeline/text_filter.rb +14 -0
- data/lib/motion-html-pipeline/pipeline/version.rb +5 -0
- data/spec/motion-html-pipeline/_helpers/mock_instumentation_service.rb +19 -0
- data/spec/motion-html-pipeline/pipeline/absolute_source_filter_spec.rb +47 -0
- data/spec/motion-html-pipeline/pipeline/disabled/auto_link_filter_spec.rb +33 -0
- data/spec/motion-html-pipeline/pipeline/disabled/camo_filter_spec.rb +75 -0
- data/spec/motion-html-pipeline/pipeline/disabled/email_reply_filter_spec.rb +64 -0
- data/spec/motion-html-pipeline/pipeline/disabled/emoji_filter_spec.rb +92 -0
- data/spec/motion-html-pipeline/pipeline/disabled/markdown_filter_spec.rb +112 -0
- data/spec/motion-html-pipeline/pipeline/disabled/plain_text_input_filter_spec.rb +20 -0
- data/spec/motion-html-pipeline/pipeline/disabled/sanitization_filter_spec.rb +164 -0
- data/spec/motion-html-pipeline/pipeline/disabled/syntax_highlighting_filter_spec.rb +59 -0
- data/spec/motion-html-pipeline/pipeline/disabled/toc_filter_spec.rb +137 -0
- data/spec/motion-html-pipeline/pipeline/https_filter_spec.rb +52 -0
- data/spec/motion-html-pipeline/pipeline/image_filter_spec.rb +37 -0
- data/spec/motion-html-pipeline/pipeline/image_max_width_filter_spec.rb +57 -0
- data/spec/motion-html-pipeline/pipeline_spec.rb +80 -0
- data/spec/spec_helper.rb +48 -0
- metadata +147 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
module MotionHTMLPipeline
|
2
|
+
class Pipeline
|
3
|
+
# HTML Filter for replacing http references to :http_url with https versions.
|
4
|
+
# Subdomain references are not rewritten.
|
5
|
+
#
|
6
|
+
# Context options:
|
7
|
+
# :http_url - The HTTP url to force HTTPS. Falls back to :base_url
|
8
|
+
class HttpsFilter < Filter
|
9
|
+
def call
|
10
|
+
doc.css(%(a[href^="#{http_url}"])).each do |element|
|
11
|
+
element['href'] = element['href'].sub(/^http:/, 'https:')
|
12
|
+
end
|
13
|
+
doc
|
14
|
+
end
|
15
|
+
|
16
|
+
# HTTP url to replace. Falls back to :base_url
|
17
|
+
def http_url
|
18
|
+
context[:http_url] || context[:base_url]
|
19
|
+
end
|
20
|
+
|
21
|
+
# Raise error if :http_url undefined
|
22
|
+
def validate
|
23
|
+
needs :http_url unless http_url
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module MotionHTMLPipeline
|
2
|
+
class Pipeline
|
3
|
+
# HTML Filter that converts image's url into <img> tag.
|
4
|
+
# For example, it will convert
|
5
|
+
# http://example.com/test.jpg
|
6
|
+
# into
|
7
|
+
# <img src="http://example.com/test.jpg" alt=""/>.
|
8
|
+
|
9
|
+
class ImageFilter < TextFilter
|
10
|
+
def call
|
11
|
+
@text.gsub(/(https|http)?:\/\/.+\.(jpg|jpeg|bmp|gif|png)(\?\S+)?/i) do |match|
|
12
|
+
%(<img src="#{match}" alt=""/>)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module MotionHTMLPipeline
|
2
|
+
class Pipeline
|
3
|
+
# This filter rewrites image tags with a max-width inline style and also wraps
|
4
|
+
# the image in an <a> tag that causes the full size image to be opened in a
|
5
|
+
# new tab.
|
6
|
+
#
|
7
|
+
# The max-width inline styles are especially useful in HTML email which
|
8
|
+
# don't use a global stylesheets.
|
9
|
+
class ImageMaxWidthFilter < Filter
|
10
|
+
def call
|
11
|
+
doc.css('img').each do |element|
|
12
|
+
# Skip if there's already a style attribute. Not sure how this
|
13
|
+
# would happen but we can reconsider it in the future.
|
14
|
+
next if element['style']
|
15
|
+
|
16
|
+
# Bail out if src doesn't look like a valid http url. trying to avoid weird
|
17
|
+
# js injection via javascript: urls.
|
18
|
+
next if element['src'].to_s.strip =~ /\Ajavascript/i
|
19
|
+
|
20
|
+
element['style'] = 'max-width:100%;'
|
21
|
+
|
22
|
+
link_image element unless has_ancestor?(element, %w[a])
|
23
|
+
end
|
24
|
+
|
25
|
+
doc
|
26
|
+
end
|
27
|
+
|
28
|
+
def link_image(element)
|
29
|
+
link = HTMLElement.alloc.initWithTagName('a', attributes: { href: element['src'], target: '_blank' })
|
30
|
+
link.appendNode(element.cloneNodeDeep(true))
|
31
|
+
|
32
|
+
parent = element.parentNode
|
33
|
+
parent.replaceChildNode(element, withNode: link)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module MotionHTMLPipeline
|
2
|
+
class Pipeline
|
3
|
+
class TextFilter < Filter
|
4
|
+
attr_reader :text
|
5
|
+
|
6
|
+
def initialize(text, context = nil, result = nil)
|
7
|
+
raise TypeError, 'text cannot be HTML' if text.is_a?(DocumentFragment)
|
8
|
+
# Ensure that this is always a string
|
9
|
+
@text = text.respond_to?(:to_str) ? text.to_str : text.to_s
|
10
|
+
super nil, context, result
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class MockedInstrumentationService
|
2
|
+
attr_reader :events
|
3
|
+
def initialize(event = nil, events = [])
|
4
|
+
@events = events
|
5
|
+
subscribe event
|
6
|
+
end
|
7
|
+
|
8
|
+
def instrument(event, payload = nil)
|
9
|
+
payload ||= {}
|
10
|
+
res = yield payload
|
11
|
+
events << [event, payload, res] if @subscribe == event
|
12
|
+
res
|
13
|
+
end
|
14
|
+
|
15
|
+
def subscribe(event)
|
16
|
+
@subscribe = event
|
17
|
+
@events
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
describe 'MotionHTMLPipeline::Pipeline::AbsoluteSourceFilterTest' do
|
2
|
+
AbsoluteSourceFilter = MotionHTMLPipeline::Pipeline::AbsoluteSourceFilter
|
3
|
+
|
4
|
+
before do
|
5
|
+
@image_base_url = 'http://assets.example.com'
|
6
|
+
@image_subpage_url = 'http://blog.example.com/a/post'
|
7
|
+
@options = {
|
8
|
+
image_base_url: @image_base_url,
|
9
|
+
image_subpage_url: @image_subpage_url
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'test_rewrites_root_urls' do
|
14
|
+
orig = %(<p><img src="/img.png"></p>)
|
15
|
+
|
16
|
+
expect("<p><img src=\"#{@image_base_url}/img.png\"></p>")
|
17
|
+
.to eq AbsoluteSourceFilter.call(orig, @options).to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'test_rewrites_relative_urls' do
|
21
|
+
orig = %(<p><img src="post/img.png"></p>)
|
22
|
+
|
23
|
+
expect("<p><img src=\"#{@image_subpage_url}/img.png\"></p>")
|
24
|
+
.to eq AbsoluteSourceFilter.call(orig, @options).to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'test_does_not_rewrite_absolute_urls' do
|
28
|
+
orig = %(<p><img src="http://other.example.com/img.png"></p>)
|
29
|
+
result = AbsoluteSourceFilter.call(orig, @options).to_s
|
30
|
+
|
31
|
+
expect(result).not_to match(/@image_base_url/)
|
32
|
+
expect(result).not_to match(/@@image_subpage_url/)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'test_fails_when_context_is_missing' do
|
36
|
+
expect{ AbsoluteSourceFilter.call('<img src="img.png">', {}) }.to raise_error(RuntimeError)
|
37
|
+
expect{ AbsoluteSourceFilter.call('<img src="/img.png">', {}) }.to raise_error(RuntimeError)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'test_tells_you_where_context_is_required' do
|
41
|
+
expect{ AbsoluteSourceFilter.call('<img src="img.png">', {}) }
|
42
|
+
.to raise_error(RuntimeError, 'MotionHTMLPipeline::Pipeline::AbsoluteSourceFilter')
|
43
|
+
|
44
|
+
expect{ AbsoluteSourceFilter.call('<img src="/img.png">', {}) }
|
45
|
+
.to raise_error(RuntimeError, 'MotionHTMLPipeline::Pipeline::AbsoluteSourceFilter')
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# describe 'MotionHTMLPipeline::Pipeline::AutolinkFilterTest' do
|
2
|
+
# AutolinkFilter = MotionHTMLPipeline::Pipeline::AutolinkFilter
|
3
|
+
#
|
4
|
+
# it '#test_uses_rinku_for_autolinking' do
|
5
|
+
# # just try to parse a complicated piece of HTML
|
6
|
+
# # that Rails auto_link cannot handle
|
7
|
+
# expect('<p>"<a href="http://www.github.com">http://www.github.com</a>"</p>')
|
8
|
+
# .to eq AutolinkFilter.to_html('<p>"http://www.github.com"</p>')
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# def test_autolink_option
|
12
|
+
# assert_equal '<p>"http://www.github.com"</p>',
|
13
|
+
# AutolinkFilter.to_html('<p>"http://www.github.com"</p>', autolink: false)
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# def test_autolink_link_attr
|
17
|
+
# assert_equal '<p>"<a href="http://www.github.com" target="_blank">http://www.github.com</a>"</p>',
|
18
|
+
# AutolinkFilter.to_html('<p>"http://www.github.com"</p>', link_attr: 'target="_blank"')
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def test_autolink_flags
|
22
|
+
# assert_equal '<p>"<a href="http://github">http://github</a>"</p>',
|
23
|
+
# AutolinkFilter.to_html('<p>"http://github"</p>', flags: Rinku::AUTOLINK_SHORT_DOMAINS)
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# def test_autolink_skip_tags
|
27
|
+
# assert_equal '<code>"http://github.com"</code>',
|
28
|
+
# AutolinkFilter.to_html('<code>"http://github.com"</code>')
|
29
|
+
#
|
30
|
+
# assert_equal '<code>"<a href="http://github.com">http://github.com</a>"</code>',
|
31
|
+
# AutolinkFilter.to_html('<code>"http://github.com"</code>', skip_tags: %w[kbd script])
|
32
|
+
# end
|
33
|
+
# end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# describe 'MotionHTMLPipeline::Pipeline::CamoFilterTest' do
|
2
|
+
# CamoFilter = MotionHTMLPipeline::Pipeline::CamoFilter
|
3
|
+
#
|
4
|
+
# def setup
|
5
|
+
# @asset_proxy_url = 'https//assets.example.org'
|
6
|
+
# @asset_proxy_secret_key = 'ssssh-secret'
|
7
|
+
# @options = {
|
8
|
+
# asset_proxy: @asset_proxy_url,
|
9
|
+
# asset_proxy_secret_key: @asset_proxy_secret_key,
|
10
|
+
# asset_proxy_whitelist: [/(^|\.)github\.com$/]
|
11
|
+
# }
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# def test_asset_proxy_disabled
|
15
|
+
# orig = %(<p><img src="http://twitter.com/img.png"></p>)
|
16
|
+
# assert_equal orig,
|
17
|
+
# CamoFilter.call(orig, @options.merge(disable_asset_proxy: true)).to_s
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def test_camouflaging_http_image_urls
|
21
|
+
# orig = %(<p><img src="http://twitter.com/img.png"></p>)
|
22
|
+
# assert_equal %(<p><img src="https//assets.example.org/a5ad43494e343b20d745586282be61ff530e6fa0/687474703a2f2f747769747465722e636f6d2f696d672e706e67" data-canonical-src="http://twitter.com/img.png"></p>),
|
23
|
+
# CamoFilter.call(orig, @options).to_s
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# def test_doesnt_rewrite_dotcom_image_urls
|
27
|
+
# orig = %(<p><img src="https://github.com/img.png"></p>)
|
28
|
+
# assert_equal orig, CamoFilter.call(orig, @options).to_s
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# def test_doesnt_rewrite_dotcom_subdomain_image_urls
|
32
|
+
# orig = %(<p><img src="https://raw.github.com/img.png"></p>)
|
33
|
+
# assert_equal orig, CamoFilter.call(orig, @options).to_s
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# def test_doesnt_rewrite_dotcom_subsubdomain_image_urls
|
37
|
+
# orig = %(<p><img src="https://f.assets.github.com/img.png"></p>)
|
38
|
+
# assert_equal orig, CamoFilter.call(orig, @options).to_s
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# def test_camouflaging_github_prefixed_image_urls
|
42
|
+
# orig = %(<p><img src="https://notgithub.com/img.png"></p>)
|
43
|
+
# assert_equal %(<p><img src="https//assets.example.org/5d4a96c69713f850520538e04cb9661035cfb534/68747470733a2f2f6e6f746769746875622e636f6d2f696d672e706e67" data-canonical-src="https://notgithub.com/img.png"></p>),
|
44
|
+
# CamoFilter.call(orig, @options).to_s
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def test_doesnt_rewrite_absolute_image_urls
|
48
|
+
# orig = %(<p><img src="/img.png"></p>)
|
49
|
+
# assert_equal orig, CamoFilter.call(orig, @options).to_s
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# def test_doesnt_rewrite_relative_image_urls
|
53
|
+
# orig = %(<p><img src="img.png"></p>)
|
54
|
+
# assert_equal orig, CamoFilter.call(orig, @options).to_s
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# def test_camouflaging_https_image_urls
|
58
|
+
# orig = %(<p><img src="https://foo.com/img.png"></p>)
|
59
|
+
# assert_equal %(<p><img src="https//assets.example.org/3c5c6dc74fd6592d2596209dfcb8b7e5461383c8/68747470733a2f2f666f6f2e636f6d2f696d672e706e67" data-canonical-src="https://foo.com/img.png"></p>),
|
60
|
+
# CamoFilter.call(orig, @options).to_s
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# def test_handling_images_with_no_src_attribute
|
64
|
+
# orig = %(<p><img></p>)
|
65
|
+
# assert_equal orig, CamoFilter.call(orig, @options).to_s
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# def test_required_context_validation
|
69
|
+
# exception = assert_raises(ArgumentError) do
|
70
|
+
# CamoFilter.call('', {})
|
71
|
+
# end
|
72
|
+
# assert_match /:asset_proxy[^_]/, exception.message
|
73
|
+
# assert_match /:asset_proxy_secret_key/, exception.message
|
74
|
+
# end
|
75
|
+
# end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# describe 'MotionHTMLPipeline::Pipeline::EmailReplyFilterTest' do
|
2
|
+
# EmailReplyFilter = MotionHTMLPipeline::Pipeline::EmailReplyFilter
|
3
|
+
#
|
4
|
+
# def setup
|
5
|
+
# @body = <<-EMAIL
|
6
|
+
# Hey, don't send email addresses in comments. They aren't filtered.
|
7
|
+
#
|
8
|
+
# > On Mar 5, 2016, at 08:05, Boaty McBoatface <boatymcboatface@example.com> wrote:
|
9
|
+
# >
|
10
|
+
# > Sup. alreadyleaked@example.com
|
11
|
+
# >
|
12
|
+
# > —
|
13
|
+
# > Reply to this email directly or view it on GitHub.
|
14
|
+
# EMAIL
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# def test_doesnt_hide_by_default
|
18
|
+
# filter = EmailReplyFilter.new(@body)
|
19
|
+
# doc = filter.call.to_s
|
20
|
+
# assert_match /alreadyleaked@example.com/, doc
|
21
|
+
# assert_match /boatymcboatface@example.com/, doc
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# def test_hides_email_addresses_when_configured
|
25
|
+
# filter = EmailReplyFilter.new(@body, hide_quoted_email_addresses: true)
|
26
|
+
# doc = filter.call.to_s
|
27
|
+
# refute_match /boatymcboatface@example.com/, doc
|
28
|
+
# refute_match /alreadyleaked@example.com/, doc
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# def test_preserves_non_email_content_while_filtering
|
32
|
+
# str = <<-EMAIL
|
33
|
+
# > Thank you! I have some thoughts on this pull request.
|
34
|
+
# >
|
35
|
+
# > * acme provides cmake and a wrapper for it. Please use '$(TARGET)-cmake' instead of cmake -DCMAKE_TOOLCHAIN_FILE='$(CMAKE_TOOLCHAIN_FILE)' -DCMAKE_BUILD_TYPE=Release.
|
36
|
+
#
|
37
|
+
# Okay -- I'm afraid I just blindly copied the eigen3.mk file, since that's a library I'm familiar with :-)
|
38
|
+
#
|
39
|
+
# > * Do you need -DCMAKE_SYSTEM_PROCESSOR=x86?
|
40
|
+
#
|
41
|
+
# Yes, this is a bit dumb, but vc checks for that (or amd) to determine that it's not being built on ARM.
|
42
|
+
#
|
43
|
+
# --
|
44
|
+
# Boaty McBoatface | http://example.org
|
45
|
+
# EMAIL
|
46
|
+
#
|
47
|
+
# filter = EmailReplyFilter.new(str, hide_quoted_email_addresses: true)
|
48
|
+
# doc = filter.call.to_s
|
49
|
+
#
|
50
|
+
# expected = <<-EXPECTED
|
51
|
+
# <div class="email-quoted-reply"> Thank you! I have some thoughts on this pull request.
|
52
|
+
#
|
53
|
+
# * acme provides cmake and a wrapper for it. Please use '$(TARGET)-cmake' instead of cmake -DCMAKE_TOOLCHAIN_FILE='$(CMAKE_TOOLCHAIN_FILE)' -DCMAKE_BUILD_TYPE=Release.</div>
|
54
|
+
# <div class="email-fragment">Okay -- I'm afraid I just blindly copied the eigen3.mk file, since that's a library I'm familiar with :-)</div>
|
55
|
+
# <div class="email-quoted-reply"> * Do you need -DCMAKE_SYSTEM_PROCESSOR=x86?</div>
|
56
|
+
# <div class="email-fragment">Yes, this is a bit dumb, but vc checks for that (or amd) to determine that it's not being built on ARM.</div>
|
57
|
+
# <span class="email-hidden-toggle"><a href="#">…</a></span><div class="email-hidden-reply" style="display:none"><div class="email-signature-reply">--
|
58
|
+
# Boaty McBoatface | http://example.org</div>
|
59
|
+
# </div>
|
60
|
+
# EXPECTED
|
61
|
+
#
|
62
|
+
# assert_equal(expected.chomp, doc)
|
63
|
+
# end
|
64
|
+
# end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# describe 'MotionHTMLPipeline::Pipeline::EmojiFilterTest' do
|
2
|
+
# EmojiFilter = MotionHTMLPipeline::Pipeline::EmojiFilter
|
3
|
+
#
|
4
|
+
# def test_emojify
|
5
|
+
# filter = EmojiFilter.new('<p>:shipit:</p>', asset_root: 'https://foo.com')
|
6
|
+
# doc = filter.call
|
7
|
+
# assert_match 'https://foo.com/emoji/shipit.png', doc.search('img').attr('src').value
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# def test_uri_encoding
|
11
|
+
# filter = EmojiFilter.new('<p>:+1:</p>', asset_root: 'https://foo.com')
|
12
|
+
# doc = filter.call
|
13
|
+
# assert_match 'https://foo.com/emoji/unicode/1f44d.png', doc.search('img').attr('src').value
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# def test_required_context_validation
|
17
|
+
# exception = assert_raises(ArgumentError) do
|
18
|
+
# EmojiFilter.call('', {})
|
19
|
+
# end
|
20
|
+
# assert_match /:asset_root/, exception.message
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# def test_custom_asset_path
|
24
|
+
# filter = EmojiFilter.new('<p>:+1:</p>', asset_path: ':file_name', asset_root: 'https://foo.com')
|
25
|
+
# doc = filter.call
|
26
|
+
# assert_match 'https://foo.com/unicode/1f44d.png', doc.search('img').attr('src').value
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# def test_not_emojify_in_code_tags
|
30
|
+
# body = '<code>:shipit:</code>'
|
31
|
+
# filter = EmojiFilter.new(body, asset_root: 'https://foo.com')
|
32
|
+
# doc = filter.call
|
33
|
+
# assert_equal body, doc.to_html
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# def test_not_emojify_in_tt_tags
|
37
|
+
# body = '<tt>:shipit:</tt>'
|
38
|
+
# filter = EmojiFilter.new(body, asset_root: 'https://foo.com')
|
39
|
+
# doc = filter.call
|
40
|
+
# assert_equal body, doc.to_html
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# def test_not_emojify_in_pre_tags
|
44
|
+
# body = '<pre>:shipit:</pre>'
|
45
|
+
# filter = EmojiFilter.new(body, asset_root: 'https://foo.com')
|
46
|
+
# doc = filter.call
|
47
|
+
# assert_equal body, doc.to_html
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# def test_not_emojify_in_custom_single_tag_foo
|
51
|
+
# body = '<foo>:shipit:</foo>'
|
52
|
+
# filter = EmojiFilter.new(body, asset_root: 'https://foo.com', ignored_ancestor_tags: %w[foo])
|
53
|
+
# doc = filter.call
|
54
|
+
# assert_equal body, doc.to_html
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# def test_not_emojify_in_custom_multiple_tags_foo_and_bar
|
58
|
+
# body = '<bar>:shipit:</bar>'
|
59
|
+
# filter = EmojiFilter.new(body, asset_root: 'https://foo.com', ignored_ancestor_tags: %w[foo bar])
|
60
|
+
# doc = filter.call
|
61
|
+
# assert_equal body, doc.to_html
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# def test_img_tag_attributes
|
65
|
+
# body = ':shipit:'
|
66
|
+
# filter = EmojiFilter.new(body, asset_root: 'https://foo.com')
|
67
|
+
# doc = filter.call
|
68
|
+
# assert_equal %(<img class="emoji" title=":shipit:" alt=":shipit:" src="https://foo.com/emoji/shipit.png" height="20" width="20" align="absmiddle">), doc.to_html
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# def test_img_tag_attributes_can_be_customized
|
72
|
+
# body = ':shipit:'
|
73
|
+
# filter = EmojiFilter.new(body, asset_root: 'https://foo.com', img_attrs: Hash('draggable' => 'false', 'height' => nil, 'width' => nil, 'align' => nil))
|
74
|
+
# doc = filter.call
|
75
|
+
# assert_equal %(<img class="emoji" title=":shipit:" alt=":shipit:" src="https://foo.com/emoji/shipit.png" draggable="false">), doc.to_html
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# def test_img_attrs_value_can_accept_proclike_object
|
79
|
+
# remove_colons = ->(name) { name.delete(':') }
|
80
|
+
# body = ':shipit:'
|
81
|
+
# filter = EmojiFilter.new(body, asset_root: 'https://foo.com', img_attrs: Hash('title' => remove_colons))
|
82
|
+
# doc = filter.call
|
83
|
+
# assert_equal %(<img class="emoji" title="shipit" alt=":shipit:" src="https://foo.com/emoji/shipit.png" height="20" width="20" align="absmiddle">), doc.to_html
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# def test_img_attrs_can_accept_symbolized_keys
|
87
|
+
# body = ':shipit:'
|
88
|
+
# filter = EmojiFilter.new(body, asset_root: 'https://foo.com', img_attrs: Hash(draggable: false, height: nil, width: nil, align: nil))
|
89
|
+
# doc = filter.call
|
90
|
+
# assert_equal %(<img class="emoji" title=":shipit:" alt=":shipit:" src="https://foo.com/emoji/shipit.png" draggable="false">), doc.to_html
|
91
|
+
# end
|
92
|
+
# end
|