Skip to content

Instantly share code, notes, and snippets.

@shadowcat-mst
Created July 10, 2018 20:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shadowcat-mst/293e3f5a7b4bd45c6c141fa3e80b87ce to your computer and use it in GitHub Desktop.
Save shadowcat-mst/293e3f5a7b4bd45c6c141fa3e80b87ce to your computer and use it in GitHub Desktop.
// intentionally incomplete dummy escape function because meh
function escapeXML (str) {
return str.toString().replace(/"/g, '"')
}
function qxml ([ firstString, ...remainingStrings ], ...interpolations) {
return remainingStrings.map(
(v, idx) => [ v, interpolations[idx] ]
).reduce(
(acc, [ trail, interp ]) => (
acc
+ (interp instanceof Object
? Object.entries(interp)
.map(([ k, v ]) => `${k}="${escapeXML(v)}"`).join(" ")
: escapeXML(interp))
+ trail
),
firstString
);
}
let bar = "bar & grill"
let attrs = { quux: 1, fleem: 'Hello "Bob"' };
console.log(qxml`<tag ${attrs}>${bar}</tag>`);
// logs: <tag quux="1" fleem="Hello &quot;Bob&quot;">bar & grill</tag>
@genio
Copy link

genio commented Jul 10, 2018

YAY

const XML = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    '\'': '&#39;',
};

function xml_escape(str = '') {
    return str.toString().replace(/([&<>"'])/g, p1 => XML[p1]);
}

function qxml ([ firstString, ...remainingStrings ], ...interpolations) {
    return remainingStrings.map(
        (v, idx) => [ v, interpolations[idx] ]
    ).reduce(
        (acc, [ trail, interp ]) => (
            acc
            + (interp instanceof Object
            ? Object.entries(interp)
                   .map(([ k, v ]) => `${k}="${xml_escape(v)}"`).join(" ")
            : xml_escape(interp))
            + trail
        ),
        firstString
    );
}

class Foo {
    // ...
    toXML() {
        let { attributes, account, consumerKey, token, nonce, timestamp, signature } = this.generate().tokenPassport;
        let string = qxml`
        <tokenPassport ${attributes}>
            <account>${account}</account>
            <consumerKey>${consumerKey}</consumerKey>
            <token>${token}</token>
            <nonce>${nonce}</nonce>
            <timestamp>${timestamp}</timestamp>
            <signature ${signature.attributes}>
                ${signature['$value']}
            </signature>
        </tokenPassport>`;
        return string.replace(/^\s+/gm, '').replace(/\r?\n|\r/g, '').trim();
    }
}

renders: (newlines added for readability in the gist)

<tokenPassport xsi:type="ns2:TokenPassport">
  <account>13&amp;bar</account>
  <consumerKey>123&lt;adfawerf&gt;huh&amp;what</consumerKey>
  <token>blehb&gt;&#39;123&#39;</token>
  <nonce>31607184781599965494</nonce>
  <timestamp>1531254889</timestamp>
  <signature algorithm="HMAC-SHA1">Ghdxa7UgA8YpDjpxVCAOVSEBQlI=</signature>
</tokenPassport>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment