thredded 0.6.0 → 0.6.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 +4 -4
- data/CHANGELOG.mkdn +15 -0
- data/README.mkdn +3 -2
- data/app/assets/stylesheets/thredded/layout/_moderation.scss +2 -1
- data/app/assets/stylesheets/thredded/layout/_user-navigation.scss +2 -1
- data/app/commands/thredded/at_notification_extractor.rb +14 -7
- data/app/commands/thredded/autofollow_mentioned_users.rb +4 -4
- data/app/controllers/thredded/moderation_controller.rb +13 -0
- data/app/models/concerns/thredded/post_common.rb +2 -5
- data/app/models/thredded/user_detail.rb +1 -1
- data/app/models/thredded/user_topic_follow.rb +1 -1
- data/app/views/thredded/moderation/_nav.html.erb +3 -0
- data/app/views/thredded/moderation/_post.html.erb +5 -0
- data/app/views/thredded/moderation/_post_moderation_record.html.erb +3 -3
- data/app/views/thredded/moderation/_user_post.html.erb +5 -0
- data/app/views/thredded/moderation/activity.html.erb +18 -0
- data/config/locales/en.yml +4 -2
- data/config/locales/pt-BR.yml +4 -2
- data/config/routes.rb +1 -0
- data/heroku.gemfile.lock +2 -4
- data/lib/html/pipeline/at_mention_filter.rb +62 -9
- data/lib/thredded/content_formatter.rb +1 -2
- data/lib/thredded/version.rb +1 -1
- data/thredded.gemspec +0 -1
- metadata +3 -17
- data/lib/thredded/at_users.rb +0 -22
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 868d81f0b7ff77d6ae58e572377f1001be7131b7
         | 
| 4 | 
            +
              data.tar.gz: f23376c4be14345f85932348d1b9745322ac642a
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 11bf79cf05bbf641a8c78540d6d07c2522dbb6ba660de178bdbbe1d98a18958b0edbc4360eaf74b71bb6db71f3f60717eb945326791ae03903f0cf64d1fc780e
         | 
| 7 | 
            +
              data.tar.gz: 12b1603c89e6e4660d67fb7a6ed90993c42d2edd408a261d8b15f107e201d1a47dbff2b157ad94628e74713cf9d4607f1ae2a10fcbdbf86b36b49a4dac6a5f95
         | 
    
        data/CHANGELOG.mkdn
    CHANGED
    
    | @@ -1,3 +1,18 @@ | |
| 1 | 
            +
            # v0.6.1
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            This is a minor bugfix release.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ## Added
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * Adds an Activity tab to moderation, with a list of all the forum topics and posts, most recent first.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ## Fixed
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            * Moderation history rendering of deleted content.
         | 
| 12 | 
            +
            * Various bugs in @-mentions and highlighting.
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            See the full list of changes here: https://github.com/thredded/thredded/compare/v0.6.0...v0.6.1.
         | 
| 15 | 
            +
             | 
| 1 16 | 
             
            # 0.6.0 - 2016-06-12
         | 
| 2 17 |  | 
| 3 18 | 
             
            **NB:** If updating to this version from 0.5.x, you will need to copy and run [this migration](https://github.com/thredded/thredded/blob/66f64068b9501ff4e8686c95894b6795aae6082f/db/upgrade_migrations/20160611094616_upgrade_v0_5_to_v0_6.rb).
         | 
    
        data/README.mkdn
    CHANGED
    
    | @@ -44,7 +44,7 @@ application and not an engine like Thredded. | |
| 44 44 | 
             
            Add the gem to your Gemfile:
         | 
| 45 45 |  | 
| 46 46 | 
             
            ```ruby
         | 
| 47 | 
            -
            gem 'thredded', '~> 0.6. | 
| 47 | 
            +
            gem 'thredded', '~> 0.6.1'
         | 
| 48 48 | 
             
            ```
         | 
| 49 49 |  | 
| 50 50 | 
             
            Add the Thredded [initializer] to your parent app by running the install generator.
         | 
| @@ -154,11 +154,12 @@ Thredded does not provide a user's profile page, but it provides a helper for re | |
| 154 154 | 
             
            in your app's user profile page.
         | 
| 155 155 |  | 
| 156 156 | 
             
            To use it:
         | 
| 157 | 
            +
             | 
| 157 158 | 
             
            1. Include `Thredded::ApplicationHelper` in the app's helpers module.
         | 
| 158 159 | 
             
            2. Render the partial like this:
         | 
| 159 160 |  | 
| 160 161 | 
             
            ```erb
         | 
| 161 | 
            -
            <%= render 'thredded/users/ | 
| 162 | 
            +
            <%= render 'thredded/users/posts',
         | 
| 162 163 | 
             
                       posts: Thredded.posts_page_view(
         | 
| 163 164 | 
             
                           scope: user.thredded_posts.order_newest_first.limit(5),
         | 
| 164 165 | 
             
                           current_user: current_user) %>
         | 
| @@ -11,7 +11,8 @@ | |
| 11 11 | 
             
            .thredded--pending-moderation &--moderation-navigation--pending,
         | 
| 12 12 | 
             
            .thredded--moderation-history &--moderation-navigation--history,
         | 
| 13 13 | 
             
            .thredded--moderation-users &--moderation-navigation--users,
         | 
| 14 | 
            -
            .thredded--moderation-user &--moderation-navigation--users | 
| 14 | 
            +
            .thredded--moderation-user &--moderation-navigation--users,
         | 
| 15 | 
            +
            .thredded--moderation-activity &--moderation-navigation--activity {
         | 
| 15 16 | 
             
              @extend %thredded--nav-tabs--item-current;
         | 
| 16 17 | 
             
            }
         | 
| 17 18 |  | 
| @@ -13,7 +13,8 @@ | |
| 13 13 | 
             
            .thredded--pending-moderation &--user-navigation--moderation,
         | 
| 14 14 | 
             
            .thredded--moderation-history &--user-navigation--moderation,
         | 
| 15 15 | 
             
            .thredded--moderation-users &--user-navigation--moderation,
         | 
| 16 | 
            -
            .thredded--moderation-user &--user-navigation--moderation | 
| 16 | 
            +
            .thredded--moderation-user &--user-navigation--moderation,
         | 
| 17 | 
            +
            .thredded--moderation-activity &--user-navigation--moderation {
         | 
| 17 18 | 
             
              @extend %thredded--nav-tabs--item-current;
         | 
| 18 19 | 
             
            }
         | 
| 19 20 |  | 
| @@ -1,16 +1,23 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require_dependency 'html/pipeline/at_mention_filter'
         | 
| 2 3 | 
             
            module Thredded
         | 
| 3 4 | 
             
              class AtNotificationExtractor
         | 
| 4 | 
            -
                 | 
| 5 | 
            -
             | 
| 6 | 
            -
                MATCH_NAME_RE = /(?:^|[\s>])@([\w]+|"[\w ]+")(?=\W|$)/
         | 
| 7 | 
            -
             | 
| 8 | 
            -
                def initialize(content)
         | 
| 9 | 
            -
                  @content = content
         | 
| 5 | 
            +
                def initialize(post)
         | 
| 6 | 
            +
                  @post = post
         | 
| 10 7 | 
             
                end
         | 
| 11 8 |  | 
| 9 | 
            +
                # @return [Array<Thredded.user_class>]
         | 
| 12 10 | 
             
                def run
         | 
| 13 | 
            -
                   | 
| 11 | 
            +
                  view_context = Thredded::ApplicationController.new.view_context
         | 
| 12 | 
            +
                  # Do not highlight @-mentions at first, because:
         | 
| 13 | 
            +
                  # * When parsing, @-mentions within <a> tags will not be considered.
         | 
| 14 | 
            +
                  # * We can't always generate the user URL here because request.host is not available.
         | 
| 15 | 
            +
                  html = @post.filtered_content(view_context, users_provider: nil)
         | 
| 16 | 
            +
                  HTML::Pipeline::AtMentionFilter.new(
         | 
| 17 | 
            +
                    html,
         | 
| 18 | 
            +
                    view_context: view_context,
         | 
| 19 | 
            +
                    users_provider: -> (user_names) { @post.readers_from_user_names(user_names).to_a }
         | 
| 20 | 
            +
                  ).mentioned_users
         | 
| 14 21 | 
             
                end
         | 
| 15 22 | 
             
              end
         | 
| 16 23 | 
             
            end
         | 
| @@ -1,4 +1,5 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require_dependency 'thredded/at_notification_extractor'
         | 
| 2 3 | 
             
            module Thredded
         | 
| 3 4 | 
             
              class AutofollowMentionedUsers
         | 
| 4 5 | 
             
                def initialize(post)
         | 
| @@ -12,10 +13,9 @@ module Thredded | |
| 12 13 | 
             
                end
         | 
| 13 14 |  | 
| 14 15 | 
             
                def autofollowers
         | 
| 15 | 
            -
                   | 
| 16 | 
            -
                  autofollowers | 
| 17 | 
            -
                  autofollowers | 
| 18 | 
            -
                  exclude_those_opting_out_of_at_notifications(autofollowers)
         | 
| 16 | 
            +
                  autofollowers = Thredded::AtNotificationExtractor.new(post).run
         | 
| 17 | 
            +
                  autofollowers.delete(post.user)
         | 
| 18 | 
            +
                  exclude_those_opting_out_of_at_notifications autofollowers
         | 
| 19 19 | 
             
                end
         | 
| 20 20 |  | 
| 21 21 | 
             
                private
         | 
| @@ -26,6 +26,19 @@ module Thredded | |
| 26 26 | 
             
                    .page(current_page)
         | 
| 27 27 | 
             
                end
         | 
| 28 28 |  | 
| 29 | 
            +
                def activity
         | 
| 30 | 
            +
                  @posts = PostsPageView.new(
         | 
| 31 | 
            +
                    thredded_current_user,
         | 
| 32 | 
            +
                    moderatable_posts
         | 
| 33 | 
            +
                      .order_newest_first
         | 
| 34 | 
            +
                      .preload(:user, :postable)
         | 
| 35 | 
            +
                      .page(current_page)
         | 
| 36 | 
            +
                  )
         | 
| 37 | 
            +
                  if flash[:last_moderated_record_id]
         | 
| 38 | 
            +
                    @last_moderated_record = accessible_post_moderation_records.find(flash[:last_moderated_record_id].to_i)
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 29 42 | 
             
                def moderate_post
         | 
| 30 43 | 
             
                  return head(:bad_request) unless Thredded::Post.moderation_states.include?(params[:moderation_state])
         | 
| 31 44 | 
             
                  flash[:last_moderated_record_id] = ModeratePost.run!(
         | 
| @@ -25,11 +25,8 @@ module Thredded | |
| 25 25 |  | 
| 26 26 | 
             
                # @param view_context [Object] the context of the rendering view.
         | 
| 27 27 | 
             
                # @return [String] formatted and sanitized html-safe post content.
         | 
| 28 | 
            -
                def filtered_content(view_context)
         | 
| 29 | 
            -
                  Thredded::ContentFormatter.new(
         | 
| 30 | 
            -
                    view_context,
         | 
| 31 | 
            -
                    users_provider: -> (names) { readers_from_user_names(names) }
         | 
| 32 | 
            -
                  ).format_content(content)
         | 
| 28 | 
            +
                def filtered_content(view_context, users_provider: -> (names) { readers_from_user_names(names) })
         | 
| 29 | 
            +
                  Thredded::ContentFormatter.new(view_context, users_provider: users_provider).format_content(content)
         | 
| 33 30 | 
             
                end
         | 
| 34 31 |  | 
| 35 32 | 
             
                private
         | 
| @@ -4,7 +4,7 @@ module Thredded | |
| 4 4 | 
             
                include ModerationState
         | 
| 5 5 |  | 
| 6 6 | 
             
                belongs_to :user, class_name: Thredded.user_class, inverse_of: :thredded_user_detail
         | 
| 7 | 
            -
                validates :user_id, presence: true
         | 
| 7 | 
            +
                validates :user_id, presence: true, uniqueness: true
         | 
| 8 8 |  | 
| 9 9 | 
             
                has_many :topics, class_name: 'Thredded::Topic', foreign_key: :user_id, primary_key: :user_id
         | 
| 10 10 | 
             
                has_many :private_topics, class_name: 'Thredded::PrivateTopic', foreign_key: :user_id, primary_key: :user_id
         | 
| @@ -3,7 +3,7 @@ module Thredded | |
| 3 3 | 
             
              class UserTopicFollow < ActiveRecord::Base
         | 
| 4 4 | 
             
                enum reason: [:manual, :posted, :mentioned]
         | 
| 5 5 |  | 
| 6 | 
            -
                belongs_to :user, inverse_of: :thredded_topic_follows
         | 
| 6 | 
            +
                belongs_to :user, inverse_of: :thredded_topic_follows, class_name: Thredded.user_class
         | 
| 7 7 | 
             
                belongs_to :topic, inverse_of: :user_follows
         | 
| 8 8 |  | 
| 9 9 | 
             
                validates :user_id, presence: true
         | 
| @@ -7,6 +7,9 @@ | |
| 7 7 | 
             
                  <li class="thredded--moderation-navigation--item thredded--moderation-navigation--history">
         | 
| 8 8 | 
             
                    <%= link_to t('thredded.nav.moderation_history'), moderation_history_path %>
         | 
| 9 9 | 
             
                  </li>
         | 
| 10 | 
            +
                  <li class="thredded--moderation-navigation--item thredded--moderation-navigation--activity">
         | 
| 11 | 
            +
                    <%= link_to t('thredded.nav.moderation_activity'), moderation_activity_path %>
         | 
| 12 | 
            +
                  </li>
         | 
| 10 13 | 
             
                  <li class="thredded--moderation-navigation--item thredded--moderation-navigation--users">
         | 
| 11 14 | 
             
                    <%= link_to t('thredded.nav.moderation_users'), users_moderation_path %>
         | 
| 12 15 | 
             
                  </li>
         | 
| @@ -10,5 +10,10 @@ | |
| 10 10 | 
             
              %>
         | 
| 11 11 | 
             
              <%= render 'thredded/posts_common/content', post: post %>
         | 
| 12 12 | 
             
              <%= render 'thredded/posts_common/actions', post: post %>
         | 
| 13 | 
            +
              <% if post.blocked? %>
         | 
| 14 | 
            +
                <p class="thredded--alert thredded--alert-danger">
         | 
| 15 | 
            +
                  <%= render 'thredded/shared/content_moderation_blocked_state', moderation_record: post.last_moderation_record %>
         | 
| 16 | 
            +
                </p>
         | 
| 17 | 
            +
              <% end %>
         | 
| 13 18 | 
             
              <%= render 'post_moderation_actions', post: post %>
         | 
| 14 19 | 
             
            <% end %>
         | 
| @@ -23,12 +23,12 @@ | |
| 23 23 | 
             
                    <%= t('thredded.moderation.posts_content_changed_since_moderation_html', post_url: post_permalink_path(post)) %>
         | 
| 24 24 | 
             
                  </p>
         | 
| 25 25 | 
             
                <% end %>
         | 
| 26 | 
            -
                <%= t | 
| 26 | 
            +
                <%= content_tag :em, t('thredded.moderation.post_deleted_notice') unless post %>
         | 
| 27 27 | 
             
              </header>
         | 
| 28 28 | 
             
              <article class="thredded--post">
         | 
| 29 29 | 
             
                <% post_user_link = capture do %>
         | 
| 30 | 
            -
                  <% if  | 
| 31 | 
            -
                    <%= link_to  | 
| 30 | 
            +
                  <% if record.post_user %>
         | 
| 31 | 
            +
                    <%= link_to record.post_user, user_moderation_path(record.post_user.id) %>
         | 
| 32 32 | 
             
                  <% else %>
         | 
| 33 33 | 
             
                    <%= safe_join [record.post_user_name, content_tag(:em, t('thredded.null_user_name'))].compact, ', ' %>
         | 
| 34 34 | 
             
                  <% end %>
         | 
| @@ -3,5 +3,10 @@ | |
| 3 3 | 
             
              <%= render 'thredded/posts_common/header_with_topic', post: post %>
         | 
| 4 4 | 
             
              <%= render 'thredded/posts_common/content', post: post %>
         | 
| 5 5 | 
             
              <%= render 'thredded/posts_common/actions', post: post %>
         | 
| 6 | 
            +
              <% if post.blocked? %>
         | 
| 7 | 
            +
                <p class="thredded--alert thredded--alert-danger">
         | 
| 8 | 
            +
                  <%= render 'thredded/shared/content_moderation_blocked_state', moderation_record: post.last_moderation_record %>
         | 
| 9 | 
            +
                </p>
         | 
| 10 | 
            +
              <% end %>
         | 
| 6 11 | 
             
              <%= render 'post_moderation_actions', post: post %>
         | 
| 7 12 | 
             
            <% end %>
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            <% content_for :thredded_page_title, t('thredded.nav.moderation') %>
         | 
| 2 | 
            +
            <% content_for :thredded_page_id, 'thredded--moderation-activity' %>
         | 
| 3 | 
            +
            <%= render 'nav' %>
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            <%= thredded_page do %>
         | 
| 6 | 
            +
              <h1><%= t 'thredded.recent_activity' %></h1>
         | 
| 7 | 
            +
              <%= content_tag :section, class: 'thredded--main-section' do %>
         | 
| 8 | 
            +
                <% if @last_moderated_record %>
         | 
| 9 | 
            +
                  <div class="thredded--moderated-notice">
         | 
| 10 | 
            +
                    <%= render 'post_moderation_record', post_moderation_record: @last_moderated_record %>
         | 
| 11 | 
            +
                  </div>
         | 
| 12 | 
            +
                <% end %>
         | 
| 13 | 
            +
                <% if @posts.present? %>
         | 
| 14 | 
            +
                  <%= render partial: 'post', collection: @posts %>
         | 
| 15 | 
            +
                  <%= paginate @posts %>
         | 
| 16 | 
            +
                <% end %>
         | 
| 17 | 
            +
              <% end %>
         | 
| 18 | 
            +
            <% end %>
         | 
    
        data/config/locales/en.yml
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            en:
         | 
| 3 3 | 
             
              thredded:
         | 
| 4 | 
            +
                recent_activity: Recent activity
         | 
| 4 5 | 
             
                errors:
         | 
| 5 6 | 
             
                  login_required: Please sign in first.
         | 
| 6 7 | 
             
                  not_authorized: You are not authorized to access this page.
         | 
| @@ -9,7 +10,7 @@ en: | |
| 9 10 | 
             
                form:
         | 
| 10 11 | 
             
                  update: Update
         | 
| 11 12 | 
             
                content_moderation_states:
         | 
| 12 | 
            -
                  content_blocked_notice: Blocked | 
| 13 | 
            +
                  content_blocked_notice: Blocked
         | 
| 13 14 | 
             
                  content_blocked_notice_with_record_html: Blocked by %{moderator} %{time_ago}
         | 
| 14 15 | 
             
                messageboard:
         | 
| 15 16 | 
             
                  create: Create a New Messageboard
         | 
| @@ -51,6 +52,7 @@ en: | |
| 51 52 | 
             
                  moderation_history: History
         | 
| 52 53 | 
             
                  moderation_pending: Pending
         | 
| 53 54 | 
             
                  moderation_users: Users
         | 
| 55 | 
            +
                  moderation_activity: Activity
         | 
| 54 56 | 
             
                  private_topics: Private Messages
         | 
| 55 57 | 
             
                  settings: Notification Settings
         | 
| 56 58 | 
             
                null_user_name: Deleted user
         | 
| @@ -140,7 +142,7 @@ en: | |
| 140 142 | 
             
                users:
         | 
| 141 143 | 
             
                  last_active_html: "Last active %{time_ago}"
         | 
| 142 144 | 
             
                  posted_in_topic_html: "Posted in %{topic_link}"
         | 
| 143 | 
            -
                  recent_activity:  | 
| 145 | 
            +
                  recent_activity: :thredded.recent_activity
         | 
| 144 146 | 
             
                  started_topic_html: "Started %{topic_link}"
         | 
| 145 147 | 
             
                  user_posted_in_topic_html: "%{user_link} posted in %{topic_link}"
         | 
| 146 148 | 
             
                  user_since_html: "User since %{time_ago}"
         | 
    
        data/config/locales/pt-BR.yml
    CHANGED
    
    | @@ -2,7 +2,7 @@ | |
| 2 2 | 
             
            pt-BR:
         | 
| 3 3 | 
             
              thredded:
         | 
| 4 4 | 
             
                content_moderation_states:
         | 
| 5 | 
            -
                  content_blocked_notice: Bloqueado | 
| 5 | 
            +
                  content_blocked_notice: Bloqueado
         | 
| 6 6 | 
             
                  content_blocked_notice_with_record_html: Bloqueados por %{moderator} %{time_ago}
         | 
| 7 7 | 
             
                errors:
         | 
| 8 8 | 
             
                  login_required: Por favor, autentique-se primeiro.
         | 
| @@ -48,6 +48,7 @@ pt-BR: | |
| 48 48 | 
             
                  edit_private_topic: :thredded.nav.edit_topic
         | 
| 49 49 | 
             
                  edit_topic: Editar
         | 
| 50 50 | 
             
                  moderation: Moderação
         | 
| 51 | 
            +
                  moderation_activity: Atividade
         | 
| 51 52 | 
             
                  moderation_history: História
         | 
| 52 53 | 
             
                  moderation_pending: Pendente
         | 
| 53 54 | 
             
                  moderation_users: Usuários
         | 
| @@ -108,6 +109,7 @@ pt-BR: | |
| 108 109 | 
             
                    create_btn: Inicie sua primeira conversa privada
         | 
| 109 110 | 
             
                    title: Você não possui mensagens privadas.
         | 
| 110 111 | 
             
                  updated_notice: Título atualizado
         | 
| 112 | 
            +
                recent_activity: Atividade recente
         | 
| 111 113 | 
             
                search:
         | 
| 112 114 | 
             
                  form:
         | 
| 113 115 | 
             
                    btn_submit: :thredded.search.form.label
         | 
| @@ -144,7 +146,7 @@ pt-BR: | |
| 144 146 | 
             
                  posts_count:
         | 
| 145 147 | 
             
                    one: Postado uma vez
         | 
| 146 148 | 
             
                    other: vezes %{count} Publicado
         | 
| 147 | 
            -
                  recent_activity:  | 
| 149 | 
            +
                  recent_activity: :thredded.recent_activity
         | 
| 148 150 | 
             
                  started_topic_html: Começou %{topic_link}
         | 
| 149 151 | 
             
                  started_topics_count:
         | 
| 150 152 | 
             
                    one: Começou um tópico
         | 
    
        data/config/routes.rb
    CHANGED
    
    | @@ -35,6 +35,7 @@ Thredded::Engine.routes.draw do | |
| 35 35 | 
             
                    get '/history(/page-:page)', action: :history, as: :moderation_history
         | 
| 36 36 | 
             
                    get '/users(/page-:page)', action: :users, as: :users_moderation
         | 
| 37 37 | 
             
                    get '/users/:id(/page-:page)', action: :user, as: :user_moderation
         | 
| 38 | 
            +
                    get '/activity(/page-:page)', action: :activity, as: :moderation_activity
         | 
| 38 39 | 
             
                  end
         | 
| 39 40 | 
             
                  post '', action: :moderate_post, as: :moderate_post
         | 
| 40 41 | 
             
                  post '/user/:id', action: :moderate_user, as: :moderate_user
         | 
    
        data/heroku.gemfile.lock
    CHANGED
    
    | @@ -9,7 +9,7 @@ GIT | |
| 9 9 | 
             
            PATH
         | 
| 10 10 | 
             
              remote: .
         | 
| 11 11 | 
             
              specs:
         | 
| 12 | 
            -
                thredded (0.6. | 
| 12 | 
            +
                thredded (0.6.1)
         | 
| 13 13 | 
             
                  active_record_union (>= 1.1.1)
         | 
| 14 14 | 
             
                  autoprefixer-rails
         | 
| 15 15 | 
             
                  autosize-rails
         | 
| @@ -30,7 +30,6 @@ PATH | |
| 30 30 | 
             
                  rails (>= 4.2.0)
         | 
| 31 31 | 
             
                  rails-timeago
         | 
| 32 32 | 
             
                  rb-gravatar
         | 
| 33 | 
            -
                  rinku
         | 
| 34 33 | 
             
                  sanitize
         | 
| 35 34 | 
             
                  sass (>= 3.4.21)
         | 
| 36 35 | 
             
                  select2-rails (~> 3.5)
         | 
| @@ -212,7 +211,6 @@ GEM | |
| 212 211 | 
             
                rb-gravatar (1.0.5)
         | 
| 213 212 | 
             
                ref (2.0.0)
         | 
| 214 213 | 
             
                request_store (1.3.1)
         | 
| 215 | 
            -
                rinku (2.0.0)
         | 
| 216 214 | 
             
                rollbar (2.11.5)
         | 
| 217 215 | 
             
                  multi_json
         | 
| 218 216 | 
             
                sanitize (4.0.1)
         | 
| @@ -228,7 +226,7 @@ GEM | |
| 228 226 | 
             
                  tilt (>= 1.1, < 3)
         | 
| 229 227 | 
             
                select2-rails (3.5.10)
         | 
| 230 228 | 
             
                  thor (~> 0.14)
         | 
| 231 | 
            -
                sprockets (3.6. | 
| 229 | 
            +
                sprockets (3.6.1)
         | 
| 232 230 | 
             
                  concurrent-ruby (~> 1.0)
         | 
| 233 231 | 
             
                  rack (> 1, < 3)
         | 
| 234 232 | 
             
                sprockets-es6 (0.9.0)
         | 
| @@ -1,23 +1,76 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            -
            require 'thredded/at_users'
         | 
| 3 | 
            -
             | 
| 4 2 | 
             
            module HTML
         | 
| 5 3 | 
             
              class Pipeline
         | 
| 6 4 | 
             
                class AtMentionFilter < Filter
         | 
| 5 | 
            +
                  DEFAULT_IGNORED_ANCESTOR_TAGS = %w(pre code tt a style).freeze
         | 
| 6 | 
            +
             | 
| 7 7 | 
             
                  # @param context [Hash]
         | 
| 8 8 | 
             
                  # @options context :users_provider [#call(usernames)] given usernames, returns a list of users.
         | 
| 9 | 
            -
                  def initialize( | 
| 10 | 
            -
                    super  | 
| 11 | 
            -
                    @text = text.to_s.delete("\r")
         | 
| 9 | 
            +
                  def initialize(doc, context = nil, result = nil)
         | 
| 10 | 
            +
                    super doc, context, result
         | 
| 12 11 | 
             
                    @users_provider = context[:users_provider]
         | 
| 13 12 | 
             
                    @view_context = context[:view_context]
         | 
| 14 13 | 
             
                  end
         | 
| 15 14 |  | 
| 16 15 | 
             
                  def call
         | 
| 17 | 
            -
                    return  | 
| 18 | 
            -
                     | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 16 | 
            +
                    return doc unless @users_provider
         | 
| 17 | 
            +
                    process_text_nodes! do |node|
         | 
| 18 | 
            +
                      content = node.to_html
         | 
| 19 | 
            +
                      next unless content.include?('@')
         | 
| 20 | 
            +
                      highlight! content
         | 
| 21 | 
            +
                      node.replace content
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                    doc
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  # @return [Array<Thredded.user_class>] users that were @-mentioned
         | 
| 27 | 
            +
                  def mentioned_users
         | 
| 28 | 
            +
                    return [] unless @users_provider
         | 
| 29 | 
            +
                    names = []
         | 
| 30 | 
            +
                    process_text_nodes! { |node| names.concat mentioned_names(node.to_html) }
         | 
| 31 | 
            +
                    names.uniq!
         | 
| 32 | 
            +
                    @users_provider.call(names)
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  private
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  MATCH_NAME_RE = /(?:^|[\s>])@([\w]+|"[\w ]+")(?=\W|$)/
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  def mentioned_names(text_node_html)
         | 
| 40 | 
            +
                    text_node_html.scan(MATCH_NAME_RE).map(&:first).map { |m| m.start_with?('"') ? m[1..-2] : m }
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  def highlight!(text_node_html)
         | 
| 44 | 
            +
                    names = mentioned_names(text_node_html)
         | 
| 45 | 
            +
                    return unless names.present?
         | 
| 46 | 
            +
                    @users_provider.call(names).each do |user|
         | 
| 47 | 
            +
                      name = user.to_s
         | 
| 48 | 
            +
                      maybe_quoted_name = name.include?(' ') ? %("#{name}") : name
         | 
| 49 | 
            +
                      url = Thredded.user_path(@view_context, user)
         | 
| 50 | 
            +
                      text_node_html.gsub!(
         | 
| 51 | 
            +
                        /(^|[\s>])(@#{Regexp.escape maybe_quoted_name})([^a-z\d]|$)/i,
         | 
| 52 | 
            +
                        %(\\1<a href="#{ERB::Util.html_escape url}">@#{ERB::Util.html_escape maybe_quoted_name}</a>\\3)
         | 
| 53 | 
            +
                      )
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  # Yields text nodes that should be processed.
         | 
| 58 | 
            +
                  def process_text_nodes!
         | 
| 59 | 
            +
                    doc.search('.//text()').each do |node|
         | 
| 60 | 
            +
                      next if has_ancestor?(node, ignored_ancestor_tags)
         | 
| 61 | 
            +
                      yield node
         | 
| 62 | 
            +
                    end
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  # Return ancestor tags to stop the at-mention highlighting.
         | 
| 66 | 
            +
                  #
         | 
| 67 | 
            +
                  # @return [Array<String>] Ancestor tags.
         | 
| 68 | 
            +
                  def ignored_ancestor_tags
         | 
| 69 | 
            +
                    if @context[:ignored_ancestor_tags]
         | 
| 70 | 
            +
                      DEFAULT_IGNORED_ANCESTOR_TAGS | @context[:ignored_ancestor_tags]
         | 
| 71 | 
            +
                    else
         | 
| 72 | 
            +
                      DEFAULT_IGNORED_ANCESTOR_TAGS
         | 
| 73 | 
            +
                    end
         | 
| 21 74 | 
             
                  end
         | 
| 22 75 | 
             
                end
         | 
| 23 76 | 
             
              end
         | 
| @@ -43,13 +43,12 @@ module Thredded | |
| 43 43 | 
             
                mattr_accessor :pipeline_filters
         | 
| 44 44 |  | 
| 45 45 | 
             
                self.pipeline_filters = [
         | 
| 46 | 
            -
                  HTML::Pipeline::AtMentionFilter,
         | 
| 47 46 | 
             
                  HTML::Pipeline::VimeoFilter,
         | 
| 48 47 | 
             
                  HTML::Pipeline::YoutubeFilter,
         | 
| 49 48 | 
             
                  HTML::Pipeline::BbcodeFilter,
         | 
| 50 49 | 
             
                  HTML::Pipeline::MarkdownFilter,
         | 
| 50 | 
            +
                  HTML::Pipeline::AtMentionFilter,
         | 
| 51 51 | 
             
                  HTML::Pipeline::EmojiFilter,
         | 
| 52 | 
            -
                  HTML::Pipeline::AutolinkFilter,
         | 
| 53 52 | 
             
                  HTML::Pipeline::SanitizationFilter,
         | 
| 54 53 | 
             
                ].freeze
         | 
| 55 54 |  | 
    
        data/lib/thredded/version.rb
    CHANGED
    
    
    
        data/thredded.gemspec
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: thredded
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.6. | 
| 4 | 
            +
              version: 0.6.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Joel Oliveira
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2016-06- | 
| 12 | 
            +
            date: 2016-06-18 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: bbcoder
         | 
| @@ -235,20 +235,6 @@ dependencies: | |
| 235 235 | 
             
                - - ">="
         | 
| 236 236 | 
             
                  - !ruby/object:Gem::Version
         | 
| 237 237 | 
             
                    version: '0'
         | 
| 238 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 239 | 
            -
              name: rinku
         | 
| 240 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 241 | 
            -
                requirements:
         | 
| 242 | 
            -
                - - ">="
         | 
| 243 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 244 | 
            -
                    version: '0'
         | 
| 245 | 
            -
              type: :runtime
         | 
| 246 | 
            -
              prerelease: false
         | 
| 247 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 248 | 
            -
                requirements:
         | 
| 249 | 
            -
                - - ">="
         | 
| 250 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 251 | 
            -
                    version: '0'
         | 
| 252 238 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 253 239 | 
             
              name: sanitize
         | 
| 254 240 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -788,6 +774,7 @@ files: | |
| 788 774 | 
             
            - app/views/thredded/moderation/_user_moderation_state.html.erb
         | 
| 789 775 | 
             
            - app/views/thredded/moderation/_user_post.html.erb
         | 
| 790 776 | 
             
            - app/views/thredded/moderation/_users_search_form.html.erb
         | 
| 777 | 
            +
            - app/views/thredded/moderation/activity.html.erb
         | 
| 791 778 | 
             
            - app/views/thredded/moderation/history.html.erb
         | 
| 792 779 | 
             
            - app/views/thredded/moderation/pending.html.erb
         | 
| 793 780 | 
             
            - app/views/thredded/moderation/user.html.erb
         | 
| @@ -871,7 +858,6 @@ files: | |
| 871 858 | 
             
            - lib/html/pipeline/bbcode_filter.rb
         | 
| 872 859 | 
             
            - lib/tasks/thredded_tasks.rake
         | 
| 873 860 | 
             
            - lib/thredded.rb
         | 
| 874 | 
            -
            - lib/thredded/at_users.rb
         | 
| 875 861 | 
             
            - lib/thredded/content_formatter.rb
         | 
| 876 862 | 
             
            - lib/thredded/engine.rb
         | 
| 877 863 | 
             
            - lib/thredded/errors.rb
         | 
    
        data/lib/thredded/at_users.rb
    DELETED
    
    | @@ -1,22 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
            module Thredded
         | 
| 3 | 
            -
              class AtUsers
         | 
| 4 | 
            -
                # @param users_provider [#call(usernames)] given usernames, returns a list of users.
         | 
| 5 | 
            -
                def self.render(content, users_provider, view_context)
         | 
| 6 | 
            -
                  at_names = AtNotificationExtractor.new(content).run
         | 
| 7 | 
            -
             | 
| 8 | 
            -
                  if at_names.any?
         | 
| 9 | 
            -
                    members = users_provider.call(at_names)
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                    members.each do |member|
         | 
| 12 | 
            -
                      member_path = Thredded.user_path(view_context, member)
         | 
| 13 | 
            -
                      name = member.to_s
         | 
| 14 | 
            -
                      content.gsub!(/(^|[\s>])(@#{name.include?(' ') ? %("#{name}") : name})\b/i,
         | 
| 15 | 
            -
                                    %(\1<a href="#{ERB::Util.html_escape member_path}">@#{ERB::Util.html_escape name}</a>))
         | 
| 16 | 
            -
                    end
         | 
| 17 | 
            -
                  end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                  content
         | 
| 20 | 
            -
                end
         | 
| 21 | 
            -
              end
         | 
| 22 | 
            -
            end
         |