@dom-expressions/babel-plugin-jsx 0.50.0-next.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,254 @@
1
+ # babel-plugin-jsx-dom-expressions
2
+
3
+ ## 0.50.0-next.15
4
+
5
+ ### Patch Changes
6
+
7
+ - df03fb8: Move all packages under the `@dom-expressions` npm scope with new names:
8
+ - `dom-expressions` → `@dom-expressions/runtime`
9
+ - `babel-plugin-jsx-dom-expressions` → `@dom-expressions/babel-plugin-jsx`
10
+ - `jsx-dom-expressions-compiler` → `@dom-expressions/jsx-compiler`
11
+ - `hyper-dom-expressions` → `@dom-expressions/hyperscript`
12
+ - `tagged-jsx-dom-expressions` → `@dom-expressions/tagged-jsx`
13
+
14
+ The old unscoped names stop receiving `next` prereleases and remain in use
15
+ only by the Solid 1.x maintenance line published from `main`.
16
+
17
+ `lit-dom-expressions` is dropped from the prerelease line; it has been
18
+ superseded by `@dom-expressions/tagged-jsx`.
19
+
20
+ `@dom-expressions/jsx-compiler` now distributes prebuilt native binaries
21
+ through per-platform packages (`@dom-expressions/jsx-compiler-darwin-x64`,
22
+ `-darwin-arm64`, `-linux-x64-gnu`, `-linux-arm64-gnu`, `-win32-x64-msvc`)
23
+ resolved automatically via `optionalDependencies`, instead of shipping a
24
+ binary inside the main package.
25
+
26
+ ## 0.50.0-next.14
27
+
28
+ ### Patch Changes
29
+
30
+ - 9a64f1f: Preserve SSR child evaluation order for deferred hydratable insert slots.
31
+
32
+ ## 0.50.0-next.13
33
+
34
+ ### Patch Changes
35
+
36
+ - f1bcd5f: Stop giving special compiler handling to `style:foo` and `class:foo` JSX namespace syntax, and rename the static compiler marker from `@once` to `@static`. `style:foo` and `class:foo` now fall through to literal HTML attributes (e.g. `<div style:border="1px solid black">` emits `style:border` verbatim).
37
+
38
+ Internal optimizations still split `style={{...}}` into `setStyleProperty` calls and `class={{...}}` into `classList.toggle` calls.
39
+
40
+ - f17f7a1: Rename the generated event listener helper from `addEventListener` to `addEvent` so compiled browser bundles no longer introduce a binding that can shadow the native `window.addEventListener` method.
41
+
42
+ ## 0.50.0-next.12
43
+
44
+ ### Patch Changes
45
+
46
+ - Port relevant maintenance fixes from the stable branch. Add `omitAttributeSpacing` for strict template attribute spacing, and align `server.js`/`server.d.ts` with the current `client.d.ts` export surface so isomorphic imports continue to resolve on the server.
47
+
48
+ ## 0.50.0-next.11
49
+
50
+ ### Patch Changes
51
+
52
+ - d5cd499: Remove `on:` namespace event support from compiler, runtime, JSX types, and renderer packages.
53
+
54
+ ## 0.50.0-next.10
55
+
56
+ ### Patch Changes
57
+
58
+ - ba2c493: Update the JSX compiler source to TypeScript and refresh its generated output expectations for the current Babel and Rollup toolchain.
59
+
60
+ ## 0.50.0-next.9
61
+
62
+ ## 0.50.0-next.8
63
+
64
+ ## 0.50.0-next.7
65
+
66
+ ### Patch Changes
67
+
68
+ - 0bd165e: Preserve shared class tokens when diffing object keys that contain multiple class names.
69
+ Ensure class-method JSX captures `this` before lifted DOM setup statements run.
70
+ - e7831bd: Optimize class arrays with leading static class strings and a fixed-shape class object so the static classes are emitted in the template and dynamic object entries compile to class toggles.
71
+ - 10f3250: SSR: group contiguous attribute and `textContent` closures into a single
72
+ `_$ssrGroup(() => […], N)` call per element so the runtime can resolve
73
+ all `N` hole positions with one closure invocation instead of `N`. The
74
+ compiler walks each top-level element's `templateValues`, identifies
75
+ runs of `≥2` groupable entries (inserts/children break a run, preserving
76
+ child isolation), and replaces them with one grouped declarator repeated
77
+ `N` times in the `ssr(...)` argument list. `_$ssrGroup` tags the
78
+ function with `fn.$g = N` so `ssr()` can dispatch through a fast path
79
+ that's gated at the end of the typeof chain — non-function holes pay
80
+ nothing for the new branch.
81
+
82
+ For the async escalation path (group fn throws `NotReadyError`), every
83
+ retry slot for the group shares a module-scoped cache keyed on `fn`:
84
+ slot 0 evaluates and caches `arr` (success) or `err` (still-pending),
85
+ slots `1..N-1` short-circuit on the cached outcome, and the cache
86
+ invalidates when slot 0 re-fires next pass. Net retry cost: 1 evaluation
87
+ per group per pass on either outcome — `N²` → `N` on success, `N²` → `1`
88
+ on failure — with no per-state bookkeeping.
89
+
90
+ Bench: `+15%` on `search-results` (heavy attribute usage), neutral on
91
+ `color-picker` (no qualifying groups). Hydration ids are unaffected:
92
+ attribute/textContent expressions never allocate ids, and inserts (which
93
+ do) stay outside groups by construction.
94
+
95
+ - 3574228: SSR rendering performance pass.
96
+
97
+ **Runtime (`dom-expressions`):**
98
+ - Inline hole resolution in `ssr()`. Switch from a `(t, ...nodes)` rest
99
+ parameter to an `arguments` walk, eliminating the per-call holes-array
100
+ allocation. Inline `string`/`number`/`null`/`boolean` fast paths skip
101
+ `tryResolveString` for the typical "all-static-after-eval" hole shape; only
102
+ the heavy path (async escalation) materializes the `{ t, h, p }` result.
103
+ - Single forward-pass `escape()`. The previous implementation walked the
104
+ string twice in the hot path (`indexOf(delim)` + `indexOf("&")` upfront
105
+ then early-exit on the no-hit case). Replaced with a `charCodeAt` loop
106
+ that bails after one pass for clean strings (the common case), and
107
+ resumes the slow path from the first hit so the clean prefix isn't
108
+ re-scanned.
109
+ - Remove the `ssrRunInScope` public export. The function had been a true
110
+ pass-through identity (`fn => fn`) since owner-capture moved into
111
+ `tryResolveString`'s `NotReadyError` handler, and the compiler stopped
112
+ emitting it. With no internal callers and no behavior, the export was
113
+ dead surface area. User code that called it can drop the wrap (it was a
114
+ no-op) or replicate the original deferred-callback owner-capture intent
115
+ in two lines with `getOwner()` + `runWithOwner()`.
116
+
117
+ **Compiler (`babel-plugin-jsx-dom-expressions`):**
118
+ - IIFE elision in statement-position JSX. When `<jsx/>` is the argument of
119
+ a `return` or the initializer of a `const` (the overwhelmingly common
120
+ shapes), the surrounding IIFE is removed and the body lifts to flat
121
+ statements before the parent. Saves one closure allocation + one
122
+ function-call frame per render. Applies to `dom`, `ssr`, and `universal`
123
+ emissions; expression-position JSX (ternary branches, array elements,
124
+ function args) keeps the IIFE since lifting would change observable
125
+ evaluation semantics.
126
+ - SSR templates emit hoisted `var` declarations for dynamic-expression temp
127
+ vars instead of wrapping the whole thing in an IIFE. In statement
128
+ position the declarations precede the `ssr(...)` call; in expression
129
+ position they hoist to the enclosing function scope and the
130
+ assignment + call become a comma sequence expression.
131
+ - Drop `ssrRunInScope` emission around dynamic SSR expressions. The
132
+ temp-var hoist stays — it's a V8 IC-stability tactic (keeps the `ssr()`
133
+ call site specialized on `Identifier` argument shapes), not an
134
+ evaluation-order requirement. Ordering is preserved by JS left-to-right
135
+ semantics.
136
+ - Drop `createComponent` wrap on SSR component invocations. The SSR
137
+ runtime's `createComponent` is `Comp(props || {})`; the compiler always
138
+ emits a real `props` object, so the `|| {}` fallback never fires. Inline
139
+ to a direct `Comp(props)` call. DOM / dev modes keep the wrapper since
140
+ it does real work (`untrack`, dev metadata).
141
+
142
+ Net effect on representative SSR shapes (color-picker, search-results) is
143
+ fewer allocations per render and a flatter call graph through the hot path.
144
+
145
+ - 6ae1a40: Replace the `wrapDynamics` previous-value default-object initializer with optional chaining for both DOM and universal generators. The combined-effect arrow now takes `(_v$, _p$) => …` and reads `_p$?.<n>` instead of receiving an `_p$ = { 0: undefined, 1: undefined, … }` defaulted object literal. Removes a per-render-effect setup allocation, shrinks compiled output, and matches the shape used elsewhere in the runtime. The DOM generator special-cases `textContent` (`!_p$ || a !== _p$.a`) to keep the first-run write semantics.
146
+
147
+ ## 0.50.0-next.6
148
+
149
+ ## 0.50.0-next.5
150
+
151
+ ## 0.50.0-next.4
152
+
153
+ ## 0.50.0-next.3
154
+
155
+ ### Patch Changes
156
+
157
+ - 4dae801: Normalize the `repository` field in every package to the standard npm
158
+ convention: a `git+https://github.com/ryansolid/dom-expressions.git` URL
159
+ with a `directory` pointing at the package within the monorepo. Restores
160
+ "View source" / "Open in repo" links on the npm registry and unblocks
161
+ tooling that resolves source from package metadata.
162
+ - 1cc342c: Unify the compiler's void-element list with the runtime's `VoidElements` set in `dom-expressions/src/constants`. The compiler previously kept its own array (`src/VoidElements.ts`) that still contained the long-deprecated `keygen` and `menuitem` tags. Both have been removed from the HTML standard and are no longer parsed as void by modern browsers, so the compiler now emits closing tags for them — which is the correct behaviour in current browsers and was a latent bug otherwise. All other void elements are unaffected.
163
+
164
+ ## 0.50.0-next.2
165
+
166
+ ### Patch Changes
167
+
168
+ - 4d14c82: Fix single-dynamic attribute accessors being silently invoked with the
169
+ previous value. Given `<div style={source()} />`, the compiler previously
170
+ emitted `effect(source, (v, p) => style(el, v, p))`, which causes the
171
+ reactive core to call `source(p)` — leaking `prev` into a user-authored
172
+ accessor that the source expression wrote as a zero-arg call. Polymorphic
173
+ accessors (e.g. atom-style signals) would observe an unexpected argument
174
+ and misbehave.
175
+
176
+ The compute position now emits `() => source()` so the user's call shape
177
+ is preserved. The prior optimization of unwrapping an IIFE
178
+ (`(() => x)()` → `() => x`) is retained since IIFEs are zero-arg and
179
+ cannot leak `prev`.
180
+
181
+ Fixes #510.
182
+
183
+ - 39c207c: Fix a SyntaxError when an element has 222+ merged dynamic attributes
184
+ (solidjs/solid#2682). The internal identifier generator produced `in` at
185
+ index 221, and since these identifiers are emitted as object shorthand
186
+ destructuring bindings, the resulting `({ …, in }) => …` could not be parsed.
187
+ `getNumberedId` now shifts past any natural index that would encode to a JS
188
+ reserved word, keeping the mapping injective and the output at 2 characters
189
+ for all practical dynamic counts.
190
+ - 03da8a5: Fix SSR escaping gaps reachable from JSX, and tighten the compiler so
191
+ redundant runtime `escape` calls drop out of the output.
192
+
193
+ Security fixes:
194
+ - `ssrStyle` and `ssrClassName` now attribute-escape object keys, not
195
+ just values. Previously a user-controlled key in `<div style={{…}} />`
196
+ or `<div class={{…}} />` could break out of the surrounding attribute.
197
+ - Dynamic fragment-child expressions (`<>{state.text}</>`) now compile
198
+ to `_$memo(() => _$escape(expr))`. Element-child expressions already
199
+ escaped via `escapeExpression`; fragment children reached SSR through
200
+ a separate path and were concatenated raw.
201
+ - Computed-key object styles (`style={{ [k]: v }}`) escape the key at
202
+ compile time.
203
+
204
+ Compiler alignment:
205
+ - SSR now matches DOM in rejecting fragments placed directly inside an
206
+ element: `<div><>…</></div>` is a compile error in both renderers.
207
+ Fragments reached via conditionals (`<div>{cond && <>…</>}</div>`)
208
+ remain legal.
209
+
210
+ Compiler optimizations:
211
+ - `escapeExpression` drops the outer `_$escape` wrap on a `JSXFragment`
212
+ when its single significant child is either a dynamic expression
213
+ (compiles to a memoized accessor function, `escape(fn)` is a no-op)
214
+ or a native element (compiles to an `_$ssr(…)` SSR node object,
215
+ `escape(object)` is a no-op). This turns
216
+ `cond && _$escape(_$memo(() => _$escape(state.text)))` into
217
+ `cond && _$memo(() => _$escape(state.text))`, and
218
+ `cond && _$escape(_$ssr(_tmpl$N))` into `cond && _$ssr(_tmpl$N)`.
219
+
220
+ SSR fixtures for `components`, `conditionalExpressions`, `fragments`,
221
+ and `attributeExpressions` regenerate. Each security fix has a JSX
222
+ round-trip test in `packages/dom-expressions/test/ssr/jsx.spec.jsx`
223
+ that feeds hostile input through `renderToString`.
224
+
225
+ - 305d9ce: - SSR: Duplicate attributes in JSX without spreads are now deduplicated —
226
+ `<div class="a" class="b" />` correctly renders as `<div class="b" />`
227
+ (last-wins), matching client behavior. Previously the compiler kept both
228
+ attributes in the output.
229
+ - Client: `setAttributeNS` / `removeAttributeNS` now use matching names when
230
+ clearing namespaced attributes (e.g. `xlink:href`). Previously removal could
231
+ leave the attribute in place because it used the local name while the set
232
+ used the qualified name.
233
+ - Expanded test coverage across all four packages; no other behavior changes.
234
+
235
+ ## 0.50.0-next.1
236
+
237
+ ### Patch Changes
238
+
239
+ - ee365e0: - `insert()` accepts an optional 5th `options` argument that is forwarded to the
240
+ internal `effect()` call, letting callers (e.g. Solid's `render()`) opt into
241
+ transition-aware initial mounts without otherwise changing `insert`'s
242
+ behavior.
243
+ - SSR: `$dflj(ids)` now materializes every id in the list in a single call
244
+ instead of stopping after the first successful `$dfl`. Callers pass only the
245
+ keys they intend to materialize, which simplifies the primitive and composes
246
+ cleanly for bulk-uncollapse cases (e.g. a group activation revealing several
247
+ held fallbacks at once).
248
+ - SSR: Fix cascading async root holes in the streaming shell. When an inner
249
+ Loading boundary resolved its first chunk while the outer shell was still
250
+ pending, `flushEnd` could call `serializer.flush()` before `doShell()` had
251
+ written the root `_assets` module map, causing seroval to silently drop the
252
+ writes and client hydration to fail with "module was not preloaded". Root
253
+ asset serialization is now memoized and gated on both paths.
254
+ - Type formatting cleanup in `jsx-properties.d.ts`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018-2019 Ryan Carniato
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,301 @@
1
+ # Babel Plugin JSX DOM Expressions
2
+
3
+ [![Build Status](https://github.com/ryansolid/dom-expressions/workflows/DOMExpressions%20CI/badge.svg)](https://github.com/ryansolid/dom-expressions/actions/workflows/main-ci.yml)
4
+ [![NPM Version](https://img.shields.io/npm/v/@dom-expressions/babel-plugin-jsx.svg?style=flat)](https://www.npmjs.com/package/@dom-expressions/babel-plugin-jsx)
5
+ ![](https://img.shields.io/npm/dt/@dom-expressions/babel-plugin-jsx.svg?style=flat)
6
+ [![Gitter](https://img.shields.io/gitter/room/dom-expressions/community)](https://gitter.im/dom-expressions/community)
7
+
8
+ This package is a JSX compiler built for [DOM Expressions](https://github.com/ryansolid/dom-expressions) to provide a general JSX to DOM transformation for reactive libraries that do fine grained change detection. This package aims to convert JSX statements to native DOM statements and wrap JSX expressions with functions that can be implemented with the library of your choice. Sort of like a JSX to Hyperscript for fine change detection.
9
+
10
+ ## Features
11
+
12
+ This plugin treats all lowercase tags as html elements and mixed cased tags as Custom Functions. This enables breaking up your view into components. This library supports Web Component Custom Elements spec. Support for common camelcase event handlers like React, dom safe attributes like class and for, a simple ref property, and parsing of objects for style, and class properties.
13
+
14
+ In general JSX Attribute Expressions are treated as attributes by default, with exception custom elements that will to properties and special fields like `class` and `style`. Plain string attributes will be treated as attributes.
15
+
16
+ This library uses a heuristic to decide whether JSX expressions need dynamic wrapping based on whether they contain function calls or property access. Simple literals and variable expressions won't be wrapped.
17
+
18
+ ## Example
19
+
20
+ ```jsx
21
+ const view = ({ item }) => {
22
+ const itemId = item.id;
23
+ return (
24
+ <tr class={itemId === selected() ? "danger" : ""}>
25
+ <td class="col-md-1">{itemId}</td>
26
+ <td class="col-md-4">
27
+ <a onClick={e => select(item, e)}>{item.label}</a>
28
+ </td>
29
+ <td class="col-md-1">
30
+ <a onClick={e => del(item, e)}>
31
+ <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
32
+ </a>
33
+ </td>
34
+ <td class="col-md-6"></td>
35
+ </tr>
36
+ );
37
+ };
38
+ ```
39
+
40
+ Compiles to:
41
+
42
+ ```jsx
43
+ import { template as _$template } from "dom";
44
+ import { delegateEvents as _$delegateEvents } from "dom";
45
+ import { className as _$className } from "dom";
46
+ import { effect as _$effect } from "dom";
47
+ import { insert as _$insert } from "dom";
48
+
49
+ const _tmpl$ = /*#__PURE__*/ _$template(
50
+ `<tr><td class="col-md-1"></td><td class="col-md-4"><a></a></td><td class="col-md-1"><a><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></a></td><td class="col-md-6"></td></tr>`,
51
+ 16
52
+ );
53
+ const view = ({ item }) => {
54
+ const itemId = item.id;
55
+ return (() => {
56
+ const _el$ = _tmpl$.cloneNode(true),
57
+ _el$2 = _el$.firstChild,
58
+ _el$3 = _el$2.nextSibling,
59
+ _el$4 = _el$3.firstChild,
60
+ _el$5 = _el$3.nextSibling,
61
+ _el$6 = _el$5.firstChild;
62
+ _$insert(_el$2, itemId);
63
+ _el$4.$$click = e => select(item, e);
64
+ _$insert(_el$4, () => item.label);
65
+ _el$6.$$click = e => del(item, e);
66
+ _$effect(
67
+ () => selected(),
68
+ _v$ => _$className(_el$, itemId === _v$ ? "danger" : "")
69
+ );
70
+ return _el$;
71
+ })();
72
+ };
73
+ _$delegateEvents(["click"]);
74
+ ```
75
+
76
+ The use of cloneNode improves repeat insert performance and precompilation reduces the number of references to the minimal traversal path. This is a basic example which doesn't leverage event delegation or any of the more advanced features described below.
77
+
78
+ ## Example Implementations
79
+
80
+ - [Solid](https://github.com/ryansolid/solid): A declarative JavaScript library for building user interfaces.
81
+ - [ko-jsx](https://github.com/ryansolid/ko-jsx): Knockout JS with JSX rendering.
82
+ - [mobx-jsx](https://github.com/ryansolid/mobx-jsx): Ever wondered how much more performant MobX is without React? A lot.
83
+
84
+ ## Plugin Options
85
+
86
+ ### moduleName
87
+
88
+ - Type: `string`
89
+ - Required: Yes
90
+
91
+ The name of the runtime module to import the methods from.
92
+
93
+ ### generate
94
+
95
+ - Type: `'dom' | 'ssr'`
96
+ - Default: `'dom'`
97
+
98
+ The output mode of the compiler. Can be "dom"(default), "ssr". "dom" is standard output. "ssr" is for server side rendering of strings.
99
+
100
+ ### hydratable
101
+
102
+ - Type: `boolean`
103
+ - Default: `false`
104
+
105
+ Indicate whether the output should contain hydratable markers.
106
+
107
+ ### delegateEvents
108
+
109
+ - Type: `boolean`
110
+ - Default: `true`
111
+
112
+ Boolean to indicate whether to enable automatic event delegation on camelCase.
113
+
114
+ ### wrapConditionals
115
+
116
+ - Type: `boolean`
117
+ - Default: `true`
118
+
119
+ Boolean indicates whether smart conditional detection should be used. This optimizes simple boolean expressions and ternaries in JSX.
120
+
121
+ ### contextToCustomElements
122
+
123
+ - Type: `boolean`
124
+ - Default: `false`
125
+
126
+ Boolean indicates whether to set current render context on Custom Elements and slots. Useful for seemless Context API with Web Components.
127
+
128
+ ### builtIns
129
+
130
+ - Type: `boolean`
131
+ - Default: `string[]`
132
+
133
+ Array of Component exports from module, that aren't included by default with the library. This plugin will automatically import them if it comes across them in the JSX.
134
+
135
+ ### effectWrapper
136
+
137
+ - Type: `string`
138
+ - Default: `effect`
139
+
140
+ This plugin leverages a heuristic for reactive wrapping and lazy evaluation of JSX expressions. This option indicates the reactive wrapper function name (`effect`), defaults to `effect`.
141
+
142
+ ### staticMarker
143
+
144
+ - Type: `string`
145
+ - Default: `@static`
146
+
147
+ Advanced compiler assertion marker. When an expression starts with this comment, the compiler treats it as static and does not wrap it in an `effect` call.
148
+
149
+ This is not a reactivity primitive and should not be used to read reactive values once. Only use it when you can prove the expression is non-reactive for the lifetime of the rendered element, and the compiler heuristic cannot infer that on its own.
150
+
151
+ ### memoWrapper
152
+
153
+ - Type: `string`
154
+ - Default: `memo`
155
+
156
+ Memos let you efficiently use a derived value in many reactive computations. This option indicates the memo function name, defaults to `memo`.
157
+
158
+ ### validate
159
+
160
+ - Type: `boolean`
161
+ - Default: `true`
162
+
163
+ Checks for properly formed HTML by checking for elements that would not be allowed in certain parent elements. This validation isn't complete but includes places where browser would "correct" it and break the DOM walks.
164
+
165
+ ### omitNestedClosingTags
166
+
167
+ - Type: `boolean`
168
+ - Default: `false`
169
+
170
+ Removes unnecessary closing tags from the template output. This may not work in all browser-like environments the same. The solution has been tested again Chrome/Edge/Firefox/Safari.
171
+
172
+ ### omitLastClosingTag
173
+
174
+ - Type: `boolean`
175
+ - Default: `true`
176
+
177
+ Removes tags from the template output if they have no closing parents and are the last element. This may not work in all browser-like environments the same. The solution has been tested again Chrome/Edge/Firefox/Safari.
178
+
179
+ ### omitQuotes
180
+
181
+ - Type: `boolean`
182
+ - Default: `true`
183
+
184
+ Removes quotes for html attributes when possible from the template output. This may not work in all browser-like environments the same. The solution has been tested again Chrome/Edge/Firefox/Safari.
185
+
186
+ ### omitAttributeSpacing
187
+
188
+ - Type: `boolean`
189
+ - Default: `true`
190
+
191
+ When `true`, quoted attributes may omit the space before the next attribute. Set this to `false` to emit strictly spaced attributes for stricter HTML/SVG parsers.
192
+
193
+ ### requireImportSource
194
+
195
+ - Type: `string | false`
196
+ - Default: `false`
197
+
198
+ When set to a string value, this option restricts JSX transformation to only files that contain a specific JSX import source pragma comment. The plugin will only transform JSX in files that include a comment with `@jsxImportSource` followed by the specified value. If the comment is missing or specifies a different import source, the transformation is skipped for that file.
199
+ Example usage:
200
+
201
+ ```jsx
202
+ // In babel configuration:
203
+ {
204
+ plugins: [
205
+ [
206
+ "jsx-dom-expressions",
207
+ {
208
+ requireImportSource: "r-dom"
209
+ }
210
+ ]
211
+ ];
212
+ }
213
+ // In your component file:
214
+ /** @jsxImportSource r-dom */
215
+ const template = <div>Hello</div>;
216
+ ```
217
+
218
+ ### inlineStyles
219
+
220
+ - Type: `boolean`
221
+ - Default: `true`
222
+
223
+ Style attributes in templates are inlined when possible: value is a string, `Record<string, string>`, etc. Inlining styles may not be desired when using strong CSP configurations. Disabling `inlineStyles` will cause all of the style definitions to be set at runtime.
224
+
225
+ ## Special Binding
226
+
227
+ ### ref
228
+
229
+ This binding will assign the variable you pass to it with the DOM element or if a function will call it with the element.
230
+
231
+ ```jsx
232
+ const Child = props => <div ref={props.ref} />;
233
+
234
+ const Parent = () => {
235
+ let ref;
236
+ return <Child ref={ref} />;
237
+ };
238
+ ```
239
+
240
+ ### on(eventName)
241
+
242
+ CamelCase event attributes such as `onClick` are treated as event handlers expecting a function. The compiler will delegate events where possible (events that bubble or can be composed), otherwise it falls back to Level 1 spec `on_____` events.
243
+
244
+ If you wish to make it into a Bound Event, you can bind a value to your delegated event by passing an array handler instead and the second argument will be passed to your event handler as the first argument (the event will be second).
245
+
246
+ ```jsx
247
+ function handler(itemId, e) {
248
+ /*...*/
249
+ }
250
+
251
+ <ul>
252
+ {list().map(item => (
253
+ <li onClick={[handler, item.id]} />
254
+ ))}
255
+ </ul>;
256
+ ```
257
+
258
+ This delegation solution works with Web Components and the Shadow DOM as well if the events are composed. That limits the list to custom events and most UA UI events like onClick, onKeyUp, onKeyDown, onDblClick, onInput, onMouseDown, onMouseUp, etc..
259
+ Important:
260
+
261
+ - To allow for casing to work, custom delegated events should follow the all lowercase convention of native events. Use a ref/directive that calls `addEventListener` when you need native listener options or custom event casing.
262
+
263
+ - Event delegates are owned by render roots and are removed when those roots dispose.
264
+
265
+ ### ... (spreads)
266
+
267
+ Spreads let you pass multiple props at once:
268
+
269
+ ```jsx
270
+ <div {...props} />
271
+ ```
272
+
273
+ Keep in mind given the independent nature of binding updates there is no guarantee of order using spreads at this time. It's under consideration.
274
+
275
+ ## Components
276
+
277
+ Components are just Capital Cased tags. Instead of wrapping with computation dynamic props will just be getter accessors. \* Remember property access triggers so don't destructure outside of computations unless you intend the content to be static.
278
+
279
+ ```jsx
280
+ const MyComp = props => {
281
+ const staticProp = props.other;
282
+ return (
283
+ <>
284
+ <div>{props.param}</div>
285
+ <div>{staticProp}</div>
286
+ </>
287
+ );
288
+ };
289
+
290
+ <MyComp param={dynamic()} other={static} />;
291
+ ```
292
+
293
+ Components may have children. This is available as props.children. It may be a node, a function, or a string, or an array of the aforementioned. Non-expression children like DOM nodes are set to evaluate lazily (upon access by default).
294
+
295
+ ## Fragments
296
+
297
+ This plugin also supports JSX Fragments with `<></>` notation. These will be compiled to arrays. The fragment syntax provides the convenience of being able to use the template syntax to wrap expressions.
298
+
299
+ ## Acknowledgements
300
+
301
+ The concept of using JSX to DOM instead of html strings and context based binding usually found in these libraries was inspired greatly by [Surplus](https://github.com/adamhaile/surplus).