@thednp/domparser
Version:
🍝 Super light HTML parser for isomorphic applications.
1 lines • 4.03 kB
Source Map (JSON)
{"version":3,"file":"parser-BeIn7YoZ.cjs","names":["htmlString?: string","root: RootLike","stack: (RootLike | NodeLike)[]","node: NodeLike"],"sources":["../src/parts/parser.ts"],"sourcesContent":["// parser.ts\nimport {\n getBaseAttributes,\n selfClosingTags,\n tokenize,\n toLowerCase,\n toUpperCase,\n} from \"./util.ts\";\nimport type {\n CommentLike,\n NodeLike,\n ParseResult,\n RootLike,\n TextLike,\n} from \"./types\";\n\n/**\n * **Parser**\n *\n * A tiny yet very fast and powerful parser that takes a string of HTML\n * and returns a DOM tree representation. In benchmarks it shows up to\n * 60x faster performance when compared to jsdom.\n *\n * @example\n * ```ts\n * const { root, components, tags } = Parser().parseFromString(\"<h1>Title</h1>\");\n * // > \"root\" is a RootLike node,\n * // > \"components\" is an array of component names,\n * // > \"tags\" is an array of tag names.\n * ```\n *\n * @returns The result of the parser.\n */\nexport function Parser() {\n return {\n parseFromString(htmlString?: string): ParseResult {\n const root: RootLike = { nodeName: \"#document\", children: [] };\n if (!htmlString) return { root, tags: [], components: [] };\n\n const stack: (RootLike | NodeLike)[] = [root];\n const components = new Set<string>();\n const tags = new Set<string>();\n const tokens = tokenize(htmlString);\n const tLen = tokens.length;\n\n for (let i = 0; i < tLen; i += 1) {\n const { tokenType, value, isSC } = tokens[i];\n const currentParent = stack[stack.length - 1];\n if (tokenType === \"doctype\") continue;\n\n if ([\"text\", \"comment\"].includes(tokenType)) {\n currentParent.children.push(\n {\n nodeName: `#${tokenType}`,\n nodeValue: value,\n } as CommentLike | TextLike,\n );\n continue;\n }\n\n const isClosing = value.startsWith(\"/\");\n const tagName = isClosing ? value.slice(1) : value.split(/[\\s/>]/)[0];\n const tagNameLower = toLowerCase(tagName);\n const isSelfClosing = isSC ||\n selfClosingTags.has(tagNameLower);\n\n // Register tag type\n (tagName[0] === toUpperCase(tagName[0]) ||\n tagName.includes(\"-\")\n ? components\n : tags).add(tagName);\n\n if (!isClosing) {\n const node: NodeLike = {\n tagName,\n nodeName: toUpperCase(tagName),\n attributes: getBaseAttributes(value),\n children: [],\n };\n\n currentParent.children.push(node);\n !isSelfClosing && stack.push(node);\n } else if (!isSelfClosing && stack.length > 1) {\n stack.pop();\n }\n }\n\n return {\n root,\n components: Array.from(components),\n tags: Array.from(tags),\n };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,SAAS;AACvB,QAAO,EACL,gBAAgBA,YAAkC;EAChD,MAAMC,OAAiB;GAAE,UAAU;GAAa,UAAU,CAAE;EAAE;AAC9D,OAAK,WAAY,QAAO;GAAE;GAAM,MAAM,CAAE;GAAE,YAAY,CAAE;EAAE;EAE1D,MAAMC,QAAiC,CAAC,IAAK;EAC7C,MAAM,6BAAa,IAAI;EACvB,MAAM,uBAAO,IAAI;EACjB,MAAM,SAAS,sBAAS,WAAW;EACnC,MAAM,OAAO,OAAO;AAEpB,OAAK,IAAI,IAAI,GAAG,IAAI,MAAM,KAAK,GAAG;GAChC,MAAM,EAAE,WAAW,OAAO,MAAM,GAAG,OAAO;GAC1C,MAAM,gBAAgB,MAAM,MAAM,SAAS;AAC3C,OAAI,cAAc,UAAW;AAE7B,OAAI,CAAC,QAAQ,SAAU,EAAC,SAAS,UAAU,EAAE;AAC3C,kBAAc,SAAS,KACrB;KACE,WAAW,GAAG,UAAU;KACxB,WAAW;IACZ,EACF;AACD;GACD;GAED,MAAM,YAAY,MAAM,WAAW,IAAI;GACvC,MAAM,UAAU,YAAY,MAAM,MAAM,EAAE,GAAG,MAAM,MAAM,SAAS,CAAC;GACnE,MAAM,eAAe,yBAAY,QAAQ;GACzC,MAAM,gBAAgB,QACpB,6BAAgB,IAAI,aAAa;AAGnC,IAAC,QAAQ,OAAO,yBAAY,QAAQ,GAAG,IACnC,QAAQ,SAAS,IAAI,GACrB,aACA,MAAM,IAAI,QAAQ;AAEtB,QAAK,WAAW;IACd,MAAMC,OAAiB;KACrB;KACA,UAAU,yBAAY,QAAQ;KAC9B,YAAY,+BAAkB,MAAM;KACpC,UAAU,CAAE;IACb;AAED,kBAAc,SAAS,KAAK,KAAK;AACjC,KAAC,iBAAiB,MAAM,KAAK,KAAK;GACnC,YAAW,iBAAiB,MAAM,SAAS,EAC1C,OAAM,KAAK;EAEd;AAED,SAAO;GACL;GACA,YAAY,MAAM,KAAK,WAAW;GAClC,MAAM,MAAM,KAAK,KAAK;EACvB;CACF,EACF;AACF"}