UNPKG

libxslt-wasm

Version:

JavaScript bindings for libxslt compiled to WebAssembly

123 lines (122 loc) 5.18 kB
import { XmlOutputBuffer } from "./XmlOutputBuffer.js"; import { DataSegment } from "../common/DataSegment.js"; import { NULL_POINTER } from "../constants.js"; import { stringToNewUTF8, HEAPU8 } from "../internal/emscripten.js"; import { xmlReadFile, xmlReadDoc, xmlReadMemory, xmlNodeDumpOutput, xmlFreeDoc, htmlDocContentDumpFormatOutput, } from "../internal/libxml2.js"; import { free, malloc } from "../internal/main.js"; import { parseXmlOptions } from "../utils/parseXmlOptions.js"; /** * A wrapper class for `xmlDocPtr` in libxml2 */ class XmlDocument extends DataSegment { static async fromUrl(url, { encoding, options } = {}) { const encodingPtr = encoding ? stringToNewUTF8(encoding) : null; const urlPtr = stringToNewUTF8(url); const xmlDocumentPtr = await xmlReadFile(urlPtr, encodingPtr ?? NULL_POINTER, parseXmlOptions(options ?? {})); if (encodingPtr !== null) { free(encodingPtr); } free(urlPtr); if (xmlDocumentPtr === NULL_POINTER) { throw new Error("Invalid XMLDocument"); } return new XmlDocument(xmlDocumentPtr); } static async fromString(xmlString, { encoding, url, options } = {}) { const xmlStringPtr = stringToNewUTF8(xmlString); const urlPtr = url ? stringToNewUTF8(url) : null; const encodingPtr = encoding ? stringToNewUTF8(encoding) : null; const xmlDocumentPtr = await xmlReadDoc(xmlStringPtr ?? NULL_POINTER, urlPtr ?? NULL_POINTER, encodingPtr ?? NULL_POINTER, parseXmlOptions(options ?? {})); free(xmlStringPtr); if (encodingPtr !== null) { free(encodingPtr); } if (urlPtr !== null) { free(urlPtr); } if (xmlDocumentPtr === NULL_POINTER) { throw new Error("Invalid XMLDocument"); } return new XmlDocument(xmlDocumentPtr); } static async fromBuffer(buffer, options) { return this.from(new Uint8Array(buffer), options); } static async from(data, { url, encoding, options } = {}) { const bufferPtr = malloc(data.byteLength); HEAPU8.set(data, bufferPtr); const urlPtr = url ? stringToNewUTF8(url) : null; const encodingPtr = encoding ? stringToNewUTF8(encoding) : null; const xmlDocumentPtr = await xmlReadMemory(bufferPtr, data.byteLength, urlPtr ?? NULL_POINTER, encodingPtr ?? NULL_POINTER, parseXmlOptions(options ?? {})); if (encodingPtr !== null) { free(encodingPtr); } if (urlPtr !== null) { free(urlPtr); } free(bufferPtr); if (xmlDocumentPtr === NULL_POINTER) { throw new Error("Invalid XMLDocument"); } return new XmlDocument(xmlDocumentPtr); } delete() { if (this.byteOffset !== NULL_POINTER) { xmlFreeDoc(this.byteOffset); } } toXmlOutputBuffer(options) { const xmlOutputBuffer = XmlOutputBuffer.allocate(); const encodingPtr = options?.encoding ? stringToNewUTF8(options.encoding) : null; /** * Since `xmlDocPtr` is a super pointer to `xmlNodePtr`, it can be passed to * `cur`. While this usage may be suspect, this technique is used for for * `htmlDocContentDumpOutput`. * * @see {@link https://gitlab.gnome.org/GNOME/libxml2/-/blob/master/HTMLtree.c#L938-942} */ xmlNodeDumpOutput(xmlOutputBuffer.byteOffset ?? NULL_POINTER, /* doc */ this.byteOffset ?? NULL_POINTER, /* cur */ this.byteOffset ?? NULL_POINTER, /* level */ 0, options?.format ? 1 : 0, /* encoding */ encodingPtr ?? NULL_POINTER); if (encodingPtr !== NULL_POINTER) { free(encodingPtr); } return xmlOutputBuffer; } /** * Formats the XML document as a string by dumping the XML tree to an * {@link XmlOutputBuffer} and returning its string representation. */ toString(options) { const xmlOutputBuffer = this.toXmlOutputBuffer(options); const xmlString = xmlOutputBuffer.toString(); xmlOutputBuffer.delete(); return xmlString; } /** * Assuming the document is an HTML tree, dumps the document to an * {@link XmlOutputBuffer} and returns the output buffer */ toHtmlOutputBuffer(options) { const htmlOutputBuffer = XmlOutputBuffer.allocate(); const encodingPtr = options?.encoding ? stringToNewUTF8(options.encoding) : null; htmlDocContentDumpFormatOutput(htmlOutputBuffer.byteOffset, this.byteOffset, encodingPtr ?? NULL_POINTER, options?.format ? 1 : 0); if (encodingPtr !== null) { free(encodingPtr); } return htmlOutputBuffer; } /** * Assuming the document is an HTML tree, serializes the document via * {@link toHtmlOutputBuffer} and returns the string */ toHtmlString(options) { const htmlOutputBuffer = this.toHtmlOutputBuffer(options); const xmlString = htmlOutputBuffer.toString(); htmlOutputBuffer.delete(); return xmlString; } } export { XmlDocument };