mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-23 23:58:31 -05:00
store the slug as the title is, only sanitize the slug
and prettify code
This commit is contained in:
parent
b772ff6e13
commit
a48dd1cc28
12 changed files with 45 additions and 45 deletions
|
@ -224,7 +224,7 @@ Discourse.Category.reopenClass({
|
||||||
|
|
||||||
findSingleBySlug: function(slug) {
|
findSingleBySlug: function(slug) {
|
||||||
return Discourse.Category.list().find(function(c) {
|
return Discourse.Category.list().find(function(c) {
|
||||||
return Discourse.Category.slugFor(c) === slug || Discourse.Category.slugFor(c) === encodeURI(slug);
|
return Discourse.Category.slugFor(c) === slug;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -254,9 +254,7 @@ Discourse.Category.reopenClass({
|
||||||
if (slug === 'none') { return parentCategory; }
|
if (slug === 'none') { return parentCategory; }
|
||||||
|
|
||||||
category = categories.find(function(item) {
|
category = categories.find(function(item) {
|
||||||
return item && item.get('parentCategory') === parentCategory &&
|
return item && item.get('parentCategory') === parentCategory && Discourse.Category.slugFor(item) === (parentSlug + "/" + slug);
|
||||||
(Discourse.Category.slugFor(item) === (parentSlug + "/" + slug) ||
|
|
||||||
Discourse.Category.slugFor(item) === encodeURIComponent(parentSlug) + "/" + encodeURIComponent(slug));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -427,8 +427,7 @@ class TopicsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def slugs_do_not_match
|
def slugs_do_not_match
|
||||||
params[:slug] && (@topic_view.topic.slug != params[:slug] &&
|
params[:slug] && @topic_view.topic.slug != params[:slug]
|
||||||
@topic_view.topic.slug != Rack::Utils.escape_path(params[:slug])) # maybe percent encoded
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def redirect_to_correct_topic(topic, post_number=nil)
|
def redirect_to_correct_topic(topic, post_number=nil)
|
||||||
|
|
|
@ -207,7 +207,7 @@ SQL
|
||||||
|
|
||||||
if slug.present?
|
if slug.present?
|
||||||
# santized custom slug
|
# santized custom slug
|
||||||
self.slug = Slug.for(Rack::Utils.unescape(slug), '')
|
self.slug = Slug.for(slug, '')
|
||||||
errors.add(:slug, 'is already in use') if duplicate_slug?
|
errors.add(:slug, 'is already in use') if duplicate_slug?
|
||||||
else
|
else
|
||||||
# auto slug
|
# auto slug
|
||||||
|
@ -342,13 +342,11 @@ SQL
|
||||||
|
|
||||||
def self.query_parent_category(parent_slug)
|
def self.query_parent_category(parent_slug)
|
||||||
self.where(slug: parent_slug, parent_category_id: nil).pluck(:id).first ||
|
self.where(slug: parent_slug, parent_category_id: nil).pluck(:id).first ||
|
||||||
self.where(slug: Rack::Utils.escape_path(parent_slug), parent_category_id: nil).pluck(:id).first ||
|
|
||||||
self.where(id: parent_slug.to_i).pluck(:id).first
|
self.where(id: parent_slug.to_i).pluck(:id).first
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.query_category(slug_or_id, parent_category_id)
|
def self.query_category(slug_or_id, parent_category_id)
|
||||||
self.where(slug: slug_or_id, parent_category_id: parent_category_id).includes(:featured_users).first ||
|
self.where(slug: slug_or_id, parent_category_id: parent_category_id).includes(:featured_users).first ||
|
||||||
self.where(slug: Rack::Utils.escape_path(slug_or_id), parent_category_id: parent_category_id).includes(:featured_users).first ||
|
|
||||||
self.where(id: slug_or_id.to_i, parent_category_id: parent_category_id).includes(:featured_users).first
|
self.where(id: slug_or_id.to_i, parent_category_id: parent_category_id).includes(:featured_users).first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -665,7 +665,7 @@ class Topic < ActiveRecord::Base
|
||||||
def slug
|
def slug
|
||||||
unless slug = read_attribute(:slug)
|
unless slug = read_attribute(:slug)
|
||||||
return '' unless title.present?
|
return '' unless title.present?
|
||||||
slug = Slug.for(title, 'topic')
|
slug = Slug.for(title)
|
||||||
if new_record?
|
if new_record?
|
||||||
write_attribute(:slug, slug)
|
write_attribute(:slug, slug)
|
||||||
else
|
else
|
||||||
|
@ -677,7 +677,7 @@ class Topic < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def title=(t)
|
def title=(t)
|
||||||
slug = Slug.for(t.to_s, 'topic')
|
slug = Slug.for(t.to_s)
|
||||||
write_attribute(:slug, slug)
|
write_attribute(:slug, slug)
|
||||||
write_attribute(:title,t)
|
write_attribute(:title,t)
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,7 @@ class NotificationSerializer < ApplicationSerializer
|
||||||
:is_warning
|
:is_warning
|
||||||
|
|
||||||
def slug
|
def slug
|
||||||
Slug.for(object.topic.title, 'topic') if object.topic.present?
|
Slug.for(object.topic.title) if object.topic.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_warning
|
def is_warning
|
||||||
|
|
|
@ -58,7 +58,7 @@ class UserActionSerializer < ApplicationSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def slug
|
def slug
|
||||||
Slug.for(object.title, 'topic')
|
Slug.for(object.title)
|
||||||
end
|
end
|
||||||
|
|
||||||
def include_slug?
|
def include_slug?
|
||||||
|
|
|
@ -48,7 +48,7 @@ module Onebox
|
||||||
return linked unless Guardian.new.can_see?(post)
|
return linked unless Guardian.new.can_see?(post)
|
||||||
|
|
||||||
topic = post.topic
|
topic = post.topic
|
||||||
slug = Slug.for(topic.title, 'topic')
|
slug = Slug.for(topic.title)
|
||||||
|
|
||||||
excerpt = post.excerpt(SiteSetting.post_onebox_maxlength)
|
excerpt = post.excerpt(SiteSetting.post_onebox_maxlength)
|
||||||
excerpt.gsub!("\n"," ")
|
excerpt.gsub!("\n"," ")
|
||||||
|
|
18
lib/slug.rb
18
lib/slug.rb
|
@ -7,7 +7,6 @@ module Slug
|
||||||
when :ascii then self.ascii_generator(string)
|
when :ascii then self.ascii_generator(string)
|
||||||
when :encoded then self.encoded_generator(string)
|
when :encoded then self.encoded_generator(string)
|
||||||
when :none then self.none_generator(string)
|
when :none then self.none_generator(string)
|
||||||
else raise Discourse::SiteSettingMissing
|
|
||||||
end
|
end
|
||||||
# Reject slugs that only contain numbers, because they would be indistinguishable from id's.
|
# Reject slugs that only contain numbers, because they would be indistinguishable from id's.
|
||||||
slug = (slug =~ /[^\d]/ ? slug : '')
|
slug = (slug =~ /[^\d]/ ? slug : '')
|
||||||
|
@ -17,15 +16,20 @@ module Slug
|
||||||
private
|
private
|
||||||
|
|
||||||
def self.ascii_generator(string)
|
def self.ascii_generator(string)
|
||||||
slug = string.gsub("'", "").parameterize
|
string.gsub("'", "")
|
||||||
slug.gsub("_", "-")
|
.parameterize
|
||||||
|
.gsub("_", "-")
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.encoded_generator(string)
|
def self.encoded_generator(string)
|
||||||
# strip and sanitized RFC 3986 reserved character and blank
|
# This generator will sanitize almost all special characters,
|
||||||
string = string.strip.gsub(/\s+/, '-').gsub(/[:\/\?#\[\]@!\$\s&'\(\)\*\+,;=]+/, '')
|
# including reserved characters from RFC3986.
|
||||||
string = Rack::Utils.escape_path(string)
|
# See also URI::REGEXP::PATTERN.
|
||||||
string =~ /^-+$/ ? '' : string
|
string.strip
|
||||||
|
.gsub(/\s+/, '-')
|
||||||
|
.gsub(/[:\/\?#\[\]@!\$&'\(\)\*\+,;=_\.~%\\`^\s|\{\}"<>]+/, '') # :/?#[]@!$&'()*+,;=_.~%\`^|{}"<>
|
||||||
|
.gsub(/\A-+|-+\z/, '') # remove possible trailing and preceding dashes
|
||||||
|
.squeeze('-') # squeeze continuous dashes to prettify slug
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.none_generator(string)
|
def self.none_generator(string)
|
||||||
|
|
|
@ -25,7 +25,7 @@ task 'build_test_topic' => :environment do
|
||||||
first_post = PostCreator.new(evil_trout, raw: "This is the original post.", title: "pushState/replaceState test topic").create
|
first_post = PostCreator.new(evil_trout, raw: "This is the original post.", title: "pushState/replaceState test topic").create
|
||||||
topic = first_post.topic
|
topic = first_post.topic
|
||||||
|
|
||||||
topic_url = "#{Discourse.base_url}/t/#{Slug.for(topic.title, 'topic')}/#{topic.id}"
|
topic_url = "#{Discourse.base_url}/t/#{Slug.for(topic.title)}/#{topic.id}"
|
||||||
|
|
||||||
99.times do |i|
|
99.times do |i|
|
||||||
post_number = (i + 2)
|
post_number = (i + 2)
|
||||||
|
|
|
@ -10,15 +10,15 @@ describe Slug do
|
||||||
before { SiteSetting.slug_generation_method = 'ascii' }
|
before { SiteSetting.slug_generation_method = 'ascii' }
|
||||||
|
|
||||||
it 'generates the slug' do
|
it 'generates the slug' do
|
||||||
expect(Slug.for("hello world", 'topic')).to eq('hello-world')
|
expect(Slug.for("hello world")).to eq('hello-world')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'generates default slug when nothing' do
|
it 'generates default slug when nothing' do
|
||||||
expect(Slug.for('', 'topic')).to eq('topic')
|
expect(Slug.for('')).to eq('topic')
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't generate slugs that are just numbers" do
|
it "doesn't generate slugs that are just numbers" do
|
||||||
expect(Slug.for('123', 'topic')).to eq('topic')
|
expect(Slug.for('123')).to eq('topic')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -27,15 +27,15 @@ describe Slug do
|
||||||
after { SiteSetting.slug_generation_method = 'ascii' }
|
after { SiteSetting.slug_generation_method = 'ascii' }
|
||||||
|
|
||||||
it 'generates the slug' do
|
it 'generates the slug' do
|
||||||
expect(Slug.for("熱帶風暴畫眉", 'topic')).to eq('%E7%86%B1%E5%B8%B6%E9%A2%A8%E6%9A%B4%E7%95%AB%E7%9C%89')
|
expect(Slug.for("熱帶風暴畫眉")).to eq('熱帶風暴畫眉')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'generates default slug when nothing' do
|
it 'generates default slug when nothing' do
|
||||||
expect(Slug.for('', 'topic')).to eq('topic')
|
expect(Slug.for('')).to eq('topic')
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't generate slugs that are just numbers" do
|
it "doesn't generate slugs that are just numbers" do
|
||||||
expect(Slug.for('123', 'topic')).to eq('topic')
|
expect(Slug.for('123')).to eq('topic')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -45,9 +45,9 @@ describe Slug do
|
||||||
|
|
||||||
it 'generates the slug' do
|
it 'generates the slug' do
|
||||||
expect(Slug.for("hello world", 'category')).to eq('category')
|
expect(Slug.for("hello world", 'category')).to eq('category')
|
||||||
expect(Slug.for("hello world", 'topic')).to eq('topic')
|
expect(Slug.for("hello world")).to eq('topic')
|
||||||
expect(Slug.for('', 'topic')).to eq('topic')
|
expect(Slug.for('')).to eq('topic')
|
||||||
expect(Slug.for('123', 'topic')).to eq('topic')
|
expect(Slug.for('123')).to eq('topic')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -111,14 +111,15 @@ describe Slug do
|
||||||
after { SiteSetting.slug_generation_method = 'ascii' }
|
after { SiteSetting.slug_generation_method = 'ascii' }
|
||||||
|
|
||||||
it 'generates precentage encoded string' do
|
it 'generates precentage encoded string' do
|
||||||
expect(Slug.encoded_generator("Jeff hate's !~-_|,=#this")).to eq("Jeff-hates-%7E-_%7Cthis")
|
expect(Slug.encoded_generator("Jeff hate's !~-_|,=#this")).to eq("Jeff-hates-this")
|
||||||
expect(Slug.encoded_generator("뉴스피드")).to eq("%EB%89%B4%EC%8A%A4%ED%94%BC%EB%93%9C")
|
expect(Slug.encoded_generator("뉴스피드")).to eq("뉴스피드")
|
||||||
expect(Slug.encoded_generator("آموزش اضافه کردن لینک اختیاری به هدر")).to eq("%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%A7%D8%B6%D8%A7%D9%81%D9%87-%DA%A9%D8%B1%D8%AF%D9%86-%D9%84%DB%8C%D9%86%DA%A9-%D8%A7%D8%AE%D8%AA%DB%8C%D8%A7%D8%B1%DB%8C-%D8%A8%D9%87-%D9%87%D8%AF%D8%B1")
|
expect(Slug.encoded_generator("آموزش اضافه کردن لینک اختیاری به هدر")).to eq("آموزش-اضافه-کردن-لینک-اختیاری-به-هدر")
|
||||||
expect(Slug.encoded_generator("熱帶風暴畫眉")).to eq("%E7%86%B1%E5%B8%B6%E9%A2%A8%E6%9A%B4%E7%95%AB%E7%9C%89")
|
expect(Slug.encoded_generator("熱帶風暴畫眉")).to eq("熱帶風暴畫眉")
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'reject RFC 3986 reserved character and blank' do
|
it 'reject RFC 3986 reserved character and blank' do
|
||||||
expect(Slug.encoded_generator(":/?#[]@!$ &'()*+,;=")).to eq("")
|
expect(Slug.encoded_generator(":/?#[]@!$ &'()*+,;=% -_`~.")).to eq("")
|
||||||
|
expect(Slug.encoded_generator(" - English and Chinese title with special characters / 中文标题 !@:?\\:'`#^& $%&*()` -- ")).to eq("English-and-Chinese-title-with-special-characters-中文标题")
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'generates null when nothing' do
|
it 'generates null when nothing' do
|
||||||
|
|
|
@ -209,8 +209,8 @@ describe Category do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates a slug" do
|
it "creates a slug" do
|
||||||
expect(@category.slug).to eq("%E6%B5%8B%E8%AF%95")
|
expect(@category.slug).to eq("测试")
|
||||||
expect(@category.slug_for_url).to eq("%E6%B5%8B%E8%AF%95")
|
expect(@category.slug_for_url).to eq("测试")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,15 +19,15 @@ describe Topic do
|
||||||
after { SiteSetting.slug_generation_method = 'ascii' }
|
after { SiteSetting.slug_generation_method = 'ascii' }
|
||||||
|
|
||||||
it "returns a Slug for a title" do
|
it "returns a Slug for a title" do
|
||||||
Slug.expects(:for).with(title, 'topic').returns(slug)
|
Slug.expects(:for).with(title).returns(slug)
|
||||||
expect(Fabricate.build(:topic, title: title).slug).to eq(slug)
|
expect(Fabricate.build(:topic, title: title).slug).to eq(slug)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for cjk characters' do
|
context 'for cjk characters' do
|
||||||
let(:title) { "熱帶風暴畫眉" }
|
let(:title) { "熱帶風暴畫眉" }
|
||||||
let(:slug) { "%E7%86%B1%E5%B8%B6%E9%A2%A8%E6%9A%B4%E7%95%AB%E7%9C%89" }
|
let(:slug) { "熱帶風暴畫眉" }
|
||||||
it "returns encoded Slug for a title" do
|
it "returns encoded Slug for a title" do
|
||||||
Slug.expects(:for).with(title, 'topic').returns(slug)
|
Slug.expects(:for).with(title).returns(slug)
|
||||||
expect(Fabricate.build(:topic, title: title).slug).to eq(slug)
|
expect(Fabricate.build(:topic, title: title).slug).to eq(slug)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -36,7 +36,7 @@ describe Topic do
|
||||||
let(:title) { "123456789" }
|
let(:title) { "123456789" }
|
||||||
let(:slug) { "topic" }
|
let(:slug) { "topic" }
|
||||||
it 'generates default slug' do
|
it 'generates default slug' do
|
||||||
Slug.expects(:for).with(title, 'topic').returns("topic")
|
Slug.expects(:for).with(title).returns("topic")
|
||||||
expect(Fabricate.build(:topic, title: title).slug).to eq("topic")
|
expect(Fabricate.build(:topic, title: title).slug).to eq("topic")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -49,7 +49,7 @@ describe Topic do
|
||||||
let(:slug) { "topic" }
|
let(:slug) { "topic" }
|
||||||
|
|
||||||
it "returns a Slug for a title" do
|
it "returns a Slug for a title" do
|
||||||
Slug.expects(:for).with(title, 'topic').returns('topic')
|
Slug.expects(:for).with(title).returns('topic')
|
||||||
expect(Fabricate.build(:topic, title: title).slug).to eq(slug)
|
expect(Fabricate.build(:topic, title: title).slug).to eq(slug)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -57,7 +57,7 @@ describe Topic do
|
||||||
context '#ascii_generator' do
|
context '#ascii_generator' do
|
||||||
before { SiteSetting.slug_generation_method = 'ascii' }
|
before { SiteSetting.slug_generation_method = 'ascii' }
|
||||||
it "returns a Slug for a title" do
|
it "returns a Slug for a title" do
|
||||||
Slug.expects(:for).with(title, 'topic').returns(slug)
|
Slug.expects(:for).with(title).returns(slug)
|
||||||
expect(Fabricate.build(:topic, title: title).slug).to eq(slug)
|
expect(Fabricate.build(:topic, title: title).slug).to eq(slug)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ describe Topic do
|
||||||
let(:title) { "熱帶風暴畫眉" }
|
let(:title) { "熱帶風暴畫眉" }
|
||||||
let(:slug) { 'topic' }
|
let(:slug) { 'topic' }
|
||||||
it "returns 'topic' when the slug is empty (say, non-latin characters)" do
|
it "returns 'topic' when the slug is empty (say, non-latin characters)" do
|
||||||
Slug.expects(:for).with(title, 'topic').returns("topic")
|
Slug.expects(:for).with(title).returns("topic")
|
||||||
expect(Fabricate.build(:topic, title: title).slug).to eq("topic")
|
expect(Fabricate.build(:topic, title: title).slug).to eq("topic")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue