Skip to content

ooxml-tools/xml

Repository files navigation

@ooxml-tools/xml

Some XML helpers to help with OOXML development

Note

These are all based around xml-js and output that modules internal format

API

asXmlElement

When working with xml-js it's really handy to not have to worry about when you're passing an XML string our the xml-js JSON type called Element

This helper function just outputs an Element for either input

asXmlElement("<name>foo</name>"); // => {name: "name", text: "foo"}
asXmlElement({ name: "name", text: "foo" }); // => {name: "name", text: "foo"}

Note

All the other functions in this document that accept XML, also accept this Element (using this function)

safeXml

An XML tagged template literal with the following features

  • error if XML is incorrect
  • array support in substitution

The following will error in development, because of mismatched start/end tags

safeXml`<foo>hello</bar>`;

Substitution of arrays "just works" so you can map values in the tagged template literals

const items = [1, 2, 3].map((n) => safeXml`<name>item ${1}</name>`);
const outXml = safeXml`<test>${items}</test>`;
assert.equal(
  outXml,
  `<test><name>item 1</name><name>item 2</name><name>item 3</name></test>`,
);

This also makes it easy to support https://prettier.io/docs/en/options#embedded-language-formatting

compact

Removes non required whitespace from the XML

const outXml = compact(`
    <test>
        something
    </test>
`);
assert.equal(outXml, "<test>something</test>");

collapseFragments

For XML to be valid, there must be a single root node. When composing apps it's handy for that not to be true.

For example the following would error

const xml = safeXml`
    <name>foo</name>
    <name>bar</name>
`;

So instead we'd like something like a HTML fragment

const xml = safeXml`
    <XML_FRAGMENT>
        <name>foo</name>
        <name>bar</name>
    </XML_FRAGMENT>
`;

So we did just that, collapseFragments walks over a tree removing <XML_FRAGMENT>...</XML_FRAGMENT> nodes.

const innerBit = safeXml`
    <XML_FRAGMENT>
        <name>foo</name>
        <name>bar</name>
    </XML_FRAGMENT>
`;
const newXml = collapseFragments(
  safeXml`
        <doc>
            ${innerBit}
        </doc>
    `,
);
assert.equal(
  newXml,
  `
    <doc>
        <name>foo</name>
        <name>bar</name>
    </doc>
`,
);

cdata

From the wikipedia page

CDATA section is a piece of element content that is marked up to be interpreted literally, as textual data, not as marked-up content.

But <name><![CDATA[one < two]]><name> is ugly and hard to read, so instead

safeXml`<name>${cdata("one < two")}</name>`;

format

Format XML in a consistent way, useful for logging and snapshot testing

format(`
   <test> one
      </test>
`); /* =>
 * <test>
 *   one
 * </test>
 */

getAllByTestId

const element = getAllByTestId(`
    <root>
        <name _testid="test">
            Hello
        </name>
    </test>
`)

getByTestId

const element = getByTestId(`
    <root>
        <name _testid="test">
            Hello
        </name>
    </test>
`)

getSingleTextNode

Returns a single text node if one exists

getSingleTextNode(`<test>hello world</test>`) // => {type: "text", text: "hello world"}

Else throws an error

getSingleTextNode(`<test>hello <foo>inner node</foo> world</test>`) // => throws Error

removeTestIds

const element = removeTestIds(`
    <root>
        <name _testid="test">
            Hello
        </name>
    </test>
`) /* =>
 * <root>
 *     <name>
 *         Hello
 *     </name>
 * </test>
 */

CI

codecov

License

MIT

About

Some XML helpers to help with OOXML development

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •