mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 09:36:19 -05:00
Support for Fancy topic titles
This commit is contained in:
parent
c0371ff427
commit
836c3a7379
14 changed files with 2139 additions and 12 deletions
1
Gemfile
1
Gemfile
|
@ -8,6 +8,7 @@ gem 'message_bus', path: 'vendor/gems/message_bus'
|
|||
gem 'rails_multisite', path: 'vendor/gems/rails_multisite'
|
||||
gem 'simple_handlebars_rails', path: 'vendor/gems/simple_handlebars_rails'
|
||||
|
||||
gem 'redcarpet', require: false
|
||||
gem 'activerecord-postgres-hstore'
|
||||
gem 'acts_as_paranoid'
|
||||
gem 'active_attr' # until we get ActiveModel::Model with Rails 4
|
||||
|
|
|
@ -332,6 +332,7 @@ GEM
|
|||
ffi (>= 0.5.0)
|
||||
rdoc (3.12.1)
|
||||
json (~> 1.4)
|
||||
redcarpet (2.2.2)
|
||||
redis (3.0.2)
|
||||
redis-actionpack (3.2.3)
|
||||
actionpack (~> 3.2.3)
|
||||
|
@ -494,6 +495,7 @@ DEPENDENCIES
|
|||
rake
|
||||
rb-fsevent
|
||||
rb-inotify (~> 0.8.8)
|
||||
redcarpet
|
||||
redis
|
||||
redis-rails
|
||||
rest-client
|
||||
|
|
|
@ -20,7 +20,9 @@ Handlebars.registerHelper 'shorten', (property, options) ->
|
|||
|
||||
Handlebars.registerHelper 'topicLink', (property, options) ->
|
||||
topic = Ember.Handlebars.get(this, property, options)
|
||||
"<a href='#{topic.get('lastReadUrl')}' class='title excerptable'>#{Handlebars.Utils.escapeExpression(topic.get('title'))}</a>"
|
||||
|
||||
title = topic.get('fancy_title') || topic.get('title')
|
||||
"<a href='#{topic.get('lastReadUrl')}' class='title excerptable'>#{title}</a>"
|
||||
|
||||
Handlebars.registerHelper 'categoryLink', (property, options) ->
|
||||
category = Ember.Handlebars.get(this, property, options)
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
<button class='btn btn-small' {{action cancelEdit target="view"}}><i class='icon-remove'></i></button>
|
||||
{{else}}
|
||||
<h1>
|
||||
{{#if view.topic.title}}
|
||||
{{#if view.topic.fancy_title}}
|
||||
{{view Discourse.TopicStatusView topicBinding="view.topic"}}
|
||||
<a href='{{unbound view.topic.url}}'>{{unbound view.topic.title}}</a>
|
||||
<a href='{{unbound view.topic.url}}'>{{{unbound view.topic.fancy_title}}}</a>
|
||||
{{else}}
|
||||
{{#if view.topic.missing}}
|
||||
{{i18n topic.not_found.title}}
|
||||
|
|
|
@ -280,7 +280,9 @@ window.Discourse.TopicView = Ember.View.extend Discourse.Scrolling,
|
|||
finishedEdit: ->
|
||||
if @get('editingTopic')
|
||||
topic = @get('topic')
|
||||
topic.set('title', $('#edit-title').val())
|
||||
new_val = $('#edit-title').val()
|
||||
topic.set('title', new_val)
|
||||
topic.set('fancy_title', new_val)
|
||||
topic.save()
|
||||
@set('editingTopic', false)
|
||||
|
||||
|
|
|
@ -138,6 +138,8 @@ class SiteSetting < ActiveRecord::Base
|
|||
|
||||
setting(:new_user_period_days, 2)
|
||||
|
||||
setting(:title_fancy_entities, true)
|
||||
|
||||
client_setting(:educate_until_posts, 2)
|
||||
|
||||
def self.call_discourse_hub?
|
||||
|
|
|
@ -5,6 +5,7 @@ require_dependency 'rate_limiter'
|
|||
require_dependency 'text_sentinel'
|
||||
|
||||
class Topic < ActiveRecord::Base
|
||||
include ActionView::Helpers
|
||||
include RateLimiter::OnCreateRecord
|
||||
|
||||
MAX_SORT_ORDER = 2147483647
|
||||
|
@ -67,7 +68,10 @@ class Topic < ActiveRecord::Base
|
|||
end
|
||||
|
||||
before_validation do
|
||||
self.title.strip! if self.title.present?
|
||||
if self.title.present?
|
||||
self.title = sanitize(self.title)
|
||||
self.title.strip!
|
||||
end
|
||||
end
|
||||
|
||||
before_create do
|
||||
|
@ -115,6 +119,14 @@ class Topic < ActiveRecord::Base
|
|||
errors.add(:title, I18n.t(:has_already_been_used)) if finder.exists?
|
||||
end
|
||||
|
||||
def fancy_title
|
||||
return title unless SiteSetting.title_fancy_entities?
|
||||
|
||||
# We don't always have to require this, if fancy is disabled
|
||||
require 'redcarpet'
|
||||
|
||||
Redcarpet::Render::SmartyPants.render(title)
|
||||
end
|
||||
|
||||
def title_quality
|
||||
# We don't care about quality on private messages
|
||||
|
|
|
@ -3,8 +3,20 @@ require_dependency 'age_words'
|
|||
class BasicTopicSerializer < ApplicationSerializer
|
||||
include ActionView::Helpers
|
||||
|
||||
attributes :id, :title, :reply_count, :posts_count, :highest_post_number, :image_url, :created_at,
|
||||
:last_posted_at, :age, :unseen, :last_read_post_number, :unread, :new_posts
|
||||
attributes :id,
|
||||
:title,
|
||||
:fancy_title,
|
||||
:reply_count,
|
||||
:posts_count,
|
||||
:highest_post_number,
|
||||
:image_url,
|
||||
:created_at,
|
||||
:last_posted_at,
|
||||
:age,
|
||||
:unseen,
|
||||
:last_read_post_number,
|
||||
:unread,
|
||||
:new_posts
|
||||
|
||||
def age
|
||||
AgeWords.age_words(Time.now - (object.created_at || Time.now))
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
class TopicLinkSerializer < ApplicationSerializer
|
||||
|
||||
attributes :url, :title, :internal, :reflection, :clicks, :user_id
|
||||
attributes :url,
|
||||
:title,
|
||||
:fancy_title,
|
||||
:internal,
|
||||
:reflection,
|
||||
:clicks,
|
||||
:user_id
|
||||
|
||||
def url
|
||||
object['url']
|
||||
|
@ -10,6 +16,10 @@ class TopicLinkSerializer < ApplicationSerializer
|
|||
object['title']
|
||||
end
|
||||
|
||||
def fancy_title
|
||||
object['fancy_title']
|
||||
end
|
||||
|
||||
def internal
|
||||
object['internal'] == 't'
|
||||
end
|
||||
|
@ -25,6 +35,7 @@ class TopicLinkSerializer < ApplicationSerializer
|
|||
def user_id
|
||||
object['user_id'].to_i
|
||||
end
|
||||
|
||||
def include_user_id?
|
||||
object['user_id'].present?
|
||||
end
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
class TopicListItemSerializer < BasicTopicSerializer
|
||||
|
||||
attributes :views, :like_count, :visible, :pinned, :closed, :archived, :last_post_age, :starred, :has_best_of, :archetype, :slug
|
||||
attributes :views,
|
||||
:like_count,
|
||||
:visible,
|
||||
:pinned,
|
||||
:closed,
|
||||
:archived,
|
||||
:last_post_age,
|
||||
:starred,
|
||||
:has_best_of,
|
||||
:archetype,
|
||||
:slug
|
||||
|
||||
has_one :category
|
||||
has_many :posters, serializer: TopicPosterSerializer, embed: :objects
|
||||
|
|
|
@ -4,6 +4,7 @@ class TopicViewSerializer < ApplicationSerializer
|
|||
def self.topic_attributes
|
||||
[:id,
|
||||
:title,
|
||||
:fancy_title,
|
||||
:posts_count,
|
||||
:created_at,
|
||||
:views,
|
||||
|
|
|
@ -342,12 +342,11 @@ en:
|
|||
|
||||
email_time_window_mins: "How many minutes we wait before sending a user mail, to give them a chance to see it first."
|
||||
flush_timings_secs: "How frequently we flush timing data to the server, in seconds."
|
||||
|
||||
max_word_length: "The maximum word length in a topic title"
|
||||
title_min_entropy: "The minimum entropy for a topic title"
|
||||
body_min_entropy: "The minimum entropy for post body"
|
||||
|
||||
new_user_period_days: "How long a user is highlighted as being new, in days."
|
||||
title_fancy_entities: "Convert fancy HTML entities in topic titles"
|
||||
|
||||
notification_types:
|
||||
mentioned: "%{display_username} mentioned you in %{link}"
|
||||
|
|
2040
db/structure.sql
2040
db/structure.sql
File diff suppressed because it is too large
Load diff
|
@ -109,6 +109,41 @@ describe Topic do
|
|||
|
||||
end
|
||||
|
||||
context 'html in title' do
|
||||
let(:topic) { Fabricate(:topic, title: "<script>alert('title')</script> is my topic title" ) }
|
||||
|
||||
it "should escape the HTML" do
|
||||
topic.title.should == "is my topic title"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'fancy title' do
|
||||
let(:topic) { Fabricate(:topic, title: "\"this topic\" -- has ``fancy stuff''" ) }
|
||||
|
||||
context 'title_fancy_entities disabled' do
|
||||
before do
|
||||
SiteSetting.stubs(:title_fancy_entities).returns(false)
|
||||
end
|
||||
|
||||
it "doesn't change the title to add entities" do
|
||||
topic.fancy_title.should == topic.title
|
||||
end
|
||||
end
|
||||
|
||||
context 'title_fancy_entities enabled' do
|
||||
before do
|
||||
SiteSetting.stubs(:title_fancy_entities).returns(true)
|
||||
end
|
||||
|
||||
it "converts the title to have fancy entities" do
|
||||
topic.fancy_title.should == "“this topic” – has “fancy stuff”"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
context 'message bus' do
|
||||
it 'calls the message bus observer after create' do
|
||||
|
|
Loading…
Reference in a new issue