FIX: Restore replacement functionality for a[href] attributes (#42)

Followup to 948634fe31
This commit is contained in:
David Taylor 2024-09-04 09:31:17 +01:00 committed by GitHub
parent 83d5f2f914
commit a37e4bf266
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 58 additions and 12 deletions

View File

@ -64,6 +64,20 @@ function buildSelect(key, placeholder) {
return select; return select;
} }
function replaceInText(text, placeholders) {
for (const [key, { delimiter, value }] of Object.entries(placeholders)) {
const placeholderWithDelimiter = `${delimiter}${key}${delimiter}`;
let substitution = value;
if (!substitution?.length || substitution === "none") {
substitution = placeholderWithDelimiter;
}
text = text.replaceAll(placeholderWithDelimiter, substitution);
}
return text;
}
function performReplacements(cooked, placeholders) { function performReplacements(cooked, placeholders) {
cooked.querySelectorAll(VALID_TAGS).forEach((elem) => { cooked.querySelectorAll(VALID_TAGS).forEach((elem) => {
const textNodeWalker = document.createTreeWalker( const textNodeWalker = document.createTreeWalker(
@ -71,6 +85,7 @@ function performReplacements(cooked, placeholders) {
NodeFilter.SHOW_TEXT NodeFilter.SHOW_TEXT
); );
// Handle text nodes
while (textNodeWalker.nextNode()) { while (textNodeWalker.nextNode()) {
const node = textNodeWalker.currentNode; const node = textNodeWalker.currentNode;
@ -80,23 +95,28 @@ function performReplacements(cooked, placeholders) {
} }
const originalText = originalContentMap.get(node); const originalText = originalContentMap.get(node);
let text = originalText; const text = replaceInText(originalText, placeholders);
for (const [key, { delimiter, value }] of Object.entries(placeholders)) {
const placeholderWithDelimiter = `${delimiter}${key}${delimiter}`;
let substitution = value;
if (!substitution?.length || substitution === "none") {
substitution = placeholderWithDelimiter;
}
text = text.replaceAll(placeholderWithDelimiter, substitution);
}
if (node.data !== text) { if (node.data !== text) {
node.data = text; node.data = text;
} }
} }
// Handle a[href] attributes
document.querySelectorAll("a[href]").forEach((link) => {
const hrefAttr = link.attributes.getNamedItem("href");
if (!originalContentMap.has(hrefAttr)) {
// Haven't seen this attr before. Get the text, and store it for future transformations
originalContentMap.set(hrefAttr, hrefAttr.value);
}
const originalUrl = originalContentMap.get(hrefAttr);
const newUrl = replaceInText(originalUrl, placeholders);
if (hrefAttr.value !== newUrl) {
hrefAttr.value = newUrl;
}
});
}); });
} }

View File

@ -47,4 +47,30 @@ RSpec.describe "Placeholder", system: true do
expect(page).to have_content("BEFORE foo bar AFTER") expect(page).to have_content("BEFORE foo bar AFTER")
end end
end end
context "when placeholder is used in a[href]" do
fab!(:post) do
Fabricate(
:post,
raw: <<~MD
[wrap=placeholder key=\"TEST1\"][/wrap]
[Some link](https://example.com/=TEST1=)
MD
)
end
it "replaces string in href" do
topic_page.visit_topic(post.topic)
expect(page).to have_link(href: "https://example.com/=TEST1=")
page.find('.discourse-placeholder-value[data-key="TEST1"]').fill_in(with: "foo")
expect(page).to have_link(href: "https://example.com/foo")
page.find('.discourse-placeholder-value[data-key="TEST1"]').fill_in(with: "bar")
expect(page).to have_link(href: "https://example.com/bar")
end
end
end end