mirror of
https://github.com/discourse/discourse.git
synced 2025-03-22 16:17:54 +08:00
FIX: Generate unique HTML heading names (#12705)
Headings with the exact same name generated exactly the same heading names, which was invalid. This replaces the old code for generating names for non-English headings which were using URI encode and resulted in unreadable headings.
This commit is contained in:
parent
42f6c9b6b9
commit
96a16123d8
@ -670,7 +670,7 @@ eviltrout</p>
|
|||||||
|
|
||||||
assert.cooked(
|
assert.cooked(
|
||||||
"# #category-hashtag",
|
"# #category-hashtag",
|
||||||
'<h1><a name="category-hashtag" class="anchor" href="#category-hashtag"></a><span class="hashtag">#category-hashtag</span></h1>',
|
'<h1><a name="category-hashtag-1" class="anchor" href="#category-hashtag-1"></a><span class="hashtag">#category-hashtag</span></h1>',
|
||||||
"it works within ATX-style headers"
|
"it works within ATX-style headers"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -696,7 +696,7 @@ eviltrout</p>
|
|||||||
test("Heading", function (assert) {
|
test("Heading", function (assert) {
|
||||||
assert.cooked(
|
assert.cooked(
|
||||||
"**Bold**\n----------",
|
"**Bold**\n----------",
|
||||||
'<h2><a name="bold" class="anchor" href="#bold"></a><strong>Bold</strong></h2>',
|
'<h2><a name="bold-1" class="anchor" href="#bold-1"></a><strong>Bold</strong></h2>',
|
||||||
"It will bold the heading"
|
"It will bold the heading"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -939,7 +939,7 @@ eviltrout</p>
|
|||||||
|
|
||||||
assert.cooked(
|
assert.cooked(
|
||||||
"## a\nb\n```\nc\n```",
|
"## a\nb\n```\nc\n```",
|
||||||
'<h2><a name="a" class="anchor" href="#a"></a>a</h2>\n<p>b</p>\n<pre><code class="lang-auto">c\n</code></pre>',
|
'<h2><a name="a-1" class="anchor" href="#a-1"></a>a</h2>\n<p>b</p>\n<pre><code class="lang-auto">c\n</code></pre>',
|
||||||
"it handles headings with code blocks after them."
|
"it handles headings with code blocks after them."
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
const SPECIAL_CHARACTERS_REGEX = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~’]/g;
|
|
||||||
|
|
||||||
export function setup(helper) {
|
export function setup(helper) {
|
||||||
if (helper.getOptions().previewing) {
|
if (helper.getOptions().previewing) {
|
||||||
return;
|
return;
|
||||||
@ -7,7 +5,11 @@ export function setup(helper) {
|
|||||||
|
|
||||||
helper.registerPlugin((md) => {
|
helper.registerPlugin((md) => {
|
||||||
md.core.ruler.push("anchor", (state) => {
|
md.core.ruler.push("anchor", (state) => {
|
||||||
for (let idx = 0, lvl = 0; idx < state.tokens.length; idx++) {
|
for (
|
||||||
|
let idx = 0, lvl = 0, headingId = 0;
|
||||||
|
idx < state.tokens.length;
|
||||||
|
idx++
|
||||||
|
) {
|
||||||
if (
|
if (
|
||||||
state.tokens[idx].type === "blockquote_open" ||
|
state.tokens[idx].type === "blockquote_open" ||
|
||||||
(state.tokens[idx].type === "bbcode_open" &&
|
(state.tokens[idx].type === "bbcode_open" &&
|
||||||
@ -37,15 +39,7 @@ export function setup(helper) {
|
|||||||
.replace(/^-+/, "")
|
.replace(/^-+/, "")
|
||||||
.replace(/-+$/, "");
|
.replace(/-+$/, "");
|
||||||
|
|
||||||
if (slug.length === 0) {
|
slug = `${slug || "heading"}-${++headingId}`;
|
||||||
slug = state.tokens[idx + 1].content
|
|
||||||
.replace(/\s+/g, "-")
|
|
||||||
.replace(SPECIAL_CHARACTERS_REGEX, "")
|
|
||||||
.replace(/\-\-+/g, "-")
|
|
||||||
.replace(/^-+/, "")
|
|
||||||
.replace(/-+$/, "");
|
|
||||||
slug = encodeURI(slug).replace(/%/g, "").substr(0, 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
linkOpen.attrSet("name", slug);
|
linkOpen.attrSet("name", slug);
|
||||||
linkOpen.attrSet("class", "anchor");
|
linkOpen.attrSet("class", "anchor");
|
||||||
|
@ -189,8 +189,8 @@ describe PrettyText do
|
|||||||
</div>
|
</div>
|
||||||
HTML
|
HTML
|
||||||
|
|
||||||
expect(cooked).to include("<h1>\n<a name=\"pre-heading\" class=\"anchor\" href=\"#pre-heading\"></a>Pre-heading</h1>")
|
expect(cooked).to include("<h1>\n<a name=\"pre-heading-1\" class=\"anchor\" href=\"#pre-heading-1\"></a>Pre-heading</h1>")
|
||||||
expect(cooked).to include("<h1>\n<a name=\"post-heading\" class=\"anchor\" href=\"#post-heading\"></a>Post-heading</h1>")
|
expect(cooked).to include("<h1>\n<a name=\"post-heading-2\" class=\"anchor\" href=\"#post-heading-2\"></a>Post-heading</h1>")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not break when there are headings before/after a poll without a title" do
|
it "does not break when there are headings before/after a poll without a title" do
|
||||||
@ -211,7 +211,7 @@ describe PrettyText do
|
|||||||
<div class="poll" data-poll-status="open" data-poll-name="poll">
|
<div class="poll" data-poll-status="open" data-poll-name="poll">
|
||||||
HTML
|
HTML
|
||||||
|
|
||||||
expect(cooked).to include("<h1>\n<a name=\"pre-heading\" class=\"anchor\" href=\"#pre-heading\"></a>Pre-heading</h1>")
|
expect(cooked).to include("<h1>\n<a name=\"pre-heading-1\" class=\"anchor\" href=\"#pre-heading-1\"></a>Pre-heading</h1>")
|
||||||
expect(cooked).to include("<h1>\n<a name=\"post-heading\" class=\"anchor\" href=\"#post-heading\"></a>Post-heading</h1>")
|
expect(cooked).to include("<h1>\n<a name=\"post-heading-2\" class=\"anchor\" href=\"#post-heading-2\"></a>Post-heading</h1>")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1909,7 +1909,7 @@ HTML
|
|||||||
|
|
||||||
html = <<~HTML
|
html = <<~HTML
|
||||||
<h1>
|
<h1>
|
||||||
<a name="hello-world" class="anchor" href="#hello-world"></a>
|
<a name="hello-world-1" class="anchor" href="#hello-world-1"></a>
|
||||||
Hello world
|
Hello world
|
||||||
</h1>
|
</h1>
|
||||||
HTML
|
HTML
|
||||||
|
Loading…
x
Reference in New Issue
Block a user