sf-package-list
Version:
Convert Salesforce package.xml manifests to and from plain-text list format.
64 lines • 2.25 kB
JavaScript
const ATTRIBUTE_PREFIX = '@_';
const INDENT = ' ';
// Matches fast-xml-builder's default entity order: & must run first so
// entities it introduces (< etc.) are not themselves re-escaped.
const escapeXmlValue = (value) => value
.replaceAll('&', '&')
.replaceAll('>', '>')
.replaceAll('<', '<')
.replaceAll("'", ''')
.replaceAll('"', '"');
const toText = (value) => String(value);
function buildAttributes(node) {
let attrStr = '';
for (const key of Object.keys(node)) {
if (!key.startsWith(ATTRIBUTE_PREFIX))
continue;
const name = key.slice(ATTRIBUTE_PREFIX.length);
attrStr += ` ${name}="${escapeXmlValue(toText(node[key]))}"`;
}
return attrStr;
}
function buildChildren(node, depth) {
let out = '';
for (const key of Object.keys(node)) {
if (key.startsWith(ATTRIBUTE_PREFIX))
continue;
const value = node[key];
if (value === undefined)
continue;
if (Array.isArray(value)) {
for (const item of value)
out += buildElement(key, item, depth);
}
else {
out += buildElement(key, value, depth);
}
}
return out;
}
function buildElement(key, value, depth) {
const indent = INDENT.repeat(depth);
if (value === null)
return `${indent}<${key}/>\n`;
if (typeof value !== 'object') {
return `${indent}<${key}>${escapeXmlValue(toText(value))}</${key}>\n`;
}
const node = value;
const attrStr = buildAttributes(node);
const childrenStr = buildChildren(node, depth + 1);
return childrenStr === ''
? `${indent}<${key}${attrStr}></${key}>\n`
: `${indent}<${key}${attrStr}>\n${childrenStr}${indent}</${key}>\n`;
}
/**
* Minimal replacement for fast-xml-builder, matching its output byte-for-byte
* for this project's config (format: true, indentBy: 4 spaces, ignoreAttributes:
* false, attributeNamePrefix: '@_', suppressEmptyNode: false). Root object must
* have exactly one top-level key.
*/
export function buildXml(jObj) {
const [rootKey] = Object.keys(jObj);
return buildElement(rootKey, jObj[rootKey], 0);
}
//# sourceMappingURL=xmlBuilder.js.map