fix: decode HTML entities in storefront widget label attributes
Some checks failed
CI / Lint, Unit & Integration Tests (push) Has been cancelled
Some checks failed
CI / Lint, Unit & Integration Tests (push) Has been cancelled
Liquid's `| escape` filter encodes apostrophes/ampersands before the label strings land in data-* attributes; depending on how the theme processes translations that could survive into `dataset` still entity-encoded and then render literally (e.g. "Couldn't load available dates") once assigned to textContent. readConfig now decodes entities once via a detached <textarea>, routed through a shared get(key, fallback) helper for every label + heading. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
a2c78d703f
commit
3749b4d134
File diff suppressed because one or more lines are too long
@ -121,43 +121,60 @@ function formatDateLabel(dateIso: string): string {
|
||||
return date.toLocaleDateString(undefined, { weekday: "short", month: "short", day: "numeric", timeZone: "UTC" });
|
||||
}
|
||||
|
||||
// Liquid's `| escape` filter turns `'` into `'` (and `&` into `&`,
|
||||
// etc.) before the string lands in a data-* attribute. Depending on how the
|
||||
// theme/section double-processes translations, that can survive into
|
||||
// `dataset` still entity-encoded and then render literally when we assign it
|
||||
// to `textContent`. Decode once here so labels always show as plain text.
|
||||
function decodeEntities(value: string): string {
|
||||
if (!value || value.indexOf("&") === -1) return value;
|
||||
const el = document.createElement("textarea");
|
||||
el.innerHTML = value;
|
||||
return el.value;
|
||||
}
|
||||
|
||||
function readConfig(root: HTMLElement): WidgetConfig {
|
||||
const d = root.dataset;
|
||||
const get = (key: string, fallback: string): string => {
|
||||
const raw = d[key];
|
||||
return raw ? decodeEntities(raw) : fallback;
|
||||
};
|
||||
|
||||
const methods: WidgetConfig["methods"] = [];
|
||||
if (d.showShipping === "true") {
|
||||
methods.push({ value: "SHIPPING", label: d.labelShipping || "Shipping", attrLabel: d.attrLabelShipping || "Shipping date" });
|
||||
methods.push({ value: "SHIPPING", label: get("labelShipping", "Shipping"), attrLabel: get("attrLabelShipping", "Shipping date") });
|
||||
}
|
||||
if (d.showLocalDelivery === "true") {
|
||||
methods.push({
|
||||
value: "LOCAL_DELIVERY",
|
||||
label: d.labelLocalDelivery || "Local delivery",
|
||||
attrLabel: d.attrLabelLocalDelivery || "Delivery date",
|
||||
label: get("labelLocalDelivery", "Local delivery"),
|
||||
attrLabel: get("attrLabelLocalDelivery", "Delivery date"),
|
||||
});
|
||||
}
|
||||
if (d.showPickup === "true") {
|
||||
methods.push({ value: "PICKUP", label: d.labelPickup || "Pickup", attrLabel: d.attrLabelPickup || "Pickup date" });
|
||||
methods.push({ value: "PICKUP", label: get("labelPickup", "Pickup"), attrLabel: get("attrLabelPickup", "Pickup date") });
|
||||
}
|
||||
|
||||
return {
|
||||
root,
|
||||
heading: d.heading || "",
|
||||
heading: get("heading", ""),
|
||||
locationId: d.locationId || null,
|
||||
googleMapsApiKey: d.googleMapsApiKey || null,
|
||||
mode: d.mode === "preview" ? "preview" : "full",
|
||||
methods,
|
||||
labels: {
|
||||
chooseDate: d.labelChooseDate || "Choose a date",
|
||||
chooseTime: d.labelChooseTime || "Choose a time",
|
||||
noDates: d.labelNoDates || "No dates are available right now.",
|
||||
confirmed: d.labelConfirmed || "Confirmed for",
|
||||
change: d.labelChange || "Change",
|
||||
loading: d.labelLoading || "Loading available dates…",
|
||||
error: d.labelError || "Couldn't load available dates. Please try again.",
|
||||
postalCodeLabel: d.labelPostalCode || "Enter your postal/ZIP code",
|
||||
postalCodeSubmit: d.labelPostalCodeSubmit || "Check availability",
|
||||
outOfArea: d.labelOutOfArea || "Sorry, we don't deliver to this address.",
|
||||
earliestPrefix: d.labelEarliestPrefix || "Earliest",
|
||||
deliveryAtCheckout: d.labelDeliveryAtCheckout || "Enter your address at checkout to see local delivery dates.",
|
||||
chooseDate: get("labelChooseDate", "Choose a date"),
|
||||
chooseTime: get("labelChooseTime", "Choose a time"),
|
||||
noDates: get("labelNoDates", "No dates are available right now."),
|
||||
confirmed: get("labelConfirmed", "Confirmed for"),
|
||||
change: get("labelChange", "Change"),
|
||||
loading: get("labelLoading", "Loading available dates…"),
|
||||
error: get("labelError", "Couldn't load available dates. Please try again."),
|
||||
postalCodeLabel: get("labelPostalCode", "Enter your postal/ZIP code"),
|
||||
postalCodeSubmit: get("labelPostalCodeSubmit", "Check availability"),
|
||||
outOfArea: get("labelOutOfArea", "Sorry, we don't deliver to this address."),
|
||||
earliestPrefix: get("labelEarliestPrefix", "Earliest"),
|
||||
deliveryAtCheckout: get("labelDeliveryAtCheckout", "Enter your address at checkout to see local delivery dates."),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user