@fnlb-project/stanza
Version:
Modern XMPP in the browser, with a JSON API
1,024 lines (1,023 loc) • 37 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.childJSON = exports.childFloat = exports.childInteger = exports.childDate = exports.childTextBuffer = exports.childText = exports.childLanguageAttribute = exports.textBuffer = exports.textJSON = exports.text = exports.childDateAttribute = exports.childFloatAttribute = exports.childIntegerAttribute = exports.childBooleanAttribute = exports.childAttribute = exports.namespacedDateAttribute = exports.namespacedFloatAttribute = exports.namespacedIntegerAttribute = exports.namespacedBooleanAttribute = exports.namespacedAttribute = exports.dateAttribute = exports.floatAttribute = exports.integerAttribute = exports.booleanAttribute = exports.attribute = void 0;
exports.createElement = createElement;
exports.getLang = getLang;
exports.getTargetLang = getTargetLang;
exports.findAll = findAll;
exports.findOrCreate = findOrCreate;
exports.languageAttribute = languageAttribute;
exports.childTimezoneOffset = childTimezoneOffset;
exports.childBoolean = childBoolean;
exports.deepChildText = deepChildText;
exports.deepChildInteger = deepChildInteger;
exports.deepChildBoolean = deepChildBoolean;
exports.deepMultipleChildText = deepMultipleChildText;
exports.childEnum = childEnum;
exports.childDoubleEnum = childDoubleEnum;
exports.multipleChildText = multipleChildText;
exports.multipleChildAttribute = multipleChildAttribute;
exports.multipleChildIntegerAttribute = multipleChildIntegerAttribute;
exports.childAlternateLanguageText = childAlternateLanguageText;
exports.multipleChildAlternateLanguageText = multipleChildAlternateLanguageText;
exports.multipleChildEnum = multipleChildEnum;
exports.splicePath = splicePath;
exports.staticValue = staticValue;
exports.childRawElement = childRawElement;
exports.childLanguageRawElement = childLanguageRawElement;
exports.childAlternateLanguageRawElement = childAlternateLanguageRawElement;
exports.parameterMap = parameterMap;
const tslib_1 = require("tslib");
const platform_1 = require("../platform");
const Element_1 = tslib_1.__importDefault(require("./Element"));
const Parser_1 = require("./Parser");
function createElement(namespace, name, parentNamespace, parent) {
if (parent) {
namespace = namespace || parent.getNamespace();
const root = parent.getNamespaceRoot(namespace);
if (root) {
const prefix = root.useNamespace('', namespace);
name = `${prefix}:${name}`;
}
}
const el = new Element_1.default(name);
if (name.indexOf(':') < 0 && (!parentNamespace || namespace !== parentNamespace)) {
el.setAttribute('xmlns', namespace);
}
return el;
}
function getLang(xml, lang) {
return (xml.getAttribute('xml:lang') || lang || '').toLowerCase();
}
function getTargetLang(children, context) {
const availableLanguages = [];
for (const child of children) {
availableLanguages.push(getLang(child, context.lang));
}
let targetLanguage;
if (!context.resolveLanguage) {
targetLanguage = context.lang;
}
else {
targetLanguage = context.resolveLanguage(availableLanguages, context.acceptLanguages || [], context.lang);
}
return targetLanguage || '';
}
function findAll(xml, namespace, element, lang) {
const existing = xml.getChildren(element, namespace);
const parentLang = getLang(xml);
if (existing.length) {
if (lang) {
return existing.filter(child => {
const childLang = getLang(child, parentLang);
if (childLang === lang) {
return true;
}
});
}
else {
return existing;
}
}
return [];
}
function findOrCreate(xml, namespace, element, lang) {
namespace = namespace || xml.getNamespace();
const existing = findAll(xml, namespace, element, lang);
if (existing.length) {
return existing[0];
}
const created = createElement(namespace, element, xml.getDefaultNamespace(), xml);
const parentLang = getLang(xml, lang);
if (lang && parentLang !== lang) {
created.setAttribute('xml:lang', lang);
}
xml.appendChild(created);
return created;
}
function createAttributeField(opts) {
return {
importer(xml) {
const rawValue = xml.getAttribute(opts.name, opts.namespace);
if (!rawValue) {
return opts.dynamicDefault ? opts.dynamicDefault(rawValue) : opts.staticDefault;
}
return opts.parseValue(rawValue);
},
exporter(xml, value) {
if (value === undefined || value === opts.staticDefault) {
return;
}
const output = opts.writeValue(value);
if (!output && !opts.emitEmpty) {
return;
}
if (!opts.namespace || !opts.prefix) {
xml.setAttribute(opts.name, output, opts.emitEmpty);
}
else {
let prefix;
const root = xml.getNamespaceRoot(opts.namespace);
if (root) {
prefix = root.useNamespace(opts.prefix, opts.namespace);
}
else {
const namespaces = xml.getNamespaceContext();
if (!namespaces[opts.namespace]) {
prefix = xml.useNamespace(opts.prefix, opts.namespace);
namespaces[opts.namespace] = prefix;
}
}
xml.setAttribute(`${prefix}:${opts.name}`, output, opts.emitEmpty);
}
}
};
}
function createAttributeType(parser, createOpts) {
return (name, defaultValue = undefined, opts = {}) => {
opts = { staticDefault: defaultValue, ...opts };
return createAttributeField({
name,
...parser,
...(createOpts ? createOpts(opts) : opts)
});
};
}
function createNamespacedAttributeType(parser, createOpts) {
return (prefix, namespace, name, defaultValue = undefined, opts = {}) => {
opts = { staticDefault: defaultValue, ...opts };
return createAttributeField({
name,
namespace,
prefix,
...parser,
...(createOpts ? createOpts(opts) : opts)
});
};
}
function createChildAttributeField(opts) {
const converter = opts.converter ||
createAttributeField({
...opts,
namespace: opts.attributeNamespace
});
return {
importer(xml, context) {
const child = xml.getChild(opts.element, opts.namespace || xml.getNamespace());
if (!child) {
return opts.dynamicDefault ? opts.dynamicDefault() : opts.staticDefault;
}
return converter.importer(child, context);
},
exporter(xml, value, context) {
if (value !== undefined && value !== opts.staticDefault) {
const child = findOrCreate(xml, opts.namespace || xml.getNamespace(), opts.element);
converter.exporter(child, value, context);
}
}
};
}
function createChildAttributeType(parser, createOpts) {
return (namespace, element, name, defaultValue = undefined, opts = {}) => {
opts = { staticDefault: defaultValue, ...opts };
return createChildAttributeField({
element,
name,
namespace,
...parser,
...(createOpts ? createOpts(opts) : opts)
});
};
}
function createTextField(opts) {
return {
importer(xml) {
const rawValue = xml.getText();
if (!rawValue) {
return opts.dynamicDefault ? opts.dynamicDefault(rawValue) : opts.staticDefault;
}
return opts.parseValue(rawValue);
},
exporter(xml, value) {
if (!value && opts.emitEmpty) {
xml.children.push('');
return;
}
if (value === undefined || value === opts.staticDefault) {
return;
}
const output = opts.writeValue(value);
if (output) {
xml.children.push(output);
}
}
};
}
function createChildTextField(opts) {
const converter = createTextField(opts);
return {
importer(xml, context) {
const children = findAll(xml, opts.namespace || xml.getNamespace(), opts.element);
const targetLanguage = getTargetLang(children, context);
if (!children.length) {
return opts.dynamicDefault ? opts.dynamicDefault() : opts.staticDefault;
}
if (opts.matchLanguage) {
for (const child of children) {
if (getLang(child, context.lang) === targetLanguage) {
return converter.importer(child, context);
}
}
}
return converter.importer(children[0], context);
},
exporter(xml, value, context) {
if (!value && opts.emitEmpty) {
findOrCreate(xml, opts.namespace || xml.getNamespace(), opts.element, opts.matchLanguage ? context.lang : undefined);
return;
}
if (value !== undefined && value !== opts.staticDefault) {
const child = findOrCreate(xml, opts.namespace || xml.getNamespace(), opts.element, opts.matchLanguage ? context.lang : undefined);
converter.exporter(child, value, context);
}
}
};
}
const stringParser = {
parseValue: v => v,
writeValue: v => v
};
const integerParser = {
parseValue: v => parseInt(v, 10),
writeValue: v => v.toString()
};
const floatParser = {
parseValue: v => parseFloat(v),
writeValue: v => v.toString()
};
const boolParser = {
parseValue: v => {
if (v === 'true' || v === '1') {
return true;
}
if (v === 'false' || v === '0') {
return false;
}
return;
},
writeValue: v => (v ? '1' : '0')
};
const dateParser = {
parseValue: v => new Date(v),
writeValue: v => (typeof v === 'string' ? v : v.toISOString())
};
const jsonParser = {
parseValue: v => JSON.parse(v),
writeValue: v => JSON.stringify(v)
};
const bufferParser = (encoding = 'utf8') => ({
parseValue: v => {
if (encoding === 'base64' && v === '=') {
v = '';
}
return platform_1.Buffer.from(v.trim(), encoding);
},
writeValue: v => {
let data;
if (typeof v === 'string') {
data = platform_1.Buffer.from(v).toString(encoding);
}
else if (v) {
data = v.toString(encoding);
}
else {
data = '';
}
if (encoding === 'base64') {
data = data || '=';
}
return data;
}
});
const tzOffsetParser = {
parseValue: v => {
let sign = -1;
if (v.charAt(0) === '-') {
sign = 1;
v = v.slice(1);
}
const split = v.split(':');
const hours = parseInt(split[0], 10);
const minutes = parseInt(split[1], 10);
return (hours * 60 + minutes) * sign;
},
writeValue: v => {
if (typeof v === 'string') {
return v;
}
else {
let formatted = '-';
if (v < 0) {
v = -v;
formatted = '+';
}
const hours = v / 60;
const minutes = v % 60;
formatted +=
(hours < 10 ? '0' : '') + hours + ':' + (minutes < 10 ? '0' : '') + minutes;
return formatted;
}
}
};
// ====================================================================
// Field Types
// ====================================================================
exports.attribute = createAttributeType(stringParser, opts => ({
dynamicDefault: opts.emitEmpty ? v => (v === '' ? '' : opts.staticDefault) : undefined,
...opts
}));
exports.booleanAttribute = createAttributeType(boolParser);
exports.integerAttribute = createAttributeType(integerParser);
exports.floatAttribute = createAttributeType(floatParser);
exports.dateAttribute = createAttributeType(dateParser);
exports.namespacedAttribute = createNamespacedAttributeType(stringParser);
exports.namespacedBooleanAttribute = createNamespacedAttributeType(boolParser);
exports.namespacedIntegerAttribute = createNamespacedAttributeType(integerParser);
exports.namespacedFloatAttribute = createNamespacedAttributeType(floatParser);
exports.namespacedDateAttribute = createNamespacedAttributeType(dateParser);
exports.childAttribute = createChildAttributeType(stringParser);
exports.childBooleanAttribute = createChildAttributeType(boolParser);
exports.childIntegerAttribute = createChildAttributeType(integerParser);
exports.childFloatAttribute = createChildAttributeType(floatParser);
exports.childDateAttribute = createChildAttributeType(dateParser);
const text = (defaultValue) => createTextField({
staticDefault: defaultValue,
...stringParser
});
exports.text = text;
const textJSON = () => createTextField({ ...jsonParser });
exports.textJSON = textJSON;
const textBuffer = (encoding = 'utf8') => createTextField({
...bufferParser(encoding)
});
exports.textBuffer = textBuffer;
function languageAttribute() {
return {
importer(xml, context) {
return getLang(xml, context.lang);
},
exporter(xml, value, context) {
if (value && value.toLowerCase() !== context.lang) {
xml.setAttribute('xml:lang', value);
}
else {
xml.setAttribute('xml:lang', undefined);
}
}
};
}
const childLanguageAttribute = (namespace, element) => createChildAttributeField({
converter: languageAttribute(),
element,
name: 'xml:lang',
namespace,
...stringParser
});
exports.childLanguageAttribute = childLanguageAttribute;
const childText = (namespace, element, defaultValue, emitEmpty = false) => createChildTextField({
element,
emitEmpty,
matchLanguage: true,
namespace,
staticDefault: defaultValue,
...stringParser
});
exports.childText = childText;
const childTextBuffer = (namespace, element, encoding = 'utf8') => createChildTextField({
element,
matchLanguage: true,
namespace,
...bufferParser(encoding)
});
exports.childTextBuffer = childTextBuffer;
const childDate = (namespace, element) => createChildTextField({
element,
namespace,
...dateParser
});
exports.childDate = childDate;
const childInteger = (namespace, element, defaultValue) => createChildTextField({
element,
namespace,
staticDefault: defaultValue,
...integerParser
});
exports.childInteger = childInteger;
const childFloat = (namespace, element, defaultValue) => createChildTextField({
element,
namespace,
staticDefault: defaultValue,
...floatParser
});
exports.childFloat = childFloat;
const childJSON = (namespace, element) => createChildTextField({
element,
namespace,
...jsonParser
});
exports.childJSON = childJSON;
function childTimezoneOffset(namespace, element) {
return createChildTextField({
element,
namespace,
staticDefault: 0,
...tzOffsetParser
});
}
function childBoolean(namespace, element) {
return {
importer(xml) {
const child = xml.getChild(element, namespace || xml.getNamespace());
if (child) {
return true;
}
},
exporter(xml, value) {
if (value) {
findOrCreate(xml, namespace || xml.getNamespace(), element);
}
}
};
}
const deepChildExporter = (path, xml, value) => {
if (!value) {
return;
}
let current = xml;
for (const node of path) {
current = findOrCreate(current, node.namespace || current.getNamespace(), node.element);
}
current.children.push(value.toString());
};
function deepChildText(path, defaultValue) {
return {
importer(xml) {
let current = xml;
for (const node of path) {
current = current.getChild(node.element, node.namespace || current.getNamespace());
if (!current) {
return defaultValue;
}
}
return current.getText() || defaultValue;
},
exporter(xml, value) {
deepChildExporter(path, xml, value);
}
};
}
function deepChildInteger(path, defaultValue) {
return {
importer(xml) {
let current = xml;
for (const node of path) {
current = current.getChild(node.element, node.namespace || current.getNamespace());
if (!current) {
return;
}
}
const data = current.getText();
if (data) {
return parseInt(data, 10);
}
else if (defaultValue) {
return defaultValue;
}
},
exporter(xml, value) {
deepChildExporter(path, xml, value);
}
};
}
function deepChildBoolean(path) {
return {
importer(xml) {
let current = xml;
for (const node of path) {
current = current.getChild(node.element, node.namespace || current.getNamespace());
if (!current) {
return false;
}
}
return true;
},
exporter(xml, value) {
if (!value) {
return;
}
let current = xml;
for (const node of path) {
current = findOrCreate(current, node.namespace || current.getNamespace(), node.element);
}
}
};
}
function deepMultipleChildText(path) {
const finalChild = path.pop();
return {
importer(xml, context) {
let current = xml;
for (const node of path) {
current = current.getChild(node.element, node.namespace || current.getNamespace());
if (!current) {
return [];
}
}
const result = [];
const children = findAll(current, finalChild.namespace || current.getNamespace(), finalChild.element);
const targetLanguage = getTargetLang(children, context);
for (const child of children) {
if (getLang(child, context.lang) === targetLanguage) {
result.push(child.getText());
}
}
return result;
},
exporter(xml, values, context) {
if (!values.length) {
return;
}
let current = xml;
for (const node of path) {
current = findOrCreate(current, node.namespace || current.getNamespace(), node.element);
}
const { namespace, element } = finalChild;
for (const value of values) {
const child = createElement(namespace || current.getNamespace(), element, context.namespace, current);
child.children.push(value);
current.appendChild(child);
}
}
};
}
function childEnum(namespace, elements, defaultValue) {
const elementNames = new Map();
const valueNames = new Map();
for (const el of elements) {
if (typeof el === 'string') {
elementNames.set(el, el);
valueNames.set(el, el);
}
else {
elementNames.set(el[1], el[0]);
valueNames.set(el[0], el[1]);
}
}
return {
importer(xml) {
for (const child of xml.children) {
if (typeof child === 'string') {
continue;
}
else if (child.getNamespace() === (namespace || xml.getNamespace()) &&
elementNames.has(child.getName())) {
return elementNames.get(child.getName());
}
}
return defaultValue;
},
exporter(xml, value) {
if (valueNames.has(value)) {
findOrCreate(xml, namespace, valueNames.get(value));
}
}
};
}
function childDoubleEnum(namespace, parentElements, childElements, defaultValue) {
const parentNames = new Set(parentElements);
const childNames = new Set(childElements);
return {
importer(xml) {
for (const parent of xml.children) {
if (typeof parent === 'string') {
continue;
}
else if (parent.getNamespace() === (namespace || xml.getNamespace()) &&
parentNames.has(parent.getName())) {
for (const child of parent.children) {
if (typeof child === 'string') {
continue;
}
else if (child.getNamespace() === (namespace || xml.getNamespace()) &&
childNames.has(child.getName())) {
return [parent.getName(), child.getName()];
}
}
return [parent.getName()];
}
}
return defaultValue;
},
exporter(xml, value) {
const parent = findOrCreate(xml, namespace, value[0]);
if (value[1]) {
findOrCreate(parent, namespace, value[1]);
}
}
};
}
function multipleChildText(namespace, element) {
return {
importer(xml, context) {
const result = [];
const children = findAll(xml, namespace || xml.getNamespace(), element);
const targetLanguage = getTargetLang(children, context);
for (const child of children) {
if (getLang(child, context.lang) === targetLanguage) {
result.push(child.getText());
}
}
return result;
},
exporter(xml, values, context) {
for (const value of values) {
const child = createElement(namespace || xml.getNamespace(), element, context.namespace, xml);
child.children.push(value);
xml.appendChild(child);
}
}
};
}
function multipleChildAttribute(namespace, element, name) {
return {
importer(xml) {
const result = [];
const children = xml.getChildren(element, namespace || xml.getNamespace());
for (const child of children) {
const childAttr = child.getAttribute(name);
if (childAttr !== undefined) {
result.push(childAttr);
}
}
return result;
},
exporter(xml, values, context) {
for (const value of values) {
const child = createElement(namespace || xml.getNamespace(), element, context.namespace, xml);
child.setAttribute(name, value);
xml.appendChild(child);
}
}
};
}
function multipleChildIntegerAttribute(namespace, element, name) {
return {
importer(xml) {
const result = [];
const children = xml.getChildren(element, namespace || xml.getNamespace());
for (const child of children) {
const childAttr = child.getAttribute(name);
if (childAttr !== undefined) {
result.push(parseInt(childAttr, 10));
}
}
return result;
},
exporter(xml, values, context) {
for (const value of values) {
const child = createElement(namespace || xml.getNamespace(), element, context.namespace, xml);
child.setAttribute(name, value.toString());
xml.appendChild(child);
}
}
};
}
function childAlternateLanguageText(namespace, element) {
return {
importer(xml, context) {
const results = [];
const children = findAll(xml, namespace || xml.getNamespace(), element);
const seenLanuages = new Set();
for (const child of children) {
const langText = child.getText();
if (langText) {
const lang = getLang(child, context.lang);
if (seenLanuages.has(lang)) {
continue;
}
results.push({ lang, value: langText });
seenLanuages.add(lang);
}
}
return seenLanuages.size > 0 ? results : undefined;
},
exporter(xml, values, context) {
for (const entry of values) {
const val = entry.value;
if (val) {
const child = createElement(namespace || xml.getNamespace(), element, context.namespace, xml);
if (entry.lang !== context.lang) {
child.setAttribute('xml:lang', entry.lang);
}
child.children.push(val);
xml.appendChild(child);
}
}
}
};
}
function multipleChildAlternateLanguageText(namespace, element) {
return {
importer(xml, context) {
const results = [];
const langIndex = new Map();
let hasResults = false;
const children = findAll(xml, namespace || xml.getNamespace(), element);
for (const child of children) {
const langText = child.getText();
if (langText) {
const lang = getLang(child, context.lang);
let langResults = langIndex.get(lang);
if (!langResults) {
langResults = [];
langIndex.set(lang, langResults);
results.push({ lang, value: langResults });
}
langResults.push(langText);
hasResults = true;
}
}
return hasResults ? results : undefined;
},
exporter(xml, values, context) {
for (const entry of values) {
for (const val of entry.value) {
const child = createElement(namespace || xml.getNamespace(), element, context.namespace, xml);
if (entry.lang !== context.lang) {
child.setAttribute('xml:lang', entry.lang);
}
child.children.push(val);
xml.appendChild(child);
}
}
}
};
}
function multipleChildEnum(namespace, elements) {
const elementNames = new Map();
const valueNames = new Map();
for (const el of elements) {
if (typeof el === 'string') {
elementNames.set(el, el);
valueNames.set(el, el);
}
else {
elementNames.set(el[1], el[0]);
valueNames.set(el[0], el[1]);
}
}
return {
importer(xml) {
const results = [];
for (const child of xml.children) {
if (typeof child === 'string') {
continue;
}
else if (child.getNamespace() === (namespace || xml.getNamespace()) &&
elementNames.has(child.getName())) {
results.push(elementNames.get(child.getName()));
}
}
return results;
},
exporter(xml, values) {
for (const value of values) {
findOrCreate(xml, namespace, valueNames.get(value));
}
}
};
}
function splicePath(namespace, element, path, multiple = false) {
return {
importer(xml, context) {
const child = xml.getChild(element, namespace || xml.getNamespace());
if (!child) {
return;
}
const results = [];
for (const grandChild of child.children) {
if (typeof grandChild === 'string') {
continue;
}
if (context.registry.getImportKey(grandChild) === path) {
const imported = context.registry.import(grandChild);
if (imported) {
results.push(imported);
}
}
}
return multiple ? results : results[0];
},
exporter(xml, data, context) {
let values = [];
if (!Array.isArray(data)) {
values = [data];
}
else {
values = data;
}
const children = [];
for (const value of values) {
const child = context.registry.export(path, value, {
...context,
namespace: namespace || xml.getNamespace() || undefined
});
if (child) {
children.push(child);
}
}
if (children.length) {
const skipChild = findOrCreate(xml, namespace || xml.getNamespace(), element);
for (const child of children) {
skipChild.appendChild(child);
}
}
}
};
}
function staticValue(value) {
return {
exporter: () => undefined,
importer: () => value
};
}
function childRawElement(namespace, element, sanitizer) {
return {
importer(xml, context) {
if (sanitizer && (!context.sanitizers || !context.sanitizers[sanitizer])) {
return;
}
const child = xml.getChild(element, namespace || xml.getNamespace());
if (child) {
if (sanitizer) {
return context.sanitizers[sanitizer](child.toJSON());
}
else {
return child.toJSON();
}
}
},
exporter(xml, value, context) {
if (typeof value === 'string') {
const wrapped = (0, Parser_1.parse)(`<${element} xmlns="${namespace || xml.getNamespace()}">${value}</${element}>`);
value = wrapped.toJSON();
}
if (sanitizer) {
if (!context.sanitizers || !context.sanitizers[sanitizer]) {
return;
}
value = context.sanitizers[sanitizer](value);
}
if (value) {
xml.appendChild(new Element_1.default(value.name, value.attributes, value.children));
}
}
};
}
function childLanguageRawElement(namespace, element, sanitizer) {
return {
importer(xml, context) {
if (sanitizer && (!context.sanitizers || !context.sanitizers[sanitizer])) {
return;
}
const children = findAll(xml, namespace || xml.getNamespace(), element);
const targetLanguage = getTargetLang(children, context);
for (const child of children) {
if (getLang(child, context.lang) === targetLanguage) {
if (sanitizer) {
return context.sanitizers[sanitizer](child.toJSON());
}
else {
return child.toJSON();
}
}
}
if (children[0]) {
if (sanitizer) {
return context.sanitizers[sanitizer](children[0].toJSON());
}
else {
return children[0].toJSON();
}
}
},
exporter(xml, value, context) {
if (typeof value === 'string') {
const wrapped = (0, Parser_1.parse)(`<${element} xmlns="${namespace || xml.getNamespace()}">${value}</${element}>`);
value = wrapped.toJSON();
}
if (value && sanitizer) {
if (!context.sanitizers || !context.sanitizers[sanitizer]) {
return;
}
value = context.sanitizers[sanitizer](value);
}
if (!value) {
return;
}
const rawElement = findOrCreate(xml, namespace || xml.getNamespace(), element, context.lang);
for (const child of value.children) {
if (typeof child === 'string') {
rawElement.appendChild(child);
}
else if (child) {
rawElement.appendChild(new Element_1.default(child.name, child.attributes, child.children));
}
}
}
};
}
function childAlternateLanguageRawElement(namespace, element, sanitizer) {
return {
importer(xml, context) {
if (sanitizer && (!context.sanitizers || !context.sanitizers[sanitizer])) {
return;
}
const results = [];
const seenLanuages = new Set();
const children = findAll(xml, namespace || xml.getNamespace(), element);
for (const child of children) {
let result = child.toJSON();
if (sanitizer) {
result = context.sanitizers[sanitizer](result);
}
if (result) {
const lang = getLang(child, context.lang);
if (seenLanuages.has(lang)) {
continue;
}
results.push({ lang, value: result });
seenLanuages.add(lang);
}
}
return seenLanuages.size > 0 ? results : undefined;
},
exporter(xml, values, context) {
for (const entry of values) {
let value = entry.value;
if (typeof value === 'string') {
const wrapped = (0, Parser_1.parse)(`<${element} xmlns="${namespace || xml.getNamespace()}">${value}</${element}>`);
value = wrapped.toJSON();
}
if (value && sanitizer) {
if (!context.sanitizers || !context.sanitizers[sanitizer]) {
continue;
}
value = context.sanitizers[sanitizer](value);
}
if (value) {
const rawElement = createElement(namespace || xml.getNamespace(), element, context.namespace, xml);
xml.appendChild(rawElement);
if (entry.lang !== context.lang) {
rawElement.setAttribute('xml:lang', entry.lang);
}
for (const child of value.children) {
if (typeof child === 'string') {
rawElement.appendChild(child);
}
else {
rawElement.appendChild(new Element_1.default(child.name, child.attributes, child.children));
}
}
}
}
}
};
}
function parameterMap(namespace, element, keyName, valueName) {
return {
importer(xml, context) {
const result = {};
const params = findAll(xml, namespace, element);
const keyImporter = (0, exports.attribute)(keyName).importer;
const valueImporter = (0, exports.attribute)(valueName).importer;
for (const param of params) {
result[keyImporter(param, context)] = valueImporter(param, context);
}
return result;
},
exporter(xml, values, context) {
const keyExporter = (0, exports.attribute)(keyName).exporter;
const valueExporter = (0, exports.attribute)(valueName).exporter;
const ns = namespace || xml.getNamespace();
for (const [param, value] of Object.entries(values)) {
const paramEl = createElement(ns, element, context.namespace, xml);
keyExporter(paramEl, param, context);
if (values[param]) {
valueExporter(paramEl, value, context);
}
xml.appendChild(paramEl);
}
}
};
}