mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 08:43:25 +08:00
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:
parent
55da8a7701
commit
3927b27f34
|
@ -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] },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user