FEATURE: Better handling of quotation marks in site text search

It also matches 3 dots with the ellipsis symbol.
This commit is contained in:
Gerhard Schlager
2018-11-10 01:17:07 +01:00
parent c7377e2f2d
commit 7c4d4331bc
6 changed files with 69 additions and 7 deletions

View File

@ -6,7 +6,8 @@ export default Ember.Component.extend({
@on("didInsertElement") @on("didInsertElement")
highlightTerm() { highlightTerm() {
const term = this.get("term"); const term = this._searchTerm();
if (term) { if (term) {
this.$(".site-text-id, .site-text-value").highlight(term, { this.$(".site-text-id, .site-text-value").highlight(term, {
className: "text-highlight" className: "text-highlight"
@ -19,6 +20,18 @@ export default Ember.Component.extend({
this.send("edit"); this.send("edit");
}, },
_searchTerm() {
const regex = this.get("searchRegex");
const siteText = this.get("siteText");
if (regex && siteText) {
const matches = siteText.value.match(new RegExp(regex, "i"));
if (matches) return matches[0];
}
return this.get("term");
},
actions: { actions: {
edit() { edit() {
this.sendAction("editAction", this.get("siteText")); this.sendAction("editAction", this.get("siteText"));

View File

@ -18,6 +18,6 @@
{{/if}} {{/if}}
{{#each siteTexts as |siteText|}} {{#each siteTexts as |siteText|}}
{{site-text-summary siteText=siteText editAction="edit" term=q}} {{site-text-summary siteText=siteText editAction="edit" term=q searchRegex=siteTexts.extras.regex}}
{{/each}} {{/each}}
{{/conditional-loading-spinner}} {{/conditional-loading-spinner}}

View File

@ -28,6 +28,10 @@ class Admin::SiteTextsController < Admin::AdminController
results << record_for(k, v) results << record_for(k, v)
end end
unless translations.empty?
extras[:regex] = I18n::Backend::DiscourseI18n.create_search_regexp(query, as_string: true)
end
results.sort! do |x, y| results.sort! do |x, y|
if x[:value].casecmp(query) == 0 if x[:value].casecmp(query) == 0
-1 -1

View File

@ -70,7 +70,7 @@ module I18n
target = opts[:backend] || backend target = opts[:backend] || backend
results = opts[:overridden] ? {} : target.search(config.locale, query) results = opts[:overridden] ? {} : target.search(config.locale, query)
regexp = /#{Regexp.escape(query)}/i regexp = I18n::Backend::DiscourseI18n.create_search_regexp(query)
(overrides_by_locale(locale) || {}).each do |k, v| (overrides_by_locale(locale) || {}).each do |k, v|
results.delete(k) results.delete(k)
results[k] = v if (k =~ regexp || v =~ regexp) results[k] = v if (k =~ regexp || v =~ regexp)

View File

@ -39,11 +39,22 @@ module I18n
false false
end end
def self.create_search_regexp(query, as_string: false)
regexp = Regexp.escape(query)
regexp.gsub!(/['‘’‚‹›]/, "['‘’‚‹›]")
regexp.gsub!(/["“”„«»]/, '["“”„«»]')
regexp.gsub!(/(?:\\\.\\\.\\\.|…)/, '(?:\.\.\.|…)')
as_string ? regexp : /#{regexp}/i
end
def search(locale, query) def search(locale, query)
results = {} results = {}
regexp = self.class.create_search_regexp(query)
fallbacks(locale).each do |fallback| fallbacks(locale).each do |fallback|
find_results(/#{Regexp.escape(query)}/i, results, translations[fallback]) find_results(regexp, results, translations[fallback])
end end
results results

View File

@ -33,17 +33,51 @@ RSpec.describe Admin::SiteTextsController do
end end
end end
context "when logged in as amin" do context "when logged in as admin" do
before do before do
sign_in(admin) sign_in(admin)
end end
describe '#index' do describe '#index' do
it 'returns json' do it 'returns json' do
get "/admin/customize/site_texts.json", params: { q: 'title' } get "/admin/customize/site_texts.json", params: { q: 'title' }
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(::JSON.parse(response.body)).to be_present expect(JSON.parse(response.body)['site_texts']).to include(include("id" => "title"))
end end
it 'normalizes quotes during search' do
value = %q|“That’s a ‘magic’ sock.”|
put "/admin/customize/site_texts/title.json", params: { site_text: { value: value } }
[
%q|That's a 'magic' sock.|,
%q|That’s a ‘magic’ sock.|,
%q|“That's a 'magic' sock.”|,
%q|"That's a 'magic' sock."|,
%q|«That's a 'magic' sock.»|,
%q|„That’s a ‚magic‘ sock.“|
].each do |search_term|
get "/admin/customize/site_texts.json", params: { q: search_term }
expect(response.status).to eq(200)
expect(JSON.parse(response.body)['site_texts']).to include(include("id" => "title", "value" => value))
end
end
it 'normalizes ellipsis' do
value = "Loading Discussion…"
put "/admin/customize/site_texts/embed.loading.json", params: { site_text: { value: value } }
[
"Loading Discussion",
"Loading Discussion...",
"Loading Discussion…"
].each do |search_term|
get "/admin/customize/site_texts.json", params: { q: search_term }
expect(response.status).to eq(200)
expect(JSON.parse(response.body)['site_texts']).to include(include("id" => "embed.loading", "value" => value))
end
end
end end
describe '#show' do describe '#show' do