@thednp/domparser
Version:
🍝 Super light HTML parser for isomorphic applications.
1 lines • 4.07 kB
Source Map (JSON)
{"version":3,"file":"parser.cjs","names":["root: RootLike","stack: (RootLike | NodeLike)[]","tokenize","toLowerCase","selfClosingTags","toUpperCase","node: NodeLike","getBaseAttributes"],"sources":["../src/parts/parser.ts"],"sourcesContent":["// parser.ts\nimport {\n getBaseAttributes,\n selfClosingTags,\n tokenize,\n toLowerCase,\n toUpperCase,\n} from \"./util\";\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,gBAAgB,YAAkC;EAChD,MAAMA,OAAiB;GAAE,UAAU;GAAa,UAAU,EAAE;GAAE;AAC9D,MAAI,CAAC,WAAY,QAAO;GAAE;GAAM,MAAM,EAAE;GAAE,YAAY,EAAE;GAAE;EAE1D,MAAMC,QAAiC,CAAC,KAAK;EAC7C,MAAM,6BAAa,IAAI,KAAa;EACpC,MAAM,uBAAO,IAAI,KAAa;EAC9B,MAAM,SAASC,sBAAS,WAAW;EACnC,MAAM,OAAO,OAAO;AAEpB,OAAK,IAAI,IAAI,GAAG,IAAI,MAAM,KAAK,GAAG;GAChC,MAAM,EAAE,WAAW,OAAO,SAAS,OAAO;GAC1C,MAAM,gBAAgB,MAAM,MAAM,SAAS;AAC3C,OAAI,cAAc,UAAW;AAE7B,OAAI,CAAC,QAAQ,UAAU,CAAC,SAAS,UAAU,EAAE;AAC3C,kBAAc,SAAS,KACrB;KACE,UAAU,IAAI;KACd,WAAW;KACZ,CACF;AACD;;GAGF,MAAM,YAAY,MAAM,WAAW,IAAI;GACvC,MAAM,UAAU,YAAY,MAAM,MAAM,EAAE,GAAG,MAAM,MAAM,SAAS,CAAC;GACnE,MAAM,eAAeC,yBAAY,QAAQ;GACzC,MAAM,gBAAgB,QACpBC,6BAAgB,IAAI,aAAa;AAGnC,IAAC,QAAQ,OAAOC,yBAAY,QAAQ,GAAG,IACnC,QAAQ,SAAS,IAAI,GACrB,aACA,MAAM,IAAI,QAAQ;AAEtB,OAAI,CAAC,WAAW;IACd,MAAMC,OAAiB;KACrB;KACA,UAAUD,yBAAY,QAAQ;KAC9B,YAAYE,+BAAkB,MAAM;KACpC,UAAU,EAAE;KACb;AAED,kBAAc,SAAS,KAAK,KAAK;AACjC,KAAC,iBAAiB,MAAM,KAAK,KAAK;cACzB,CAAC,iBAAiB,MAAM,SAAS,EAC1C,OAAM,KAAK;;AAIf,SAAO;GACL;GACA,YAAY,MAAM,KAAK,WAAW;GAClC,MAAM,MAAM,KAAK,KAAK;GACvB;IAEJ"}