libs icon indicating copy to clipboard operation
libs copied to clipboard

CDATA missing from stringify output

Open acerspyro opened this issue 4 years ago • 4 comments
trafficstars

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: image

After: image

acerspyro avatar Oct 11 '21 05:10 acerspyro

Will look into it this week 👍

lowlighter avatar Oct 12 '21 17:10 lowlighter

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?

acerspyro avatar Oct 12 '21 21:10 acerspyro

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 🙂

lowlighter avatar Oct 14 '21 02:10 lowlighter

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

acerspyro avatar Oct 14 '21 16:10 acerspyro

hey, any updates on this? :D Would like to use CDATA for an RSS feed plugin.

adb-sh avatar Apr 11 '23 20:04 adb-sh

Sorry for the long wait !

It should be supported now, lmk if you if you still have issues with this 🙂

lowlighter avatar Apr 18 '23 02:04 lowlighter