Source: stanza.js

import log from './log.js';
import { xmlHtmlNode } from './utils.js';

const PARSE_ERROR_NS = 'http://www.w3.org/1999/xhtml';

/**
 * @param {string} string
 * @param {boolean} [throwErrorIfInvalidNS]
 * @return {Element}
 */
export function toStanza(string, throwErrorIfInvalidNS) {
    const doc = xmlHtmlNode(string);

    if (doc.getElementsByTagNameNS(PARSE_ERROR_NS, 'parsererror').length) {
        throw new Error(`Parser Error: ${string}`);
    }

    const node = doc.firstElementChild;

    if (
        ['message', 'iq', 'presence'].includes(node.nodeName.toLowerCase()) &&
        node.namespaceURI !== 'jabber:client' &&
        node.namespaceURI !== 'jabber:server'
    ) {
        const err_msg = `Invalid namespaceURI ${node.namespaceURI}`;
        if (throwErrorIfInvalidNS) {
            throw new Error(err_msg);
        } else {
            log.error(err_msg);
        }
    }
    return node;
}

/**
 * A Stanza represents a XML element used in XMPP (commonly referred to as
 * stanzas).
 */
export class Stanza {
    /**
     * @param { string[] } strings
     * @param { any[] } values
     */
    constructor(strings, values) {
        this.strings = strings;
        this.values = values;
    }

    /**
     * @return { string }
     */
    toString() {
        this.string =
            this.string ||
            this.strings.reduce((acc, str) => {
                const idx = this.strings.indexOf(str);
                const value = this.values.length > idx ? this.values[idx].toString() : '';
                return acc + str + value;
            }, '');
        return this.string;
    }

    /**
     * @return { Element }
     */
    tree() {
        this.node = this.node ?? toStanza(this.toString(), true);
        return this.node;
    }
}

/**
 * Tagged template literal function which generates {@link Stanza } objects
 * @example stx`<presence type="${type}" xmlns="jabber:client"><show>${show}</show></presence>`
 *
 * @param { string[] } strings
 * @param { ...any } values
 */
export function stx(strings, ...values) {
    return new Stanza(strings, values);
}