FIX: allow quote-less details BBCode

In 53b3d2f0dc we introduced a stricter BBCode Tag parser. It prevents having "values" with spaces when they're not surrounded by a valid pair of quotes.

The `[details=` BBCode Tag is popular enough that it's worth adding a special case for it (especially since it doesn't support other parameters).

This also adds the Finnish pair of quotes.

Context - https://meta.discourse.org/t/details-accepts-only-one-word-as-summary/313019
This commit is contained in:
Régis Hanol 2024-06-24 12:33:24 +02:00
parent 55da8a7701
commit 3927b27f34
2 changed files with 30 additions and 31 deletions

View File

@ -34,15 +34,9 @@ function trailingSpaceOnly(src, start, max) {
return true; return true;
} }
// Easiest case is the closing tag which never has any attributes
const BBCODE_CLOSING_TAG_REGEXP = /^\[\/([-\w]+)\]/i;
// Old case where we supported attributes without quotation marks
const BBCODE_QUOTE_TAG_REGEXP = /^\[quote=([-\w,: ]+)\]/i;
// Most common quotation marks. // Most common quotation marks.
// More can be found at https://en.wikipedia.org/wiki/Quotation_mark // More can be found at https://en.wikipedia.org/wiki/Quotation_mark
const QUOTATION_MARKS = [`""`, `''`, `“”`, ``, `„“`, ``, `«»`, ``]; const QUOTATION_MARKS = [`""`, `''`, `“”`, `””`, ``, `„“`, ``, `«»`, ``];
const QUOTATION_MARKS_NO_MATCH = QUOTATION_MARKS.map( const QUOTATION_MARKS_NO_MATCH = QUOTATION_MARKS.map(
([a, b]) => `${a}[^${b}]+${b}` ([a, b]) => `${a}[^${b}]+${b}`
@ -52,6 +46,15 @@ const QUOTATION_MARKS_WITH_MATCH = QUOTATION_MARKS.map(
([a, b]) => `${a}([^${b}]+)${b}` ([a, b]) => `${a}([^${b}]+)${b}`
).join("|"); ).join("|");
// Easiest case is the closing tag which never has any attributes
const BBCODE_CLOSING_TAG_REGEXP = /^\[\/([-\w]+)\]/i;
// Old case where we supported attributes without quotation marks
const BBCODE_QUOTE_OR_DETAILS_TAG_REGEXP = new RegExp(
`^\\[(quote|details)=(\\s*[^${QUOTATION_MARKS.join("")}].+?)\\]`,
"i"
);
// This is used to match a **valid** opening tag // This is used to match a **valid** opening tag
// NOTE: it does not match the closing bracket "]" because it makes the regexp too slow // NOTE: it does not match the closing bracket "]" because it makes the regexp too slow
// due to the backtracking. So we check for the "]" manually. // due to the backtracking. So we check for the "]" manually.
@ -86,18 +89,18 @@ export function parseBBCodeTag(src, start, max, multiline) {
}; };
} }
// CASE 2 - [quote=...] tag (without quotes) // CASE 2 - [quote=...] or [details=...] tag (without quotes)
m = BBCODE_QUOTE_TAG_REGEXP.exec(text); m = BBCODE_QUOTE_OR_DETAILS_TAG_REGEXP.exec(text);
if (m && m[0] && m[1]) { if (m && m[0] && m[1] && m[2]) {
if (multiline && !trailingSpaceOnly(src, start + m[0].length, max)) { if (multiline && !trailingSpaceOnly(src, start + m[0].length, max)) {
return null; return null;
} }
return { return {
tag: "quote", tag: m[1],
length: m[0].length, length: m[0].length,
attrs: { _default: m[1] }, attrs: { _default: m[2] },
}; };
} }

View File

@ -1,23 +1,16 @@
import { setupTest } from "ember-qunit";
import { module, test } from "qunit"; import { module, test } from "qunit";
import { cook } from "discourse/lib/text"; import { cook } from "discourse/lib/text";
const opts = { module("lib:details-cooked-test", (hooks) => {
siteSettings: { setupTest(hooks);
enable_emoji: true,
emoji_set: "twitter",
highlighted_languages: "json|ruby|javascript",
default_code_lang: "auto",
},
censoredWords: "shucks|whiz|whizzer",
getURL: (url) => url,
};
module("lib:details-cooked-test", function () { test("details", async (assert) => {
test("details", async function (assert) {
const testCooked = async (input, expected, text) => { const testCooked = async (input, expected, text) => {
const cooked = (await cook(input, opts)).toString(); const cooked = (await cook(input)).toString();
assert.strictEqual(cooked, expected, text); assert.strictEqual(cooked, expected, text);
}; };
await testCooked( await testCooked(
`<details><summary>Info</summary>coucou</details>`, `<details><summary>Info</summary>coucou</details>`,
`<details><summary>Info</summary>coucou</details>`, `<details><summary>Info</summary>coucou</details>`,
@ -25,12 +18,15 @@ module("lib:details-cooked-test", function () {
); );
await testCooked( await testCooked(
"[details=testing]\ntest\n[/details]", `[details=test'ing all the things]\ntest\n[/details]`,
`<details> `<details>\n<summary>\ntest'ing all the things</summary>\n<p>test</p>\n</details>`,
<summary> "details with spaces and a single quote"
testing</summary> );
<p>test</p>
</details>` await testCooked(
`[details=”test'ing all the things”]\ntest\n[/details]`,
`<details>\n<summary>\ntest'ing all the things</summary>\n<p>test</p>\n</details>`,
"details surrounded by finnish double quotes"
); );
}); });
}); });