Improve runtime error handling for missing close tags
Consider this sample code, which accidentally omits a closing tag.
import htm from 'https://unpkg.com/htm?module'
const h = (type, props, ...children) => ({type, props, children});
const html = htm.bind(h)
console.log(JSON.stringify(html`<h1>Hello, world!`));
In this case, the user intended to include a closing tag </h1>, and so the user's desired logged result is {"type":"h1","props":null,"children":["Hello, world!"]}
Actual: ["h1","Hello, world!"] The element name is incorrectly handled as a text node.
Expected: Throw an exception.
Btw innerHTML parser does not throw errors and silently returns wrongly parsed markup.
Implementing validation in parser would be size overhead.
Maybe linter package?
I think it's worth investigating the runtime size overhead. It might not be that much.
I filed a separate bug that the transpiler also silently ignores errors; that's definitely a bad thing. The transpiler should use as many bytes as it needs to ensure correctness and report clear errors. (Plus, the transpiler itself can be a linter with babel-eslint.)
investigating the runtime size overhead
Ok, some possible error cases then.
html`<a`
html`<a${'b'}>`
html`<a${'b'}`
html`<${'b'}a>`
html`<a></${''}>`
html`<a><${''}/>`
html`<a></`
html`<a ${'b'}></a>`
html`<a a${'b'}></a>`
html`<a "a${'b'}"></a>`
html`<a <!--"a${'b'}"></a>`
...
That list grows to hundreds - there are too many combinations of modes ('"quotes, comments, attrib names, attrib values, spread, fields, closing tag, tag/text, fragment). I am pretty sure there's no silver bullet, the parser is super minimalistic. Maybe transpiler indeed?
It's not possible to implement runtime error checking in a way that represents a reasonable size tradeoff. This is particularly true because 100% of the classes of error that would be caught are also the classes of error that can be detected via static analysis.
Some solutions:
- compile from JSX (enables full linting & type safety)
- write an ESLint plugin for HTM
- Surprisingly, nobody has done this yet. I just threw something together to start from but don't have the time to dedicate to it right now.
- Lobby for first-class Tagged Template DSL support in TypeScript and Babel
this is probably a duplicate of #56 & #122