libs
libs copied to clipboard
CDATA missing from stringify output
When importing XML that contains <![CDATA[]]> tags, re-exporting strips those tags.
I don't believe there are any options available to re-instate them on output.
This causes issues when attempting to import CDATA-escaped HTML, re-exporting it escapes all HTML-parseSable characters.
Before:

After:

Will look into it this week 👍
Cheers!
FWIW, I've worked around it by adding CDATA tags to the original input where they belonged, based on the content type and the tag name, as I'm not sure how specific the WordPress importer is about the presence or lack of CDATA on inoffensive values.
To that effect, I'd appreciate if tags that were originally imported as CDATA tags were somehow preserved after being parsed into a JS object, manipulated and re-exported, perhaps using specialized types like XMLStrings or just XML<T> that keep the CDATA state.
I've also pulled the xml repository and made the following changes to avoid stripping existing CDATA tags:
stringify.ts, L23
/** CDATA matching */
const CDATA = /<!\[CDATA\[.*?]]>/s;
stringify.ts, L173
/** Default replacer */
function replace(
value: string,
{ nullToEmpty = true }: StringifierOptions,
) {
switch (true) {
// Convert empty values to null
case nullToEmpty && (value === null):
return "";
// Keep CDATA
case CDATA.test(value):
return value;
// Escape XML entities
default:
for (const entity in ENTITIES) {
value = `${value}`.replaceAll(
entity,
ENTITIES[entity as keyof typeof ENTITIES],
);
}
return value;
}
}
I also noticed, unless I'm wrong, the replacer method callback mentioned in the StringifierOptions is not actually implemented and goes nowhere. Is this something I could help you with in a separate issue?
To that effect, I'd appreciate if tags that were originally imported as CDATA tags were somehow preserved after being parsed into a JS object, manipulated and re-exported, perhaps using specialized types like XMLStrings or just XML<T> that keep the CDATA state.
I'd like to avoid using wrappers mostly to keep people's unit testing simple (like when asserting against string litterals: assertObjectMatch({foo:"bar"}, {foo:XMLString("bar")}) probably won't pass).
Eventually we could implement a metadata holder (probably with a non-enumerable Symbol to make it transparent) to retain some informations and helps re-export after manipulation (like: {[Symbol.for("xml-meta")]:{cdata:true}}) or just use the replacer feature
I also noticed, unless I'm wrong, the replacer method callback mentioned in the StringifierOptions is not actually implemented and goes nowhere. Is this something I could help you with in a separate issue?
Yes indeed, probably forgot to implement it 😅
You can open a PR with your changes if you wish to integrate them 👍
Since you found a work-around in the meantime, I won't work on this and will instead spend some time on v2 (#7) later while keeping in mind these improvements 🙂
Since you found a work-around in the meantime, I won't work on this and will instead spend some time on v2 (#7) later while keeping in mind these improvements slightly_smiling_face
No worries! #7 seems to be priority, most XML documents don't really use CDATA anyway
I'd like to avoid using wrappers mostly to keep people's unit testing simple (like when asserting against string litterals: assertObjectMatch({foo:"bar"}, {foo:XMLString("bar")}) probably won't pass).
I agree, a Metadata holder sounds like a much better idea
Yes indeed, probably forgot to implement it sweat_smile
Give me a few days and I'll open a PR, I'll also open a second one to not escape CDATA tags since it's easy to do and uninvasive
hey, any updates on this? :D Would like to use CDATA for an RSS feed plugin.
Sorry for the long wait !
It should be supported now, lmk if you if you still have issues with this 🙂