UNPKG

12.9 kBSource Map (JSON)View Raw
1{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,yBAAyB,EACzB,8BAA8B,EAC9B,qBAAqB,EACrB,sBAAsB,EACtB,MAAM,EACN,gBAAgB,GAEjB,MAAM,cAAc,CAAC;AAEtB,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,MAAM,cAAc,GAAG,CAAC,CAAC;AACzB,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAC9B,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAClC,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC;AACpB,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,MAAM,YAAY,GAAG,GAAG,CAAC;AAEzB,MAAM,MAAM,GAAG,CAAC,CAAe,EAAa,EAAE,CAAC,CAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,QAAQ,MAAK,SAAS,CAAC;AACzE,MAAM,SAAS,GAAG,CAAC,CAAe,EAAgB,EAAE,CAAC,CAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,QAAQ,MAAK,YAAY,CAAC;AAClF,MAAM,SAAS,GAAG,CAAC,CAAe,EAAgB,EAAE,CAAC,CAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,QAAQ,MAAK,YAAY,CAAC;AAElF,QAAQ,CAAC,CAAC,aAAa,CAAC,EAAW,EAAE,QAAa;IAChD,MAAM,EAAE,GAAG,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IACpD,KAAK,MAAM,IAAI,IAAI,gBAAgB,CAAC,EAAE,CAAC;QACrC,MAAM,IAAY,CAAC;AACvB,CAAC;AAED,QAAQ,CAAC,CAAC,gBAAgB,CAAC,EAAW,EAAE,QAAa;IACnD,MAAM,EAAE,GAAG,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;IACvD,KAAK,MAAM,IAAI,IAAI,gBAAgB,CAAC,EAAE,CAAC;QACrC,MAAM,IAAe,CAAC;AAC1B,CAAC;AAED,SAAS,QAAQ,CAAC,EAAe;IAC/B,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,WAAW;QAAE,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC;IACjD,OAAO,EAAE,IAAI,EAAE,CAAC,WAAW,CAAC;AAC9B,CAAC;AAMD;;GAEG;AACH,MAAM,OAAO,kBAAkB;IAA/B;QACE,oCAAS,IAAI,GAAG,EAAkC,EAAC;QACnD,yCAAc,IAAI,KAAK,EAAmB,EAAC;IAgI7C,CAAC;IA9HQ,EAAE,CAAC,QAAgB,EAAE,QAA8B;QACxD,MAAM,CAAC,uBAAA,IAAI,iCAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,UAAU,CAAC,QAAyB;QACzC,uBAAA,IAAI,sCAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,SAAS,CAAC,QAAkB;QACjC,oEAAoE;QACpE,0FAA0F;QAC1F,wDAAwD;QACxD,OAAO,IAAI,QAAQ,CAAC,qBAAqB,CAAC,sBAAsB,CAAC,CAAC,KAAK,IAAI,EAAE;;YAC3E,kFAAkF;YAClF,oEAAoE;YACpE,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACvC,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;YACzC,0EAA0E;YAE1E,2DAA2D;YAC3D,qGAAqG;YACrG,0CAA0C;YAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAiD,CAAC;YACzE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAiE,CAAC;YACzF,MAAM,OAAO,GAAG,IAAI,GAAG,EAA6C,CAAC;YACrE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsD,CAAC;YAE9E,KAAK,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,uBAAA,IAAI,iCAAO,EAAE;gBAC9C,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE;oBACtD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;wBAC9B,IAAI,OAAO,CAAC,OAAO,EAAE;4BACnB,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;yBACtD;wBAED,kFAAkF;wBAClF,+CAA+C;wBAC/C,IAAI,OAAO,CAAC,SAAS,EAAE;4BACrB,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;yBAC1E;wBAED,4GAA4G;wBAC5G,IAAI,OAAO,CAAC,IAAI,EAAE;4BAChB,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE;gCAChD,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;6BAClD;yBACF;wBAED,IAAI,OAAO,CAAC,QAAQ,EAAE;4BACpB,KAAK,MAAM,IAAI,IAAI,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE;gCACnD,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;6BACtD;yBACF;qBACF;iBACF;aACF;YAED,iDAAiD;YACjD,IAAG,QAAQ,CAAC,OAAO,EAAE;gBACnB,MAAM,OAAO,GAAG,IAAI,8BAA8B,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBACrE,KAAK,MAAM,OAAO,IAAI,uBAAA,IAAI,sCAAY,EAAE;oBACtC,MAAM,CAAA,MAAA,OAAO,CAAC,OAAO,+CAAf,OAAO,EAAW,OAAO,CAAC,CAAA,CAAC;iBAClC;aACF;YAED,wGAAwG;YACxG,sFAAsF;YACtF,MAAM,MAAM,GAAG,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,GAAG,SAAS,GAAG,YAAY,CAAC,CAAC;YAE5F,iDAAiD;YACjD,oEAAoE;YACpE,kGAAkG;YAClG,MAAM,KAAK,GAAG,CAAC,GAAG,gBAAgB,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;YAElD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;gBACxB,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,MAAA,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAI,EAAE,EAAE;oBACzD,MAAM,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;iBACnC;gBAED,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE;oBACnB,MAAM,QAAQ,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAI,EAAE,CAAC;oBACzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;wBAC9B,MAAM,OAAO,CAAC,IAAI,yBAAyB,CAAC,IAAI,EAAE,QAAQ,CAAuB,CAAC,CAAC;qBACpF;iBACF;qBACI,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE;oBACrB,MAAM,QAAQ,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAI,EAAE,CAAC;oBACzC,MAAM,IAAI,GAAG,IAAI,sBAAsB,CAAC,IAAI,EAAE,QAAQ,CAAoB,CAAC;oBAC3E,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;wBAC9B,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;qBACrB;oBACD,KAAK,MAAM,OAAO,IAAI,uBAAA,IAAI,sCAAY,EAAE;wBACtC,MAAM,CAAA,MAAA,OAAO,CAAC,IAAI,+CAAZ,OAAO,EAAQ,IAAI,CAAC,CAAA,CAAC;qBAC5B;oBACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;wBAC7B,MAAM,QAAQ,GAAG,IAAI,sBAAsB,CAAC,IAAI,EAAE,QAAQ,CAAoB,CAAC;wBAC/E,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;4BAC9B,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;yBACzB;wBACD,KAAK,MAAM,OAAO,IAAI,uBAAA,IAAI,sCAAY,EAAE;4BACtC,MAAM,CAAA,MAAA,OAAO,CAAC,IAAI,+CAAZ,OAAO,EAAQ,QAAQ,CAAC,CAAA,CAAC;yBAChC;qBACF;iBACF;qBACI,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE;oBACxB,MAAM,QAAQ,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAI,EAAE,CAAC;oBACzC,MAAM,OAAO,GAAG,IAAI,yBAAyB,CAAC,IAAI,EAAE,QAAQ,CAAuB,CAAC;oBACpF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;wBAC9B,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;qBACxB;oBACD,KAAK,MAAM,OAAO,IAAI,uBAAA,IAAI,sCAAY,EAAE;wBACtC,MAAM,CAAA,MAAA,OAAO,CAAC,QAAQ,+CAAhB,OAAO,EAAY,OAAO,CAAC,CAAA,CAAC;qBACnC;iBACF;aACF;YAED,4CAA4C;YAC5C,MAAM,GAAG,GAAG,IAAI,qBAAqB,CAAC,QAAQ,CAAC,CAAC;YAChD,KAAK,MAAM,OAAO,IAAI,uBAAA,IAAI,sCAAY,EAAE;gBACtC,MAAM,CAAA,MAAA,OAAO,CAAC,GAAG,+CAAX,OAAO,EAAO,GAAG,CAAC,CAAA,CAAC;aAC1B;YAED,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QACvD,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACpB,CAAC;CACF","sourcesContent":["import { parseHTML } from 'linkedom'\nimport { asyncIterableToStream } from 'whatwg-stream-to-async-iter';\nimport {\n ParsedHTMLRewriterElement,\n ParsedHTMLRewriterText,\n ParsedHTMLRewriterComment,\n ParsedHTMLRewriterDocumentType,\n ParsedHTMLRewriterEnd,\n promiseToAsyncIterable,\n append,\n treeWalkerToIter,\n Awaitable,\n} from './support.js';\n\nconst ELEMENT_NODE = 1;\nconst ATTRIBUTE_NODE = 2;\nconst TEXT_NODE = 3;\nconst COMMENT_NODE = 8;\nconst DOCUMENT_NODE = 9;\nconst DOCUMENT_TYPE_NODE = 10;\nconst DOCUMENT_FRAGMENT_NODE = 11;\nconst SHOW_ALL = -1;\nconst SHOW_ELEMENT = 1;\nconst SHOW_TEXT = 4;\nconst SHOW_COMMENT = 128;\n\nconst isText = (n?: Node | null): n is Text => n?.nodeType === TEXT_NODE;\nconst isElement = (n?: Node | null): n is Element => n?.nodeType === ELEMENT_NODE;\nconst isComment = (n?: Node | null): n is Comment => n?.nodeType === COMMENT_NODE;\n\nfunction* findTextNodes(el: Element, document: any): Iterable<Text> {\n const tw = document.createTreeWalker(el, SHOW_TEXT);\n for (const node of treeWalkerToIter(tw))\n yield node as Text;\n}\n\nfunction* findCommentNodes(el: Element, document: any): Iterable<Comment> {\n const tw = document.createTreeWalker(el, SHOW_COMMENT);\n for (const node of treeWalkerToIter(tw))\n yield node as Comment;\n}\n\nfunction findNext(el: Node | null): Node | null {\n while (el && !el.nextSibling) el = el.parentNode;\n return el && el.nextSibling;\n}\n\nexport type ParsedElementHandler = ElementHandler & {\n innerHTML?(html: string): void | Promise<void>;\n}\n\n/**\n * A DOM-based implementation of Cloudflare's `HTMLRewriter`.\n */\nexport class ParsedHTMLRewriter implements HTMLRewriter {\n #onMap = new Map<string, ParsedElementHandler[]>();\n #onDocument = new Array<DocumentHandler>();\n\n public on(selector: string, handlers: ParsedElementHandler): HTMLRewriter {\n append(this.#onMap, selector, handlers);\n return this;\n }\n\n public onDocument(handlers: DocumentHandler): HTMLRewriter {\n this.#onDocument.push(handlers);\n return this;\n }\n\n public transform(response: Response): Response {\n // This dance (promise => async gen => stream) is necessary because \n // a) the `Response` constructor doesn't accept async data, except via (byte) streams, and\n // b) `HTMLRewriter.transform` is not an async function.\n return new Response(asyncIterableToStream(promiseToAsyncIterable((async () => {\n // This is where the \"parse\" part comes in: We're not actually stream processing, \n // instead we'll just build the DOM in memory and run the selectors.\n const htmlText = await response.text();\n const { document } = parseHTML(htmlText);\n // const document = new DOMParser().parseFromString(htmlText, 'text/html')\n\n // After that, the hardest part is getting the order right.\n // First, we'll build a map of all elements that are \"interesting\", based on the registered handlers.\n // We take advantage of existing DOM APIs:\n const elemMap = new Map<Element, ((el: Element) => Awaitable<void>)[]>();\n const htmlMap = new Map<Node | null, [Element, ((html: string) => Awaitable<void>)][]>();\n const textMap = new Map<Text, ((text: Text) => Awaitable<void>)[]>();\n const commMap = new Map<Comment, ((comment: Comment) => Awaitable<void>)[]>();\n\n for (const [selector, handlers] of this.#onMap) {\n for (const elem of document.querySelectorAll(selector)) {\n for (const handler of handlers) {\n if (handler.element) {\n append(elemMap, elem, handler.element.bind(handler));\n }\n\n // The `innerHTML` handler needs to run at the beginning of the next sibling node,\n // after all the inner handlers have completed:\n if (handler.innerHTML) {\n append(htmlMap, findNext(elem), [elem, handler.innerHTML.bind(handler)]);\n }\n\n // Non-element handlers are odd, in the sense that they run for _any_ children, not just the immediate ones:\n if (handler.text) {\n for (const text of findTextNodes(elem, document)) {\n append(textMap, text, handler.text.bind(handler))\n }\n }\n\n if (handler.comments) {\n for (const comm of findCommentNodes(elem, document)) {\n append(commMap, comm, handler.comments.bind(handler))\n }\n }\n }\n }\n }\n\n // Handle document doctype before everything else\n if(document.doctype) {\n const doctype = new ParsedHTMLRewriterDocumentType(document.doctype);\n for (const handler of this.#onDocument) {\n await handler.doctype?.(doctype);\n }\n }\n\n // We'll then walk the DOM and run the registered handlers each time we encounter an \"interesting\" node.\n // Because we've stored them in a hash map, and can retrieve them via object identity:\n const walker = document.createTreeWalker(document, SHOW_ELEMENT | SHOW_TEXT | SHOW_COMMENT);\n\n // We need to walk the entire tree ahead of time,\n // otherwise the order might change based on added/deleted elements:\n // We're also adding `null` at the end to handle the edge case of `innerHTML` of the last element.\n const nodes = [...treeWalkerToIter(walker), null];\n\n for (const node of nodes) {\n for (const [prevElem, handler] of htmlMap.get(node) ?? []) {\n await handler(prevElem.innerHTML);\n }\n\n if (isElement(node)) {\n const handlers = elemMap.get(node) ?? [];\n for (const handler of handlers) {\n await handler(new ParsedHTMLRewriterElement(node, document) as unknown as Element);\n }\n }\n else if (isText(node)) {\n const handlers = textMap.get(node) ?? [];\n const text = new ParsedHTMLRewriterText(node, document) as unknown as Text;\n for (const handler of handlers) {\n await handler(text);\n }\n for (const handler of this.#onDocument) {\n await handler.text?.(text);\n }\n if (!isText(node.nextSibling)) {\n const textLast = new ParsedHTMLRewriterText(null, document) as unknown as Text;\n for (const handler of handlers) {\n await handler(textLast);\n }\n for (const handler of this.#onDocument) {\n await handler.text?.(textLast);\n }\n }\n }\n else if (isComment(node)) {\n const handlers = commMap.get(node) ?? [];\n const comment = new ParsedHTMLRewriterComment(node, document) as unknown as Comment;\n for (const handler of handlers) {\n await handler(comment);\n }\n for (const handler of this.#onDocument) {\n await handler.comments?.(comment);\n }\n }\n }\n\n // Handle document end after everything else\n const end = new ParsedHTMLRewriterEnd(document);\n for (const handler of this.#onDocument) {\n await handler.end?.(end);\n }\n\n return new TextEncoder().encode(document.toString());\n })())), response);\n }\n}\n"]}
\No newline at end of file