import { Parser, Input, Output, run } from './combinator/parser'; import { html, define } from 'typed-dom/dom'; import { querySelectorWith, querySelectorAllWith } from 'typed-dom/query'; export function inspect(parser: Parser, input: Input, until: number | string = Infinity): [...string[][], string] | undefined { const output = new Output(); for (const _ of run(parser, input, output)); assert.deepStrictEqual(output.data, [output.data[0]]); assert(output.labels.length === 1); assert(output.annotations.length === 1); assert(output.references.length === 1); assert(output.state || output.peek().length === 0); assert(!output.error); return !output.state ? undefined : [ ...output.data.map(nodes => nodes.foldl((acc, { value: node }) => { assert(node); if (typeof node === 'string') return acc.push(node), acc; if (node instanceof DocumentFragment) return acc.push(html('div', [node]).innerHTML), acc; node = node.cloneNode(true); assert(!querySelectorWith(node, '.invalid[data-invalid-message$="."]')); querySelectorAllWith(node, '.invalid').forEach(el => { assert(el.matches('[data-invalid-syntax][data-invalid-type][data-invalid-message]')); define(el, { 'data-invalid-syntax': null, 'data-invalid-type': null, 'data-invalid-message': null, }); }); until = typeof until === 'number' ? until : ~(~node.outerHTML.indexOf(until) || -Infinity) + until.length; const el = html('div'); assert(!node.outerHTML.match(/[\x00-\x08\x0B-\x1F\x7F]/)); el.innerHTML = node.outerHTML.slice(0, until); if (node.outerHTML.length <= until) { assert(node.outerHTML === el.innerHTML); // eslint-disable-next-line redos/no-vulnerable assert(node.childNodes.length === el.firstChild?.childNodes.length || />[^<]{65537}/.test(node.outerHTML)); } else { assert(el.innerHTML.startsWith(node.outerHTML.slice(0, until))); } return acc.push(normalize(node.outerHTML.slice(0, until))), acc; }, [])), input.source.slice(input.position), ]; } // Bug: Firefox export function normalize(html: string): string { return html .replace(/:random-\w+:/g, ':random:') .replace(/ data-invalid-\w+="[^"]*"/g, ''); }