Merge pull request #462 from dgilperez/auto_linking
Adds autolinking for comments
This commit is contained in:
3
Gemfile
3
Gemfile
@@ -29,7 +29,7 @@ gem 'omniauth-google-oauth2'
|
|||||||
gem 'kaminari'
|
gem 'kaminari'
|
||||||
gem 'ancestry'
|
gem 'ancestry'
|
||||||
gem 'acts-as-taggable-on'
|
gem 'acts-as-taggable-on'
|
||||||
gem "responders"
|
gem 'responders'
|
||||||
gem 'foundation-rails'
|
gem 'foundation-rails'
|
||||||
gem 'foundation_rails_helper'
|
gem 'foundation_rails_helper'
|
||||||
gem 'acts_as_votable'
|
gem 'acts_as_votable'
|
||||||
@@ -40,6 +40,7 @@ gem 'social-share-button'
|
|||||||
gem 'initialjs-rails', '0.2.0'
|
gem 'initialjs-rails', '0.2.0'
|
||||||
gem 'unicorn'
|
gem 'unicorn'
|
||||||
gem 'paranoia'
|
gem 'paranoia'
|
||||||
|
gem 'rinku', require: 'rails_rinku'
|
||||||
gem 'savon'
|
gem 'savon'
|
||||||
gem 'dalli'
|
gem 'dalli'
|
||||||
gem 'rollbar', '~> 2.2.1'
|
gem 'rollbar', '~> 2.2.1'
|
||||||
|
|||||||
@@ -294,6 +294,7 @@ GEM
|
|||||||
http-cookie (>= 1.0.2, < 2.0)
|
http-cookie (>= 1.0.2, < 2.0)
|
||||||
mime-types (>= 1.16, < 3.0)
|
mime-types (>= 1.16, < 3.0)
|
||||||
netrc (~> 0.7)
|
netrc (~> 0.7)
|
||||||
|
rinku (1.7.3)
|
||||||
rollbar (2.2.1)
|
rollbar (2.2.1)
|
||||||
rspec (3.3.0)
|
rspec (3.3.0)
|
||||||
rspec-core (~> 3.3.0)
|
rspec-core (~> 3.3.0)
|
||||||
@@ -444,6 +445,7 @@ DEPENDENCIES
|
|||||||
quiet_assets
|
quiet_assets
|
||||||
rails (= 4.2.4)
|
rails (= 4.2.4)
|
||||||
responders
|
responders
|
||||||
|
rinku
|
||||||
rollbar (~> 2.2.1)
|
rollbar (~> 2.2.1)
|
||||||
rspec-rails (~> 3.0)
|
rspec-rails (~> 3.0)
|
||||||
sass-rails (~> 5.0)
|
sass-rails (~> 5.0)
|
||||||
|
|||||||
9
app/helpers/text_with_links_helper.rb
Normal file
9
app/helpers/text_with_links_helper.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
module TextWithLinksHelper
|
||||||
|
|
||||||
|
def text_with_links(text)
|
||||||
|
return unless text
|
||||||
|
sanitized = sanitize text, tags: [], attributes: []
|
||||||
|
Rinku.auto_link(sanitized, :all, 'target="_blank" rel="nofollow"').html_safe
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
class Mailer < ApplicationMailer
|
class Mailer < ApplicationMailer
|
||||||
|
helper :text_with_links
|
||||||
|
|
||||||
def comment(comment)
|
def comment(comment)
|
||||||
@comment = comment
|
@comment = comment
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<li id="<%= dom_id(comment) %>">
|
<li id="<%= dom_id(comment) %>">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="small-12 medium-8 column">
|
<div class="small-12 medium-8 column">
|
||||||
<%= comment.body %>
|
<%= text_with_links comment.body %>
|
||||||
<%= link_to comment.commentable.title, comment.commentable %>
|
<%= link_to comment.commentable.title, comment.commentable %>
|
||||||
</div>
|
</div>
|
||||||
<div class="small-6 medium-4 column text-right">
|
<div class="small-6 medium-4 column text-right">
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<li id="<%= dom_id(comment) %>">
|
<li id="<%= dom_id(comment) %>">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="small-12 medium-10 column">
|
<div class="small-12 medium-10 column">
|
||||||
<%= comment.body %>
|
<%= text_with_links comment.body %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -63,17 +63,17 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% if comment.as_administrator? %>
|
<% if comment.as_administrator? %>
|
||||||
<p class="comment-user is-admin"><%= comment.body %></p>
|
<p class="comment-user is-admin"><%= text_with_links comment.body %></p>
|
||||||
<% elsif comment.as_moderator? %>
|
<% elsif comment.as_moderator? %>
|
||||||
<p class="comment-user is-moderator"><%= comment.body %></p>
|
<p class="comment-user is-moderator"><%= text_with_links comment.body %></p>
|
||||||
<% elsif comment.user.official? && comment.user_id == @commentable.author_id %>
|
<% elsif comment.user.official? && comment.user_id == @commentable.author_id %>
|
||||||
<p class="comment-user level-<%= comment.user.official_level %> is-author"><%= comment.body %></p>
|
<p class="comment-user level-<%= comment.user.official_level %> is-author"><%= text_with_links comment.body %></p>
|
||||||
<% elsif comment.user.official? %>
|
<% elsif comment.user.official? %>
|
||||||
<p class="comment-user level-<%= comment.user.official_level %>"><%= comment.body %></p>
|
<p class="comment-user level-<%= comment.user.official_level %>"><%= text_with_links comment.body %></p>
|
||||||
<% elsif comment.user_id == @commentable.author_id %>
|
<% elsif comment.user_id == @commentable.author_id %>
|
||||||
<p class="comment-user is-author"><%= comment.body %></p>
|
<p class="comment-user is-author"><%= text_with_links comment.body %></p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<p class="comment-user"><%= comment.body %></p>
|
<p class="comment-user"><%= text_with_links comment.body %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
<span id="<%= dom_id(comment) %>_votes" class="comment-votes right">
|
<span id="<%= dom_id(comment) %>_votes" class="comment-votes right">
|
||||||
<%= render 'comments/votes', comment: comment %>
|
<%= render 'comments/votes', comment: comment %>
|
||||||
|
|||||||
@@ -13,6 +13,6 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p style="border-left: 2px solid #DEE0E3;font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-style: italic;font-weight: normal;line-height: 24px;margin-left: 20px;padding: 10px;">
|
<p style="border-left: 2px solid #DEE0E3;font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-style: italic;font-weight: normal;line-height: 24px;margin-left: 20px;padding: 10px;">
|
||||||
<%= @comment.body %>
|
<%= text_with_links @comment.body %>
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -13,6 +13,6 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p style="border-left: 2px solid #DEE0E3;font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-style: italic;font-weight: normal;line-height: 24px;margin-left: 20px;padding: 10px;">
|
<p style="border-left: 2px solid #DEE0E3;font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-style: italic;font-weight: normal;line-height: 24px;margin-left: 20px;padding: 10px;">
|
||||||
<%= @reply.body %>
|
<%= text_with_links @reply.body %>
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<%= comment.commentable_type.constantize.model_name.human %>
|
<%= comment.commentable_type.constantize.model_name.human %>
|
||||||
<span class="date"><%= l comment.updated_at.to_date %></span>
|
<span class="date"><%= l comment.updated_at.to_date %></span>
|
||||||
</td>
|
</td>
|
||||||
<td><%= comment.body %></td>
|
<td><%= text_with_links comment.body %></td>
|
||||||
<td class="text-center"><%= comment.flags_count %></td>
|
<td class="text-center"><%= comment.flags_count %></td>
|
||||||
<td>
|
<td>
|
||||||
<%= link_to t("moderation.comments.index.hide"), hide_in_moderation_screen_moderation_comment_path(comment, request.query_parameters), method: :put, class: "delete" %>
|
<%= link_to t("moderation.comments.index.hide"), hide_in_moderation_screen_moderation_comment_path(comment, request.query_parameters), method: :put, class: "delete" %>
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ require 'rails_helper'
|
|||||||
include ActionView::Helpers::DateHelper
|
include ActionView::Helpers::DateHelper
|
||||||
|
|
||||||
feature 'Comments' do
|
feature 'Comments' do
|
||||||
|
let(:user) { create :user }
|
||||||
|
let(:debate) { create :debate }
|
||||||
|
|
||||||
scenario 'Index' do
|
scenario 'Index' do
|
||||||
debate = create(:debate)
|
|
||||||
3.times { create(:comment, commentable: debate) }
|
3.times { create(:comment, commentable: debate) }
|
||||||
|
|
||||||
visit debate_path(debate)
|
visit debate_path(debate)
|
||||||
@@ -19,8 +20,32 @@ feature 'Comments' do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scenario 'Turns links into html links' do
|
||||||
|
create :comment, commentable: debate, body: 'Built with http://rubyonrails.org/'
|
||||||
|
|
||||||
|
visit debate_path(debate)
|
||||||
|
|
||||||
|
within first('.comment') do
|
||||||
|
expect(page).to have_content 'Built with http://rubyonrails.org/'
|
||||||
|
expect(page).to have_link('http://rubyonrails.org/', href: 'http://rubyonrails.org/')
|
||||||
|
expect(find_link('http://rubyonrails.org/')[:rel]).to eq('nofollow')
|
||||||
|
expect(find_link('http://rubyonrails.org/')[:target]).to eq('_blank')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Sanitizes comment body for security' do
|
||||||
|
create :comment, commentable: debate, body: "<script>alert('hola')</script> <a href=\"javascript:alert('sorpresa!')\">click me<a/> http://madrid.es"
|
||||||
|
|
||||||
|
visit debate_path(debate)
|
||||||
|
|
||||||
|
within first('.comment') do
|
||||||
|
expect(page).to have_content "click me http://madrid.es"
|
||||||
|
expect(page).to have_link('http://madrid.es', href: 'http://madrid.es')
|
||||||
|
expect(page).not_to have_link('click me')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
scenario 'Paginated comments' do
|
scenario 'Paginated comments' do
|
||||||
debate = create(:debate)
|
|
||||||
per_page = 10
|
per_page = 10
|
||||||
(per_page + 2).times { create(:comment, commentable: debate)}
|
(per_page + 2).times { create(:comment, commentable: debate)}
|
||||||
|
|
||||||
@@ -39,7 +64,6 @@ feature 'Comments' do
|
|||||||
|
|
||||||
feature 'Not logged user' do
|
feature 'Not logged user' do
|
||||||
scenario 'can not see comments forms' do
|
scenario 'can not see comments forms' do
|
||||||
debate = create(:debate)
|
|
||||||
create(:comment, commentable: debate)
|
create(:comment, commentable: debate)
|
||||||
visit debate_path(debate)
|
visit debate_path(debate)
|
||||||
|
|
||||||
@@ -53,9 +77,6 @@ feature 'Comments' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
scenario 'Create', :js do
|
scenario 'Create', :js do
|
||||||
user = create(:user)
|
|
||||||
debate = create(:debate)
|
|
||||||
|
|
||||||
login_as(user)
|
login_as(user)
|
||||||
visit debate_path(debate)
|
visit debate_path(debate)
|
||||||
|
|
||||||
@@ -68,9 +89,6 @@ feature 'Comments' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
scenario 'Errors on create', :js do
|
scenario 'Errors on create', :js do
|
||||||
user = create(:user)
|
|
||||||
debate = create(:debate)
|
|
||||||
|
|
||||||
login_as(user)
|
login_as(user)
|
||||||
visit debate_path(debate)
|
visit debate_path(debate)
|
||||||
|
|
||||||
@@ -82,7 +100,6 @@ feature 'Comments' do
|
|||||||
scenario 'Reply', :js do
|
scenario 'Reply', :js do
|
||||||
citizen = create(:user, username: 'Ana')
|
citizen = create(:user, username: 'Ana')
|
||||||
manuela = create(:user, username: 'Manuela')
|
manuela = create(:user, username: 'Manuela')
|
||||||
debate = create(:debate)
|
|
||||||
comment = create(:comment, commentable: debate, user: citizen)
|
comment = create(:comment, commentable: debate, user: citizen)
|
||||||
|
|
||||||
login_as(manuela)
|
login_as(manuela)
|
||||||
@@ -103,8 +120,6 @@ feature 'Comments' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
scenario 'Errors on reply', :js do
|
scenario 'Errors on reply', :js do
|
||||||
user = create(:user)
|
|
||||||
debate = create(:debate)
|
|
||||||
comment = create(:comment, commentable: debate, user: user)
|
comment = create(:comment, commentable: debate, user: user)
|
||||||
|
|
||||||
login_as(user)
|
login_as(user)
|
||||||
@@ -120,7 +135,6 @@ feature 'Comments' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
scenario "N replies", :js do
|
scenario "N replies", :js do
|
||||||
debate = create(:debate)
|
|
||||||
parent = create(:comment, commentable: debate)
|
parent = create(:comment, commentable: debate)
|
||||||
|
|
||||||
7.times do
|
7.times do
|
||||||
@@ -133,8 +147,6 @@ feature 'Comments' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
scenario "Flagging as inappropriate", :js do
|
scenario "Flagging as inappropriate", :js do
|
||||||
user = create(:user)
|
|
||||||
debate = create(:debate)
|
|
||||||
comment = create(:comment, commentable: debate)
|
comment = create(:comment, commentable: debate)
|
||||||
|
|
||||||
login_as(user)
|
login_as(user)
|
||||||
@@ -151,8 +163,6 @@ feature 'Comments' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
scenario "Undoing flagging as inappropriate", :js do
|
scenario "Undoing flagging as inappropriate", :js do
|
||||||
user = create(:user)
|
|
||||||
debate = create(:debate)
|
|
||||||
comment = create(:comment, commentable: debate)
|
comment = create(:comment, commentable: debate)
|
||||||
Flag.flag(user, comment)
|
Flag.flag(user, comment)
|
||||||
|
|
||||||
@@ -170,7 +180,6 @@ feature 'Comments' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
scenario "Flagging turbolinks sanity check", :js do
|
scenario "Flagging turbolinks sanity check", :js do
|
||||||
user = create(:user)
|
|
||||||
debate = create(:debate, title: "Should we change the world?")
|
debate = create(:debate, title: "Should we change the world?")
|
||||||
comment = create(:comment, commentable: debate)
|
comment = create(:comment, commentable: debate)
|
||||||
|
|
||||||
@@ -187,7 +196,6 @@ feature 'Comments' do
|
|||||||
feature "Moderators" do
|
feature "Moderators" do
|
||||||
scenario "can create comment as a moderator", :js do
|
scenario "can create comment as a moderator", :js do
|
||||||
moderator = create(:moderator)
|
moderator = create(:moderator)
|
||||||
debate = create(:debate)
|
|
||||||
|
|
||||||
login_as(moderator.user)
|
login_as(moderator.user)
|
||||||
visit debate_path(debate)
|
visit debate_path(debate)
|
||||||
@@ -208,7 +216,6 @@ feature 'Comments' do
|
|||||||
citizen = create(:user, username: "Ana")
|
citizen = create(:user, username: "Ana")
|
||||||
manuela = create(:user, username: "Manuela")
|
manuela = create(:user, username: "Manuela")
|
||||||
moderator = create(:moderator, user: manuela)
|
moderator = create(:moderator, user: manuela)
|
||||||
debate = create(:debate)
|
|
||||||
comment = create(:comment, commentable: debate, user: citizen)
|
comment = create(:comment, commentable: debate, user: citizen)
|
||||||
|
|
||||||
login_as(manuela)
|
login_as(manuela)
|
||||||
@@ -234,7 +241,6 @@ feature 'Comments' do
|
|||||||
|
|
||||||
scenario "can not comment as an administrator" do
|
scenario "can not comment as an administrator" do
|
||||||
moderator = create(:moderator)
|
moderator = create(:moderator)
|
||||||
debate = create(:debate)
|
|
||||||
|
|
||||||
login_as(moderator.user)
|
login_as(moderator.user)
|
||||||
visit debate_path(debate)
|
visit debate_path(debate)
|
||||||
@@ -246,7 +252,6 @@ feature 'Comments' do
|
|||||||
feature "Administrators" do
|
feature "Administrators" do
|
||||||
scenario "can create comment as an administrator", :js do
|
scenario "can create comment as an administrator", :js do
|
||||||
admin = create(:administrator)
|
admin = create(:administrator)
|
||||||
debate = create(:debate)
|
|
||||||
|
|
||||||
login_as(admin.user)
|
login_as(admin.user)
|
||||||
visit debate_path(debate)
|
visit debate_path(debate)
|
||||||
@@ -267,7 +272,6 @@ feature 'Comments' do
|
|||||||
citizen = create(:user, username: "Ana")
|
citizen = create(:user, username: "Ana")
|
||||||
manuela = create(:user, username: "Manuela")
|
manuela = create(:user, username: "Manuela")
|
||||||
admin = create(:administrator, user: manuela)
|
admin = create(:administrator, user: manuela)
|
||||||
debate = create(:debate)
|
|
||||||
comment = create(:comment, commentable: debate, user: citizen)
|
comment = create(:comment, commentable: debate, user: citizen)
|
||||||
|
|
||||||
login_as(manuela)
|
login_as(manuela)
|
||||||
@@ -293,7 +297,6 @@ feature 'Comments' do
|
|||||||
|
|
||||||
scenario "can not comment as a moderator" do
|
scenario "can not comment as a moderator" do
|
||||||
admin = create(:administrator)
|
admin = create(:administrator)
|
||||||
debate = create(:debate)
|
|
||||||
|
|
||||||
login_as(admin.user)
|
login_as(admin.user)
|
||||||
visit debate_path(debate)
|
visit debate_path(debate)
|
||||||
|
|||||||
Reference in New Issue
Block a user