auto_html 1.6.3 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +65 -94
  3. data/Rakefile +8 -7
  4. data/lib/auto_html/emoji.rb +24 -0
  5. data/lib/auto_html/html_escape.rb +12 -0
  6. data/lib/auto_html/image.rb +23 -0
  7. data/lib/auto_html/link.rb +33 -0
  8. data/lib/auto_html/markdown.rb +17 -0
  9. data/lib/auto_html/pipeline.rb +18 -0
  10. data/lib/auto_html/simple_format.rb +23 -0
  11. data/lib/auto_html/tag_helper.rb +38 -0
  12. data/lib/auto_html.rb +11 -15
  13. data/spec/auto_html/emoji_spec.rb +9 -0
  14. data/spec/auto_html/html_escape_spec.rb +10 -0
  15. data/spec/auto_html/image_spec.rb +41 -0
  16. data/spec/auto_html/link_spec.rb +53 -0
  17. data/spec/auto_html/markdown_spec.rb +9 -0
  18. data/spec/auto_html/pipeline_spec.rb +26 -0
  19. data/spec/auto_html/simple_format_spec.rb +18 -0
  20. data/spec/auto_html/tag_helper_spec.rb +30 -0
  21. data/spec/spec_helper.rb +13 -0
  22. metadata +114 -92
  23. data/lib/auto_html/auto_html_for.rb +0 -64
  24. data/lib/auto_html/base.rb +0 -18
  25. data/lib/auto_html/builder.rb +0 -21
  26. data/lib/auto_html/capistrano.rb +0 -17
  27. data/lib/auto_html/filter.rb +0 -22
  28. data/lib/auto_html/filters/dailymotion.rb +0 -6
  29. data/lib/auto_html/filters/flickr.rb +0 -20
  30. data/lib/auto_html/filters/gist.rb +0 -8
  31. data/lib/auto_html/filters/google_map.rb +0 -19
  32. data/lib/auto_html/filters/google_video.rb +0 -6
  33. data/lib/auto_html/filters/hashtag.rb +0 -7
  34. data/lib/auto_html/filters/html_escape.rb +0 -9
  35. data/lib/auto_html/filters/image.rb +0 -16
  36. data/lib/auto_html/filters/instagram.rb +0 -10
  37. data/lib/auto_html/filters/link.rb +0 -16
  38. data/lib/auto_html/filters/liveleak.rb +0 -19
  39. data/lib/auto_html/filters/metacafe.rb +0 -13
  40. data/lib/auto_html/filters/redcarpet.rb +0 -4
  41. data/lib/auto_html/filters/sanitize.rb +0 -5
  42. data/lib/auto_html/filters/simple_format.rb +0 -12
  43. data/lib/auto_html/filters/soundcloud.rb +0 -21
  44. data/lib/auto_html/filters/ted.rb +0 -13
  45. data/lib/auto_html/filters/twitter.rb +0 -19
  46. data/lib/auto_html/filters/vimeo.rb +0 -15
  47. data/lib/auto_html/filters/worldstar.rb +0 -8
  48. data/lib/auto_html/filters/youtube.rb +0 -19
  49. data/lib/auto_html/filters/youtube_js_api.rb +0 -6
  50. data/lib/auto_html/railtie.rb +0 -10
  51. data/lib/auto_html/rake_tasks.rb +0 -27
  52. data/lib/auto_html/task.rb +0 -9
  53. data/test/fixture_setup.rb +0 -13
  54. data/test/fixtures/database.yml +0 -5
  55. data/test/fixtures/schema.rb +0 -20
  56. data/test/functional/auto_html_for_options_test.rb +0 -26
  57. data/test/functional/auto_html_for_test.rb +0 -56
  58. data/test/functional/filter_test.rb +0 -27
  59. data/test/test_helper.rb +0 -9
  60. data/test/unit/auto_html_test.rb +0 -37
  61. data/test/unit/filters/dailymotion_test.rb +0 -20
  62. data/test/unit/filters/gist_test.rb +0 -15
  63. data/test/unit/filters/google_map_test.rb +0 -24
  64. data/test/unit/filters/hashtag_test.rb +0 -25
  65. data/test/unit/filters/html_escape_test.rb +0 -15
  66. data/test/unit/filters/image_test.rb +0 -65
  67. data/test/unit/filters/instagram_test.rb +0 -8
  68. data/test/unit/filters/link_test.rb +0 -55
  69. data/test/unit/filters/liveleak_test.rb +0 -15
  70. data/test/unit/filters/metacafe_test.rb +0 -29
  71. data/test/unit/filters/redcarpet_test.rb +0 -38
  72. data/test/unit/filters/sanitize_test.rb +0 -36
  73. data/test/unit/filters/simple_format_test.rb +0 -15
  74. data/test/unit/filters/soundcloud_test.rb +0 -29
  75. data/test/unit/filters/ted_test.rb +0 -18
  76. data/test/unit/filters/twitter_test.rb +0 -45
  77. data/test/unit/filters/vimeo_test.rb +0 -50
  78. data/test/unit/filters/worldstar_test.rb +0 -14
  79. data/test/unit/filters/youtube_js_api_test.rb +0 -30
  80. data/test/unit/filters/youtube_test.rb +0 -59
  81. data/test/unit/unit_test_helper.rb +0 -3
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fe9d59c6aaaa2ac3a738aaceeab582872044be2d3983957e6cc3f973023fa10a
4
+ data.tar.gz: 4667fc4cd2183f36a8141446050b8ab31abbbdd6ef06ae8bf547fd75a43660db
5
+ SHA512:
6
+ metadata.gz: b091f4972d71693b18ffb2d19ecc9fa9361d4f0787a7a75bc0c9f10aee59b7d3dc346909a741485ef7ce2e82e2c9960e5cc45d8ad38f53a0e4fed8a590bb7f46
7
+ data.tar.gz: 4d79645b12e7ff1e7884f460b36c9d95496698780f2854183afdaa719b585d98f328fdb99355dc08949c7696dfb420195c1113b53e751bf0267f77a291bc2dd3
data/README.md CHANGED
@@ -1,123 +1,94 @@
1
- auto_html [![Build Status](https://secure.travis-ci.org/dejan/auto_html.png?branch=master)](http://travis-ci.org/dejan/auto_html)
2
- =========
1
+ # AutoHtml
3
2
 
3
+ AutoHtml is a collection of filters that transforms plain text into HTML code.
4
4
 
5
- auto_html is a Rails extension for transforming URLs to appropriate resource (image, link, YouTube, Vimeo video,...). It's the perfect choice if you don't want to bother visitors with rich HTML editor or markup code, but you still want to allow them to embed video, images, links and more on your site, purely by pasting URL. Check out the [live demo](http://rors.org/demos/auto_html).
5
+ ## Installation
6
6
 
7
+ Add this line to your application's Gemfile:
7
8
 
8
- ## Install
9
+ ```ruby
10
+ gem 'auto_html'
11
+ ```
9
12
 
10
- Specify the gem in Gemfile of the project
13
+ And then execute:
11
14
 
12
- gem "auto_html"
15
+ ```sh
16
+ $ bundle
17
+ ```
13
18
 
19
+ Or install it yourself as:
14
20
 
15
- ## Example usage
21
+ ```sh
22
+ $ gem install auto_html
23
+ ```
16
24
 
17
- Transforming string with text and URLs is done with *auto_html* method:
25
+ ## Abstract
18
26
 
19
- include AutoHtml
20
-
21
- auto_html('Hey! Checkout out: http://vukajlija.com') { simple_format; link(:target => 'blank') }
22
- => "<p>Hey! Checkout out: <a href='http://vukajlija.com' target='blank'>http://vukajlija.com</a></p>"
27
+ AutoHtml uses concepts found in "Pipes and Filters" processing design pattern:
23
28
 
24
- You'll probably have user input stored in model, so it's a good place to automate and even store this conversion for performance reason. This is done with *auto_html_for* method. Let's say you have model Comment with attribute body. Create another column in table Comments called body_html (again, this is optional but recommended for performance reasons). Now have something like this:
29
+ * `Filter` - transforms an input. In AutoHtml context, this is any object that does the transformation through `#call(String)` method. Filter options should be passed in initializer. AutoHtml provides some filters already, ie Link, Image, Markdown, etc.
30
+ * `Pipeline` - a composition of filters that transforms input by passing the output of one filter as input for the next filter in line. In AutoHtml context, this is the `AutoHtml::Pipeline` class. Since the same interface (method `#call`) is used to pass input, we can say that Pipeline is just another Filter, which means it can be used as a building block for other Pipelines, in a mix with other filters.
25
31
 
26
- class Comment < ActiveRecord::Base
27
- auto_html_for :body do
28
- html_escape
29
- image
30
- youtube(:width => 400, :height => 250, :autoplay => true)
31
- link :target => "_blank", :rel => "nofollow"
32
- simple_format
33
- end
34
- end
32
+ ## Examples
35
33
 
36
- ... and you'll have this behavior:
34
+ ```ruby
35
+ link_filter = AutoHtml::Link.new(target: '_blank')
36
+ link_filter.call('Checkout out my blog: http://rors.org')
37
+ # => 'Checkout out my blog: <a target="blank" href="http://rors.org">http://rors.org</a>'
37
38
 
38
- Comment.create(:body => 'Hey check out this cool video: http://www.youtube.com/watch?v=WdsGihou8J4')
39
- => #<Comment id: 123, body: '<p>Hey check out this cool video: <div class="video youtube"><iframe class="youtube-player" type="text/html" width="587" height="350" src="http://www.youtube.com/embed/WdsGihou8J4" frameborder="0"> <br /></iframe></div></p>'>
39
+ emoji_filter = AutoHtml::Emoji.new
40
+ emoji_filter.call(':point_left: yo!')
41
+ # => '<img src="/images/emoji/unicode/1f448.png" class="emoji" title=":point_left:" alt=":point_left:" height="20" witdh="20" align="absmiddle" /> yo!'
40
42
 
41
- Note that order of invoking filters is important, i.e. you want html_escape as first and link amongst last, so that it doesn't transform youtube URL to plain link.
42
-
43
-
44
- Now all you have to do is to display it in template without escaping, since plugin took care of that:
45
-
46
- <% for comment in @comments %>
47
- <li><%= comment.body_html %></li>
48
- <% end %>
49
-
50
-
51
- If you need to display preview, no problem. Have something like this as action in your controller:
52
-
53
- def preview
54
- comment = Comment.new(params[:comment])
55
- render :text => comment.body_html
56
- end
57
-
58
- AutoHtml is highly customizable, and you can easily create new filters that will transform user input any way you like. For instance, this is the image filter that comes bundled with plugin:
59
-
60
- AutoHtml.add_filter(:image) do |text|
61
- text.gsub(/http:\/\/.+\.(jpg|jpeg|bmp|gif|png)(\?\S+)?/i) do |match|
62
- %|<img src="#{match}" alt=""/>|
63
- end
64
- end
43
+ # Use Pipeline to combine filters
44
+ base_format = AutoHtml::Pipeline.new(link_filter, emoji_filter)
45
+ base_format.call('Checkout out my blog: http://rors.org :point_left: yo!')
46
+ # => 'Checkout out my blog: <a href="http://rors.org">http://rors.org</a> <img src="/images/emoji/unicode/1f448.png" class="emoji" title=":point_left:" alt=":point_left:" height="20" witdh="20" align="absmiddle" /> yo!'
65
47
 
48
+ # A pipeline can be reused in another pipeline. Note that the order of filters is important - ie you want
49
+ # `Image` before `Link` filter so that URL of the image gets transformed to `img` tag and not `a` tag.
50
+ comment_format = AutoHtml::Pipeline.new(AutoHtml::Markdown.new, AutoHtml::Image.new, base_format)
51
+ comment_format.call("Hello!\n\n Checkout out my blog: http://rors.org :point_left: yo! \n\n http://gifs.joelglovier.com/boom/booyah.gif")
52
+ # => "<p>Hello!</p>\n\n<p>Checkout out my blog: <a href="<img src="http://rors.org" target="_blank">http://rors.org</a> <img src="/images/emoji/unicode/1f448.png" />" class="emoji" title=":point_left:" alt=":point_left:" height="20" witdh="20" align="absmiddle" /> yo! </p>\n\n<p><a href="<img src="http://gifs.joelglovier.com/boom/booyah.gif" />" target="_blank"><img src="http://gifs.joelglovier.com/boom/booyah.gif" /></a></p>\n"
53
+ ```
66
54
 
67
55
  ## Bundled filters
68
56
 
69
- For filter list and options they support check: <http://github.com/dejan/auto_html/tree/master/lib/auto_html/filters>
70
-
71
-
72
- ## Non-ActiveRecord models
73
-
74
- AutoHtml uses standard ActiveModel API, which means that you can include AutoHtmlFor module (that automates transformation of the field) in any non-ActiveRecord model that uses ActiveModel. Here's working [mongoid](http://mongoid.org/) example:
75
-
76
- class Post
77
- include Mongoid::Document
78
- include AutoHtmlFor
79
-
80
- field :body
57
+ Bellow is the list of bundled filters along with their optional arguments on initialization and their default values.
81
58
 
82
- auto_html_for :body do
83
- simple_format
84
- link
85
- end
86
- end
59
+ * `AutoHtml::Emoji`
60
+ * `AutoHtml::HtmlEscape`
61
+ * `AutoHtml::Image`, proxy: nil, alt: nil
62
+ * `AutoHtml::Link`, target: nil, rel: nil
63
+ * `AutoHtml::Markdown`
64
+ * `AutoHtml::SimpleFormat`
87
65
 
66
+ ## Using AutoHtml with ActiveRecord
88
67
 
89
- ## Rake and Capistrano tasks
68
+ For performance reasons it's a good idea to store the formated output in the database, in a separate column, to avoid generating the same content on each access.
69
+ This can be acomplished simply by overriding the attribute writter:
90
70
 
91
- AutoHtml has a Rake task for rebuilding cached in DB column values
92
- Usage: `rake auto_html:rebuild CLASS=[your model]`
93
- Where `[your model]` is the name of model which values you want to rebuild.
71
+ ```ruby
72
+ class Comment < ActiveRecord::Base
73
+ FORMAT = AutoHtml::Pipeline.new(
74
+ AutoHtml::HtmlEscape.new,
75
+ AutoHtml::Markdown.new
76
+ )
94
77
 
95
- If you want to run it on remote server, just add this to your `deploy.rb`:
78
+ def text=(t)
79
+ super(t)
80
+ self[:text_html] = FORMAT.call(t)
81
+ end
82
+ end
83
+ ```
96
84
 
97
- require 'auto_html/capistrano'
98
-
99
- Now you can run `cap auto_html:rebuild CLASS=[your_model]`.
85
+ Now, every time `text` attribute is set, `text_html` will be set as well:
100
86
 
87
+ ```Ruby
88
+ comment = Comment.new(text: 'Hey!')
89
+ comment.text_html # => '<p>Hey!</p>'
90
+ ```
101
91
 
102
92
  ## Licence
103
93
 
104
- Copyright (c) 2009 Dejan Simic
105
-
106
- Permission is hereby granted, free of charge, to any person obtaining
107
- a copy of this software and associated documentation files (the
108
- "Software"), to deal in the Software without restriction, including
109
- without limitation the rights to use, copy, modify, merge, publish,
110
- distribute, sublicense, and/or sell copies of the Software, and to
111
- permit persons to whom the Software is furnished to do so, subject to
112
- the following conditions:
113
-
114
- The above copyright notice and this permission notice shall be
115
- included in all copies or substantial portions of the Software.
116
-
117
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
118
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
119
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
120
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
121
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
122
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
123
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
94
+ AutoHtml is released under the [MIT License](https://raw.githubusercontent.com/dejan/auto_html/master/MIT-LICENSE).
data/Rakefile CHANGED
@@ -1,9 +1,10 @@
1
- require 'rake/testtask'
1
+ # frozen_string_literal: true
2
2
 
3
- desc 'Default: run tests'
4
- task :default => :test
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
5
6
 
6
- desc 'Test AutoHtml'
7
- Rake::TestTask.new(:test) do |t|
8
- t.pattern = 'test/**/*_test.rb'
9
- end
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new
9
+
10
+ task default: %i[rubocop spec]
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gemoji'
4
+
5
+ module AutoHtml
6
+ # Emoji filter
7
+ class Emoji
8
+ def call(text)
9
+ text.gsub(self.class.emoji_pattern) do
10
+ name = Regexp.last_match(1)
11
+ ::Emoji.find_by_alias(name).raw
12
+ end
13
+ end
14
+
15
+ def self.emoji_pattern
16
+ @emoji_pattern ||=
17
+ /:(#{emoji_names.map { |name| Regexp.escape(name) }.join('|')}):/
18
+ end
19
+
20
+ def self.emoji_names
21
+ ::Emoji.all.map(&:aliases).flatten.sort
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+
5
+ module AutoHtml
6
+ # HTML escape filter
7
+ class HtmlEscape
8
+ def call(text)
9
+ CGI.escapeHTML(text)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AutoHtml
4
+ # Image filter
5
+ class Image
6
+ def initialize(proxy: nil, alt: nil)
7
+ @proxy = proxy || ''
8
+ @alt = alt
9
+ end
10
+
11
+ def call(text)
12
+ text.gsub(image_pattern) do |match|
13
+ TagHelper.tag(:img, src: @proxy + match, alt: @alt)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def image_pattern
20
+ %r{(?<!src=")https?://.+?\.(jpg|jpeg|bmp|gif|png|svg)(\?\S+)?}i
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'rinku'
5
+ require 'rexml/document'
6
+
7
+ module AutoHtml
8
+ # Link filter
9
+ class Link
10
+ def initialize(target: nil, rel: nil)
11
+ @target = target
12
+ @rel = rel
13
+ end
14
+
15
+ def call(text)
16
+ Rinku.auto_link(text, :all, attributes)
17
+ end
18
+
19
+ private
20
+
21
+ def attributes
22
+ [target_attr, rel_attr].compact.join(' ') unless [target_attr, rel_attr].compact.empty?
23
+ end
24
+
25
+ def rel_attr
26
+ %(rel="#{@rel}") if @rel
27
+ end
28
+
29
+ def target_attr
30
+ %(target="#{@target}") if @target
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'redcarpet'
4
+
5
+ module AutoHtml
6
+ # Markdown filter
7
+ class Markdown
8
+ def initialize
9
+ render = Redcarpet::Render::HTML
10
+ @markdown = Redcarpet::Markdown.new(render)
11
+ end
12
+
13
+ def call(text)
14
+ @markdown.render(text)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AutoHtml
4
+ # Applies collection of filters to a text
5
+ class Pipeline
6
+ def initialize(*filters)
7
+ @filters = filters.flatten
8
+ end
9
+
10
+ def call(text)
11
+ return '' if text.nil? || text.empty?
12
+
13
+ @filters.inject(text) do |content, filter|
14
+ filter.call(content)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AutoHtml
4
+ # SimpleFormat filter
5
+ class SimpleFormat
6
+ def call(text)
7
+ paragraphs = split_paragraphs(text)
8
+ paragraphs.map! do |paragraph|
9
+ TagHelper.tag(:p) { paragraph }
10
+ end.join("\n\n")
11
+ end
12
+
13
+ private
14
+
15
+ def split_paragraphs(text)
16
+ return [] if text.nil? || text.empty?
17
+
18
+ text.to_s.gsub(/\r\n?/, "\n").split(/\n\n+/).map! do |t|
19
+ t.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />') || t
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AutoHtml
4
+ # XHTML tags builder
5
+ module TagHelper
6
+ def tag(tag_name, attrs = {})
7
+ if block_given?
8
+ content_tag(tag_name, yield, attrs)
9
+ else
10
+ unary_tag(tag_name, attrs)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def unary_tag(tag_name, attrs = {})
17
+ "<#{tag_and_attributes(tag_name, tag_attributes(attrs))} />"
18
+ end
19
+
20
+ def content_tag(tag_name, value, attrs = {})
21
+ start_tag = "<#{tag_and_attributes(tag_name, tag_attributes(attrs))}>"
22
+ end_tag = "</#{tag_name}>"
23
+ [start_tag, value, end_tag].join
24
+ end
25
+
26
+ def tag_and_attributes(tag_name, attributes)
27
+ attributes.empty? ? tag_name : "#{tag_name} #{attributes}"
28
+ end
29
+
30
+ def tag_attributes(hash)
31
+ hash.compact
32
+ .to_a
33
+ .map { |k, v| %(#{k}="#{v}") }.join(' ')
34
+ end
35
+
36
+ extend self
37
+ end
38
+ end
data/lib/auto_html.rb CHANGED
@@ -1,17 +1,13 @@
1
- %w(base filter builder auto_html_for).each do |f|
2
- require File.expand_path("../auto_html/#{f}", __FILE__)
3
- end
1
+ # frozen_string_literal: true
4
2
 
5
- Dir["#{File.dirname(__FILE__) + '/auto_html/filters'}/**/*"].each do |filter|
6
- require "#{filter}"
3
+ # AutoHtml is a collection of filters that transform plain text into HTML code.
4
+ module AutoHtml
5
+ autoload :Pipeline, 'auto_html/pipeline'
6
+ autoload :TagHelper, 'auto_html/tag_helper'
7
+ autoload :Emoji, 'auto_html/emoji'
8
+ autoload :HtmlEscape, 'auto_html/html_escape'
9
+ autoload :Image, 'auto_html/image'
10
+ autoload :Link, 'auto_html/link'
11
+ autoload :Markdown, 'auto_html/markdown'
12
+ autoload :SimpleFormat, 'auto_html/simple_format'
7
13
  end
8
-
9
- # if rails
10
- require 'auto_html/railtie' if defined?(Rails::Railtie)
11
- if defined?(ActiveRecord::Base)
12
- ActiveRecord::Base.send :include, AutoHtmlFor
13
-
14
- module ActionView::Helpers::TextHelper
15
- include AutoHtml
16
- end
17
- end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe AutoHtml::Emoji do
6
+ it 'converts emoji to HTML' do
7
+ expect(subject.call(':joy:')).to eq('😂')
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe AutoHtml::HtmlEscape do
6
+ it 'escapes html tags' do
7
+ result = subject.call('<script>alert(0)</script>')
8
+ expect(result).to eq '&lt;script&gt;alert(0)&lt;/script&gt;'
9
+ end
10
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe AutoHtml::Image do
6
+ it 'transforms an image link to image tag' do
7
+ result = subject.call('http://rors.org/images/rails.png')
8
+ expect(result).to eq('<img src="http://rors.org/images/rails.png" />')
9
+ end
10
+
11
+ it 'transforms image link with a param to image tag' do
12
+ result = subject.call('http://farm4.static.flickr.com/3664/3512431377_71b8d002ef.jpg?v=0')
13
+ expect(result).to eq('<img src="http://farm4.static.flickr.com/3664/3512431377_71b8d002ef.jpg?v=0" />')
14
+ end
15
+
16
+ it 'transforms image link on https to image tag' do
17
+ result = subject.call('https://img.skitch.com/20100910-1wrbg5749xe29ya5t3s85bnaiy.png')
18
+ expect(result).to eq('<img src="https://img.skitch.com/20100910-1wrbg5749xe29ya5t3s85bnaiy.png" />')
19
+ end
20
+
21
+ it 'transforms image link to a image tag with proxy as source' do
22
+ filter = AutoHtml::Image.new(proxy: 'https://proxy/?url=')
23
+ result = filter.call('http://img.skitch.com/20100910-1wrbg5749xe29ya5t3s85bnaiy.png')
24
+ expect(result).to eq('<img src="https://proxy/?url=http://img.skitch.com/20100910-1wrbg5749xe29ya5t3s85bnaiy.png" />')
25
+ end
26
+
27
+ it 'does not transforms already transformed image' do
28
+ result = subject.call('<img src="http://farm4.static.flickr.com/3459/3270173112_5099d3d730.jpg" />')
29
+ expect(result).to eq('<img src="http://farm4.static.flickr.com/3459/3270173112_5099d3d730.jpg" />')
30
+ end
31
+
32
+ it 'transforms an image link within text to image tag' do
33
+ result = subject.call('Which do you prefer, this one http://www.lockhartfineart.com/images/Rio_Grande_Frost.JPG, or this one http://rors.org/images/rails.png?')
34
+ expect(result).to eq('Which do you prefer, this one <img src="http://www.lockhartfineart.com/images/Rio_Grande_Frost.JPG" />, or this one <img src="http://rors.org/images/rails.png" />?')
35
+ end
36
+
37
+ it 'transforms an image link with a lot of param to image tag' do
38
+ result = subject.call('http://tbn3.google.com/images?q=tbn:vS-jtEi9Xc8K6M:http://upload.wikimedia.org/wikipedia/commons/b/ba/Potturinn.jpeg')
39
+ expect(result).to eq('<img src="http://tbn3.google.com/images?q=tbn:vS-jtEi9Xc8K6M:http://upload.wikimedia.org/wikipedia/commons/b/ba/Potturinn.jpeg" />')
40
+ end
41
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe AutoHtml::Link do
6
+ it 'transforms URL to a link' do
7
+ result = subject.call('<a href="https://www.ruby-lang.org/en/" >https://www.ruby-lang.org/en/</a>')
8
+ expect(result).to eq '<a href="https://www.ruby-lang.org/en/" >https://www.ruby-lang.org/en/</a>'
9
+ end
10
+
11
+ it 'transforms URL with param to a link' do
12
+ result = subject.call('http://example.com/abc?query=ruby')
13
+ expect(result).to eq '<a href="http://example.com/abc?query=ruby">http://example.com/abc?query=ruby</a>'
14
+ end
15
+
16
+ it 'transforms URL with param and a trailing dot' do
17
+ result = subject.call('http://example.com/abc?query=ruby.')
18
+ expect(result).to eq '<a href="http://example.com/abc?query=ruby">http://example.com/abc?query=ruby</a>.'
19
+ end
20
+
21
+ it 'transforms URL with anchor and a trailing dot' do
22
+ result = subject.call('http://example.com/example#id=123.12.')
23
+ expect(result).to eq '<a href="http://example.com/example#id=123.12">http://example.com/example#id=123.12</a>.'
24
+ end
25
+
26
+ it 'transforms URL with commas' do
27
+ result = subject.call('http://www.dw-world.de/dw/article/0,,4708386,00.html?maca=ser-rss-ser-all-1494-rdf')
28
+ expect(result).to eq '<a href="http://www.dw-world.de/dw/article/0,,4708386,00.html?maca=ser-rss-ser-all-1494-rdf">http://www.dw-world.de/dw/article/0,,4708386,00.html?maca=ser-rss-ser-all-1494-rdf</a>'
29
+ end
30
+
31
+ it 'transforms complex URL' do
32
+ result = subject.call('http://www.google.com/#q=nikola+tesla&ct=tesla09&oi=ddle&fp=Xmf0jJ9P_V0')
33
+ expect(result).to eq '<a href="http://www.google.com/#q=nikola+tesla&ct=tesla09&oi=ddle&fp=Xmf0jJ9P_V0">http://www.google.com/#q=nikola+tesla&ct=tesla09&oi=ddle&fp=Xmf0jJ9P_V0</a>'
34
+ end
35
+
36
+ it 'transforms with target options' do
37
+ filter = described_class.new(target: '_blank')
38
+ result = filter.call('http://rors.org')
39
+ expect(result).to eq '<a href="http://rors.org" target="_blank">http://rors.org</a>'
40
+ end
41
+
42
+ it 'transforms with rel options' do
43
+ filter = described_class.new(rel: 'nofollow')
44
+ result = filter.call('http://rors.org')
45
+ expect(result).to eq '<a href="http://rors.org" rel="nofollow">http://rors.org</a>'
46
+ end
47
+
48
+ it 'transforms with target and rel options' do
49
+ filter = described_class.new(target: '_blank', rel: 'nofollow')
50
+ result = filter.call('http://rors.org')
51
+ expect(result).to eq '<a href="http://rors.org" target="_blank" rel="nofollow">http://rors.org</a>'
52
+ end
53
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe AutoHtml::Markdown do
6
+ it 'formats input using simple GFM rules' do
7
+ expect(subject.call('*hello*')).to eq "<p><em>hello</em></p>\n"
8
+ end
9
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe AutoHtml::Pipeline do
6
+ subject { described_class.new(AutoHtml::SimpleFormat.new, AutoHtml::Image.new, AutoHtml::Link.new) }
7
+
8
+ it 'does not transforms input when no filters provided' do
9
+ input = 'Hey check out my blog => http://rors.org'
10
+ result = described_class.new.call(input)
11
+ expect(result).to eq input
12
+ end
13
+
14
+ it 'transforms input using provided filters' do
15
+ result = subject.call 'Check the logo: http://rors.org/images/rails.png. Visit: http://rubyonrails.org'
16
+ expect(result).to eq '<p>Check the logo: <img src="http://rors.org/images/rails.png" />. Visit: <a href="http://rubyonrails.org">http://rubyonrails.org</a></p>'
17
+ end
18
+
19
+ it 'is blank if input is blank' do
20
+ expect(subject.call('')).to eq ''
21
+ end
22
+
23
+ it 'is blank if input is nil' do
24
+ expect(subject.call(nil)).to eq ''
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe AutoHtml::SimpleFormat do
6
+ it 'formats input using simple rules' do
7
+ result = subject.call('Hey check out my blog => http://rors.org')
8
+ expect(result).to eq '<p>Hey check out my blog => http://rors.org</p>'
9
+
10
+ expect(subject.call("crazy\r\n cross\r platform linebreaks")).to eq "<p>crazy\n<br /> cross\n<br /> platform linebreaks</p>"
11
+ expect(subject.call("A paragraph\n\nand another one!")).to eq "<p>A paragraph</p>\n\n<p>and another one!</p>"
12
+ expect(subject.call("A paragraph\n With a newline")).to eq "<p>A paragraph\n<br /> With a newline</p>"
13
+
14
+ expect(subject.call("A\nB\nC\nD")).to eq "<p>A\n<br />B\n<br />C\n<br />D</p>"
15
+
16
+ expect(subject.call("A\r\n \nB\n\n\r\n\t\nC\nD")).to eq "<p>A\n<br /> \n<br />B</p>\n\n<p>\t\n<br />C\n<br />D</p>"
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe AutoHtml::TagHelper do
6
+ it 'generates tag with attributes' do
7
+ result = subject.tag(:img, src: '1.png', alt: 'number one!')
8
+ expect(result).to eq '<img src="1.png" alt="number one!" />'
9
+ end
10
+
11
+ it 'generates tag without attributes' do
12
+ result = subject.tag(:br)
13
+ expect(result).to eq '<br />'
14
+ end
15
+
16
+ it 'generates content tags' do
17
+ result = subject.tag(:label, for: 'name') { 'Name' }
18
+ expect(result).to eq '<label for="name">Name</label>'
19
+ end
20
+
21
+ it 'generates content tags without attributes' do
22
+ result = subject.tag(:label) { 'Username' }
23
+ expect(result).to eq '<label>Username</label>'
24
+ end
25
+
26
+ it 'generates nested tags' do
27
+ result = subject.tag(:form) { subject.tag(:input, type: 'text') }
28
+ expect(result).to eq '<form><input type="text" /></form>'
29
+ end
30
+ end