{"id":13305,"library":"htmljs-parser","title":"HTMLJS Parser","description":"The `htmljs-parser` is a specialized HTML parser designed to understand and process both standard HTML elements and embedded JavaScript expressions, particularly within attribute values and placeholders. It forms a core component of the Marko framework. The current stable version is `5.10.2`, with a consistent release cadence of frequent patch updates and minor versions introducing new validation APIs and parsing refinements. Its primary differentiator lies in its ability to deeply integrate JavaScript expression parsing directly into the HTML parsing stream, enabling advanced templating and reactive UI paradigms that extend beyond traditional HTML parsing capabilities. It is well-suited for environments requiring the compilation or processing of HTML containing dynamic JavaScript logic.","status":"active","version":"5.10.2","language":"javascript","source_language":"en","source_url":"https://github.com/marko-js/htmljs-parser","tags":["javascript","HTML","JavaScript","browser","compiler","expressions","nodejs","parser","server","typescript"],"install":[{"cmd":"npm install htmljs-parser","lang":"bash","label":"npm"},{"cmd":"yarn add htmljs-parser","lang":"bash","label":"yarn"},{"cmd":"pnpm add htmljs-parser","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The package primarily uses named exports. For CommonJS, destructure the export from `require()`.","wrong":"const createParser = require('htmljs-parser').createParser;","symbol":"createParser","correct":"import { createParser } from 'htmljs-parser';"},{"note":"ErrorCode is a named export from the main package entry point, not a default export or a submodule.","wrong":"import ErrorCode from 'htmljs-parser/error-code';","symbol":"ErrorCode","correct":"import { ErrorCode } from 'htmljs-parser';"},{"note":"TagType is also a named export, primarily used for categorizing parsed HTML tags programmatically. Since v5.8.1, it uses a normal enum for easier consumption.","wrong":"const TagType = require('htmljs-parser').TagType;","symbol":"TagType","correct":"import { TagType } from 'htmljs-parser';"}],"quickstart":{"code":"import { createParser, ErrorCode, TagType } from 'htmljs-parser';\n\nconst htmlCode = `\n<div>\n  <!-- A simple comment -->\n  Hi ${process.env.USERNAME ?? 'Guest'}!\n  <span class=\"greeting\">Hello world!</span>\n  <div $!{someDynamicAttr}>\n    <![CDATA[This is CDATA]]>\n  </div>\n</div>\n`;\n\nconst parser = createParser({\n  onError(range) {\n    console.error(`Error (${ErrorCode[range.code]}): ${range.message} at ${range.start}:${range.end}`);\n  },\n  onText(range) {\n    console.log(`Text: '${parser.read(range)}'`);\n  },\n  onPlaceholder(range) {\n    console.log(`Placeholder (escape: ${range.escape}): '${parser.read(range)}' (value: '${parser.read(range.value)}')`);\n  },\n  onComment(range) {\n    console.log(`Comment: '${parser.read(range)}' (value: '${parser.read(range.value)}')`);\n  },\n  onCDATA(range) {\n    console.log(`CDATA: '${parser.read(range)}' (value: '${parser.read(range.value)}')`);\n  },\n  onOpenTagName(range, tagType) {\n    console.log(`Open Tag: '${parser.read(range)}' (type: ${TagType[tagType]})`);\n  },\n  onCloseTagName(range, tagType) {\n    console.log(`Close Tag: '${parser.read(range)}' (type: ${TagType[tagType]})`);\n  }\n});\n\nparser.parse(htmlCode);","lang":"typescript","description":"This example demonstrates how to create a parser instance and register handlers for various parsing events, including text, placeholders, comments, CDATA sections, and tag names. It showcases how to read the raw content of a parsed range and access additional metadata."},"warnings":[{"fix":"Thoroughly test parsing output after upgrading to ensure whitespace rendering aligns with expectations. Consult release notes for specific changes related to concise mode.","message":"Whitespace handling, particularly in 'concise mode' or 'concise blocks', has undergone multiple refinements and fixes across various patch and minor releases within the v5 series. Users heavily relying on precise whitespace in the parsed output of these modes should anticipate potential subtle changes when upgrading and conduct thorough regression testing.","severity":"gotcha","affected_versions":">=5.9.0"},{"fix":"Upgrade to the latest v5 patch release to benefit from fixes in JavaScript/TypeScript expression parsing. Ensure your embedded JavaScript adheres to standard syntax to avoid unexpected interpretations.","message":"The parser's robust JavaScript expression parsing capabilities (including TypeScript syntax) within HTML attributes and placeholders have received several bug fixes related to arrow functions and unary operators. Older v5 versions might misinterpret complex JavaScript/TypeScript syntax embedded directly in markup, leading to incorrect parse trees or errors.","severity":"gotcha","affected_versions":"<5.7.4"},{"fix":"Understand that `htmljs-parser` provides a stream of parsing events and `Range` objects. To get the actual string content of a range, use `parser.read(range)`. If a DOM-like structure is required, an additional layer of abstraction would need to be built on top of these events.","message":"This parser is a low-level tool, often used as a dependency for frameworks like Marko. Its API provides detailed ranges and event handlers rather than building a simple DOM-like tree. Users expecting a high-level DOM manipulation or querying API might find its event-driven, range-based output more granular and complex than anticipated.","severity":"gotcha","affected_versions":">=5.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Either configure your project to use ECMAScript Modules (ESM) by setting `\"type\": \"module\"` in `package.json` or by using `.mjs` file extensions, or use CommonJS `require()` syntax: `const { createParser } = require('htmljs-parser');`","cause":"Attempting to use `import` statements in a CommonJS (CJS) environment without proper transpilation or configuration.","error":"SyntaxError: Cannot use import statement outside a module"},{"fix":"Ensure that the `range` object passed to your event handlers is always valid before attempting to access its properties. Add checks like `if (range) { /* ... */ }` or ensure your parser configuration is robust.","cause":"Attempting to access properties of a `range` object that is `undefined` because a parsing event did not occur as expected, or a handler was called with an invalid range.","error":"TypeError: Cannot read properties of undefined (reading 'start')"},{"fix":"Review the specific patch and minor release notes for v5.9.0 and v5.10.x regarding 'concise mode' and whitespace handling. Update your parsing logic or expectations to accommodate these changes, or adjust the input HTML/concise blocks accordingly.","cause":"Changes in whitespace stripping logic in recent v5 minor releases, particularly for HTML in 'concise mode' or within template literals, can lead to subtle differences in the final parsed text nodes.","error":"Unexpected whitespace or missing content in parsed output for concise blocks."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":"","cli_version":null}