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(
|
||||
"# #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"
|
||||
);
|
||||
|
||||
|
@ -696,7 +696,7 @@ eviltrout</p>
|
|||
test("Heading", function (assert) {
|
||||
assert.cooked(
|
||||
"**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"
|
||||
);
|
||||
});
|
||||
|
@ -939,7 +939,7 @@ eviltrout</p>
|
|||
|
||||
assert.cooked(
|
||||
"## 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."
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
const SPECIAL_CHARACTERS_REGEX = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~’]/g;
|
||||
|
||||
export function setup(helper) {
|
||||
if (helper.getOptions().previewing) {
|
||||
return;
|
||||
|
@ -7,7 +5,11 @@ export function setup(helper) {
|
|||
|
||||
helper.registerPlugin((md) => {
|
||||
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 (
|
||||
state.tokens[idx].type === "blockquote_open" ||
|
||||
(state.tokens[idx].type === "bbcode_open" &&
|
||||
|
@ -37,15 +39,7 @@ export function setup(helper) {
|
|||
.replace(/^-+/, "")
|
||||
.replace(/-+$/, "");
|
||||
|
||||
if (slug.length === 0) {
|
||||
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);
|
||||
}
|
||||
slug = `${slug || "heading"}-${++headingId}`;
|
||||
|
||||
linkOpen.attrSet("name", slug);
|
||||
linkOpen.attrSet("class", "anchor");
|
||||
|
|
|
@ -189,8 +189,8 @@ describe PrettyText do
|
|||
</div>
|
||||
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=\"post-heading\" class=\"anchor\" href=\"#post-heading\"></a>Post-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-2\" class=\"anchor\" href=\"#post-heading-2\"></a>Post-heading</h1>")
|
||||
end
|
||||
|
||||
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">
|
||||
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=\"post-heading\" class=\"anchor\" href=\"#post-heading\"></a>Post-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-2\" class=\"anchor\" href=\"#post-heading-2\"></a>Post-heading</h1>")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1909,7 +1909,7 @@ HTML
|
|||
|
||||
html = <<~HTML
|
||||
<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
|
||||
</h1>
|
||||
HTML
|
||||
|
|
Loading…
Reference in New Issue