UNPKG

read-excel-file

Version:

Read `.xlsx` files in a web browser or in Node.js

130 lines (120 loc) 4.91 kB
// Starting from version `11.x`, `saxen` dropped CommonJS export. // CommonJS compatibility was requested by one of the users of this package: // https://gitlab.com/catamphetamine/read-excel-file/-/work_items/115 // Because of that, `saxen` source code had to be copy-pasted. // // Not to mention that it would have to be copy-pasted anyway for compatiblity with `worker-f` // because `Parser` is not a "self-contained" function. // // import { Parser } from 'saxen' import Parser from '../saxen/parser.js'; /** * Parses XML markup in a streaming fashion by calling the supplied callback functions as the XML markup is being input. * @param {any} state — The initial `state`. This `state` will supposedly be modified by the callback functions as the XML is being parsed. * @param {function} [onOpenTag] * @param {function} [onCloseTag] * @param {function} [onText] * @returns {object} An object with properties: `promise`, `write(string)`, `end()`. The `promise` resolves with nothing. */ export default function parseXmlStream(state, onOpenTag, onCloseTag, onText) { var errored = false; var mustNotHaveErrored = function mustNotHaveErrored() { if (errored) { // If this error is thrown then it means that there's a bug in the code // because the code should not have got here if the XML parsing process // has already errored. throw new Error('Errored'); } }; var resolvePromise; // const xmlns = false var parser = new Parser(); // // Whether it should parse XML "namespaces" (`xmlns` stuff). // // It parses faster when the "namespaces" mode is disabled. // // That's why it's not enabled. // if (xmlns) { // // // See `xml/xlsxNamespaces.js` file for the list of possible `.xlsx` namespaces. // // parser.ns(xlsxNamespaces) // parser.ns() // } var write = function write(xml) { mustNotHaveErrored(); parser.write(xml); }; var end = function end() { mustNotHaveErrored(); parser.end(); resolvePromise(); }; // This `promise` resolves with the final `state` when finished parsing. var promise = new Promise(function (resolve, reject) { resolvePromise = resolve; // on XML parsing error var onerror = function onerror(error) { errored = true; // If the error is not re-thrown here, the parser will simply keep parsing, // i.e. it doesn't halt after encountering an error and doesn't require manual resuming. // So it must re-throw the error here in order for the parser to stop. // Because the error is thrown inside a `new Promise()` constructor, // the promise will reject automatically. throw error; }; // got some text. `text` is the string of text. var ontext = function ontext(text, decodeEntities) { if (onText) { // `saxen` doesn't decode character references (`&#233;`, `&amp;`, etc) in text: // instead, it provides a `decodeEntities()` function for the consumer to call. onText(decodeEntities(text), state); } }; // opened a tag. `node` has "name" and "attributes" var onopentag = function onopentag(elementName, getAttributes, decodeEntities, selfClosing, getContext) { if (onOpenTag) { var attributes = getAttributes(); // `saxen` doesn't decode character references (`&#233;`, `&amp;`, etc) // in attribute values either, so decode them here. // The reason why `saxen` deliberately doesn't decode character references by default // is performance, I assume. for (var name in attributes) { // Also remove an `xmlns` prefix from the attribute name, if present. // When doing so, don't clean up the attribute name with a prefix // because it doesn't interfere, and it's faster this way. attributes[trimXmlnsPrefix(name, true)] = decodeEntities(attributes[name]); } onOpenTag(trimXmlnsPrefix(elementName), attributes, state); } }; // closed a tag. var onclosetag = function onclosetag(elementName) { if (onCloseTag) { onCloseTag(trimXmlnsPrefix(elementName), state); } }; parser.on('error', onerror); parser.on('text', ontext); parser.on('openTag', onopentag); parser.on('closeTag', onclosetag); }); return { promise: promise, write: write, end: end }; } function trimXmlnsPrefix(string, isAttributeName) { var i = 0; while (i < string.length) { if (string[i] === ':') { // If `string` is an attribute name, filter out `xmlns:...` cases // which aren't really attributes but rather xmlns schema URIs. if (isAttributeName && i === 5 && string.slice(0, 5) === 'xmlns') { // Ignore this attribute. } else { return string.slice(i + 1); } } i++; } return string; } //# sourceMappingURL=parseXmlStream.saxen.js.map