UNPKG

tag-soup

Version:

The fastest pure JS SAX/DOM XML/HTML parser.

85 lines (84 loc) 3.39 kB
import { createSaxParser } from './createSaxParser'; /** * Creates a new stateful DOM parser. * * @template Node The type of object that describes a node in the DOM tree. * @template ContainerNode The type of object that describes an element or a document in the DOM tree. * * @param handler The handler that provides factories and callbacks that produce the DOM tree. * @param options The parser options. * @returns The new parser that produces a DOM tree during parsing. */ export function createDomParser(handler, options) { var nodes = []; var saxParser = createSaxParser(createSaxHandler(nodes, handler, function (node) { return nodes.push(node); }), options); var write = function (sourceChunk) { saxParser.write(sourceChunk); return nodes; }; var parse = function (source) { saxParser.parse(source); var result = nodes; reset(); return result; }; var reset = function () { saxParser.reset(); nodes = []; }; return { write: write, parse: parse, reset: reset, }; } function createSaxHandler(nodes, handler, pushRootNode) { var elementFactory = handler.element, containerEndCallback = handler.containerEnd, appendChildCallback = handler.appendChild, textFactory = handler.text, documentFactory = handler.document, commentFactory = handler.comment, processingInstructionFactory = handler.processingInstruction, cdataFactory = handler.cdata, sourceEndCallback = handler.sourceEnd, resetCallback = handler.reset; var ancestors = { length: 0 }; if (typeof elementFactory !== 'function') { throw new Error('Missing element factory'); } if (typeof appendChildCallback !== 'function') { throw new Error('Missing appendChild callback'); } var pushNode = function (node) { if (ancestors.length !== 0) { appendChildCallback(ancestors[ancestors.length - 1], node); } else { pushRootNode(node); } }; var createDataTokenCallback = function (dataFactory) { return dataFactory != null ? function (token) { return pushNode(dataFactory(token)); } : undefined; }; return { startTag: function (token) { var node = elementFactory(token); pushNode(node); if (!token.selfClosing) { ancestors[ancestors.length++] = node; } }, endTag: function (token) { --ancestors.length; containerEndCallback === null || containerEndCallback === void 0 ? void 0 : containerEndCallback(ancestors[ancestors.length], token); }, doctype: function (token) { if (documentFactory && nodes.length === 0) { var node = documentFactory(token); pushNode(node); ancestors[ancestors.length++] = node; } }, text: createDataTokenCallback(textFactory), processingInstruction: createDataTokenCallback(processingInstructionFactory), cdata: createDataTokenCallback(cdataFactory), comment: createDataTokenCallback(commentFactory), sourceEnd: sourceEndCallback, reset: function () { ancestors.length = 0; resetCallback === null || resetCallback === void 0 ? void 0 : resetCallback(); }, }; }