FIX: handle quote rendering for external Discourse instance (#16722)

Gracefully handle quotes from an external discourse instance by stripping quote-controls and including username in the title
This commit is contained in:
Isaac Janzen 2022-05-12 10:07:43 -05:00 committed by GitHub
parent 991b62b6f1
commit 20740f196c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 11 deletions

View File

@ -282,6 +282,11 @@ export default class PostCooked {
this._updateQuoteElements($aside, "chevron-down");
const $title = $(".title", $aside);
// If post/topic is not found then display username, skip controls
if (e.classList.contains("quote-post-not-found")) {
return (e.querySelector(".title").innerHTML = e.dataset.username);
}
// Unless it's a full quote, allow click to expand
if (!($aside.data("full") || $title.data("has-quote-controls"))) {
$title.on("click", (e2) => {

View File

@ -78,9 +78,8 @@ class CookedPostProcessor
q.css('blockquote').text
)
if comparer.modified?
q['class'] = ((q['class'] || '') + " quote-modified").strip
end
q['class'] = ((q['class'] || '') + " quote-post-not-found").strip if comparer.missing?
q['class'] = ((q['class'] || '') + " quote-modified").strip if comparer.modified?
end
end
end

View File

@ -15,12 +15,18 @@ class QuoteComparer
# This algorithm is far from perfect, but it follows the Discourse
# philosophy of "catch the obvious cases, leave moderation for the
# complicated ones"
def missing?
return true if @parent_post.blank?
end
def modified?
return true if @text.blank? || @parent_post.blank?
return true if @text.blank?
parent_text = Nokogiri::HTML5::fragment(@parent_post.cooked).text.delete(QuoteComparer.whitespace)
text = @text.delete(QuoteComparer.whitespace)
if @parent_post
parent_text = Nokogiri::HTML5::fragment(@parent_post.cooked).text.delete(QuoteComparer.whitespace)
text = @text.delete(QuoteComparer.whitespace)
!parent_text.include?(text)
!parent_text.include?(text)
end
end
end

View File

@ -1753,6 +1753,22 @@ describe CookedPostProcessor do
end
end
context "external discourse instance quote" do
let(:external_raw) do
<<~RAW.strip
[quote="random_guy_not_from_our_discourse, post:2004, topic:401"]
this quote is not from our discourse
[/quote]
and this is a reply
RAW
end
let(:cp) { Fabricate(:post, raw: external_raw) }
it "it should be marked as missing" do
cpp.post_process_quotes
expect(cpp.doc.css('aside.quote.quote-post-not-found')).to be_present
end
end
end
context "full quote on direct reply" do

View File

@ -4,6 +4,30 @@ require 'quote_comparer'
describe QuoteComparer do
describe "#missing?" do
fab!(:post) { Fabricate(:post, raw: "This has **text** we _are_ matching") }
it "returns true for missing topic and post" do
expect(QuoteComparer.new(nil, nil, "test")).to be_missing
end
it "returns true for missing topic" do
expect(QuoteComparer.new(nil, post.post_number, "test")).to be_missing
end
it "returns true for missing post" do
expect(QuoteComparer.new(post.topic_id, nil, "test")).to be_missing
end
it "returns false for only missing text" do
expect(QuoteComparer.new(post.topic_id, post.post_number, nil)).to_not be_missing
end
it "returns false for no missing topic and post" do
expect(QuoteComparer.new(post.topic_id, post.post_number, "test")).to_not be_missing
end
end
describe "#modified?" do
fab!(:post) { Fabricate(:post, raw: "This has **text** we _are_ matching") }
@ -11,10 +35,6 @@ describe QuoteComparer do
QuoteComparer.new(post.topic_id, post.post_number, text)
end
it "returns true for no post" do
expect(QuoteComparer.new(nil, nil, "test")).to be_modified
end
it "returns true for nil text" do
expect(qc(nil)).to be_modified
end