From f0f03acb2ce56e4e153685b1498517736dd0a695 Mon Sep 17 00:00:00 2001 From: Kyle Zhao Date: Fri, 13 Sep 2019 07:04:14 -0700 Subject: [PATCH] FIX: Do not escape `fancy_title` again. (#8095) `fancy_title` is already escaped by Rails. Escaping it again would print the HTML entity as-is, e.g. `"` instead of `"`. This fixes the issue by introducing a new `escapedContent` attribute on the `QuickAccessItem` widget. --- .../widgets/quick-access-item.js.es6 | 27 +++++++++++++--- .../widgets/quick-access-messages.js.es6 | 2 +- .../widgets/quick-access-item-test.js.es6 | 31 +++++++++++++++++++ 3 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 test/javascripts/widgets/quick-access-item-test.js.es6 diff --git a/app/assets/javascripts/discourse/widgets/quick-access-item.js.es6 b/app/assets/javascripts/discourse/widgets/quick-access-item.js.es6 index a869484cc70..a37200e5956 100644 --- a/app/assets/javascripts/discourse/widgets/quick-access-item.js.es6 +++ b/app/assets/javascripts/discourse/widgets/quick-access-item.js.es6 @@ -3,7 +3,22 @@ import RawHtml from "discourse/widgets/raw-html"; import { createWidget } from "discourse/widgets/widget"; import { emojiUnescape } from "discourse/lib/text"; import { iconNode } from "discourse-common/lib/icon-library"; +import { escapeExpression } from "discourse/lib/utilities"; +/** + * This helper widget tries to enforce a consistent look and behavior for any + * item under any quick access panels. + * + * It accepts the following attributes: + * action + * actionParam + * content + * escapedContent + * href + * icon + * read + * username + */ createWidget("quick-access-item", { tagName: "li", @@ -18,13 +33,11 @@ createWidget("quick-access-item", { return result; }, - html({ icon, href, content }) { + html({ icon, href }) { return h("a", { attributes: { href } }, [ iconNode(icon), new RawHtml({ - html: `
${this._usernameHtml()}${emojiUnescape( - Handlebars.Utils.escapeExpression(content) - )}
` + html: `
${this._usernameHtml()}${this._contentHtml()}
` }) ]); }, @@ -37,6 +50,12 @@ createWidget("quick-access-item", { } }, + _contentHtml() { + const content = + this.attrs.escapedContent || escapeExpression(this.attrs.content); + return emojiUnescape(content); + }, + _usernameHtml() { return this.attrs.username ? `${this.attrs.username} ` : ""; } diff --git a/app/assets/javascripts/discourse/widgets/quick-access-messages.js.es6 b/app/assets/javascripts/discourse/widgets/quick-access-messages.js.es6 index 9988e649d7a..e8431bc3d27 100644 --- a/app/assets/javascripts/discourse/widgets/quick-access-messages.js.es6 +++ b/app/assets/javascripts/discourse/widgets/quick-access-messages.js.es6 @@ -12,7 +12,7 @@ function toItem(message) { ); return { - content: message.fancy_title, + escapedContent: message.fancy_title, href: postUrl(message.slug, message.id, nextUnreadPostNumber), icon: ICON, read: message.last_read_post_number >= message.highest_post_number, diff --git a/test/javascripts/widgets/quick-access-item-test.js.es6 b/test/javascripts/widgets/quick-access-item-test.js.es6 new file mode 100644 index 00000000000..19da5eff69f --- /dev/null +++ b/test/javascripts/widgets/quick-access-item-test.js.es6 @@ -0,0 +1,31 @@ +import { moduleForWidget, widgetTest } from "helpers/widget-test"; + +moduleForWidget("quick-access-item"); + +const CONTENT_DIV_SELECTOR = "li > a > div"; + +widgetTest("content attribute is escaped", { + template: '{{mount-widget widget="quick-access-item" args=args}}', + + beforeEach() { + this.set("args", { content: "bold" }); + }, + + test(assert) { + const contentDiv = find(CONTENT_DIV_SELECTOR)[0]; + assert.equal(contentDiv.innerText, "bold"); + } +}); + +widgetTest("escapedContent attribute is not escaped", { + template: '{{mount-widget widget="quick-access-item" args=args}}', + + beforeEach() { + this.set("args", { escapedContent: ""quote"" }); + }, + + test(assert) { + const contentDiv = find(CONTENT_DIV_SELECTOR)[0]; + assert.equal(contentDiv.innerText, '"quote"'); + } +});