kerfjs 3.0.0-beta.1 → 4.0.0
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 +29 -4
- package/README.md +8 -6
- package/ai/cursorrules +5 -3
- package/ai/manifest.json +5 -5
- package/ai/skill.md +5 -3
- package/dist/{chunk-JVVU2RQO.js → chunk-JXAR5J54.js} +21 -9
- package/dist/chunk-JXAR5J54.js.map +1 -0
- package/dist/html.js +1 -1
- package/dist/index.js +2 -2
- package/dist/jsx-runtime.d.ts +338 -34
- package/dist/jsx-runtime.js +1 -1
- package/llms.txt +3 -2
- package/package.json +17 -3
- package/dist/chunk-JVVU2RQO.js.map +0 -1
package/dist/jsx-runtime.d.ts
CHANGED
|
@@ -33,6 +33,124 @@ import { B as Binding } from './bindings-CYwoJpQb.js';
|
|
|
33
33
|
* undefined / `SafeHtml`. Event-handler props (`onClick` etc.) are
|
|
34
34
|
* deliberately omitted: kerf renders to strings, so inline handlers do
|
|
35
35
|
* nothing. Use `delegate()` / `delegateCapture()` instead.
|
|
36
|
+
*
|
|
37
|
+
* ---
|
|
38
|
+
*
|
|
39
|
+
* ## Provenance — where these types come from
|
|
40
|
+
*
|
|
41
|
+
* Attribute names, value sets, and per-element membership are taken from the
|
|
42
|
+
* **WHATWG HTML Living Standard** (and **SVG 2** for the SVG interfaces), with
|
|
43
|
+
* MDN used only as a readable index into them. They are NOT derived from
|
|
44
|
+
* `@types/react`, `lib.dom.d.ts`, or any other framework's table — those model
|
|
45
|
+
* a *property* surface (`HTMLElement.draggable: boolean`), and kerf emits
|
|
46
|
+
* *content attributes* into an HTML string, which is a different contract in
|
|
47
|
+
* exactly the places that bite (see the enumerated-attribute rule below).
|
|
48
|
+
*
|
|
49
|
+
* Coverage is deliberately focused rather than exhaustive: the ~100 most-used
|
|
50
|
+
* elements and their commonly-authored attributes. A missing attribute is a
|
|
51
|
+
* gap to fill, not a statement that it's invalid — extend via declaration
|
|
52
|
+
* merging (above) until it lands here.
|
|
53
|
+
*
|
|
54
|
+
* ## The rule that governs every value type
|
|
55
|
+
*
|
|
56
|
+
* `boolean` in an attribute type means **HTML boolean attribute** — one whose
|
|
57
|
+
* *presence* is the whole signal. `foo={true}` renders ` foo` and `foo={false}`
|
|
58
|
+
* renders nothing, so only attributes with those exact semantics may accept a
|
|
59
|
+
* boolean.
|
|
60
|
+
*
|
|
61
|
+
* HTML's **enumerated** attributes look boolean but are not: they take the
|
|
62
|
+
* literal *strings* `"true"` / `"false"`, and their missing-value default is a
|
|
63
|
+
* third state. Typing one as `boolean` produces markup that silently means the
|
|
64
|
+
* opposite of what was written:
|
|
65
|
+
*
|
|
66
|
+
* - `draggable={true}` → `<div draggable>` → empty value is invalid for
|
|
67
|
+
* `draggable`, so the element falls to the **auto** state — which for a
|
|
68
|
+
* `<div>` means **not draggable**. The attribute that was supposed to turn
|
|
69
|
+
* dragging on turns nothing on.
|
|
70
|
+
* - `draggable={false}` → attribute omitted → **auto** again, and auto for
|
|
71
|
+
* `<img>` / `<a href>` is *draggable*. The disable never happens either.
|
|
72
|
+
* - `spellCheck={false}` / `contentEditable={false}` → omitted → the
|
|
73
|
+
* **inherit** default, not the false state. (Their `true` direction happens
|
|
74
|
+
* to work: the empty string is a spec keyword for the true state on those
|
|
75
|
+
* two, unlike `draggable`.)
|
|
76
|
+
*
|
|
77
|
+
* So these are typed as string literal unions and reject `boolean` outright.
|
|
78
|
+
* Six attributes have this shape; they do NOT all share one type, because the
|
|
79
|
+
* keywords differ — `EnumeratedBool` (`"true"`/`"false"`) covers `draggable`,
|
|
80
|
+
* `spellcheck` and `writingsuggestions`, `ContentEditableValue` adds
|
|
81
|
+
* `plaintext-only`, and `translate` (`"yes"`/`"no"`) and `autocorrect`
|
|
82
|
+
* (`"on"`/`"off"`) spell their keywords differently again. Grep `EnumeratedBool`
|
|
83
|
+
* for the largest group. The fix is at the type
|
|
84
|
+
* level rather than in the runtime on purpose: translating `{true}` →
|
|
85
|
+
* `="true"` would require the renderer to carry a list of every enumerated
|
|
86
|
+
* attribute in HTML, and any attribute *missing* from that list would silently
|
|
87
|
+
* regress to precisely this bug. A per-attribute type keeps the knowledge where
|
|
88
|
+
* the spec knowledge already lives and costs nothing at runtime. The tradeoff
|
|
89
|
+
* is a compile error on `draggable={true}` — which is the point.
|
|
90
|
+
*
|
|
91
|
+
* One residual hole this cannot close: a signal-valued attribute
|
|
92
|
+
* (`draggable={sig}`) is `ReadonlySignal<unknown>`, so a boolean inside it is
|
|
93
|
+
* invisible to the type system. Put the string in the signal: `signal('true')`.
|
|
94
|
+
*
|
|
95
|
+
* A third shape sits between the two and accepts `boolean | string`
|
|
96
|
+
* legitimately: **presence-or-value** attributes, where the presence carries
|
|
97
|
+
* the meaning and a value refines it. `download` is the clearest case — bare,
|
|
98
|
+
* it means "download this and let the server name the file"; with a value, the
|
|
99
|
+
* value is the filename; absent, it's ordinary navigation. `capture` on
|
|
100
|
+
* `<input type="file">` is the same shape (bare = the default capture device,
|
|
101
|
+
* `user`/`environment` pick one).
|
|
102
|
+
*
|
|
103
|
+
* The test that separates this shape from the enumerated one: ask what
|
|
104
|
+
* `{true}` and `{false}` each render, then what those markups MEAN. Here all
|
|
105
|
+
* three states are real and distinct, so both forms are typed. For `draggable`
|
|
106
|
+
* they collapse onto the same `auto` state, which is why `boolean` is rejected
|
|
107
|
+
* there.
|
|
108
|
+
*
|
|
109
|
+
* ## Deliberate deviations from the spec
|
|
110
|
+
*
|
|
111
|
+
* Each of these is a knowing departure, kept because removing it would cost
|
|
112
|
+
* more than it buys:
|
|
113
|
+
*
|
|
114
|
+
* - **Lowercase aliases** (`class`, `for`, `tabindex`, `autofocus`,
|
|
115
|
+
* `spellcheck`, `contenteditable`, `autocomplete`) sit alongside the
|
|
116
|
+
* camelCase forms. Both spellings are accepted because the migration docs
|
|
117
|
+
* tell incoming developers to write the real HTML name.
|
|
118
|
+
* - **`contentEditable="inherit"`** is accepted but is *not* a spec keyword.
|
|
119
|
+
* It lands on the inherit state only via the invalid-value default. Kept
|
|
120
|
+
* for React parity; omitting the attribute is the spec-correct way to
|
|
121
|
+
* inherit.
|
|
122
|
+
* - **`tabindex` / `autofocus` / `capture`** accept a widened value set
|
|
123
|
+
* (string ints, plain `boolean`) matching what the parser actually honors.
|
|
124
|
+
* - **`cellPadding` / `cellSpacing`** are obsolete presentational attributes,
|
|
125
|
+
* marked `@deprecated` rather than removed so legacy markup still compiles.
|
|
126
|
+
* - **`xlink:*`** attributes are deprecated in SVG 2 but still typed — real
|
|
127
|
+
* documents and icon sprites still carry them.
|
|
128
|
+
* - **`data-morph-skip` / `-skip-children` / `-preserve`** are kerf's own
|
|
129
|
+
* `data-*` attributes, valid HTML by the `data-*` rule.
|
|
130
|
+
* - **`<meta property>`** is Open Graph vocabulary, not an attribute in the
|
|
131
|
+
* HTML standard. Typed anyway because it is universal in real documents —
|
|
132
|
+
* every social-preview `<head>` carries `og:*` meta tags.
|
|
133
|
+
*
|
|
134
|
+
* Attributes that are *not* typed because they do nothing when rendered as
|
|
135
|
+
* markup: `value` / `defaultValue` on `<select>` and `<textarea>` (neither
|
|
136
|
+
* element has a `value` content attribute — a select's selection comes from
|
|
137
|
+
* `<option selected>`, a textarea's value is its child text), any `on*`
|
|
138
|
+
* handler prop (rejected at runtime — use `delegate()`), and the declarative
|
|
139
|
+
* shadow DOM attributes on `<template>` (`shadowrootmode` and its
|
|
140
|
+
* `shadowrootdelegatesfocus` / `shadowrootclonable` companions): the fragment
|
|
141
|
+
* parsing behind `innerHTML` — kerf's entire client render path — never
|
|
142
|
+
* instantiates declarative shadow roots (only the document parser and
|
|
143
|
+
* `setHTMLUnsafe` do), so through `mount()` the template would sit inert in
|
|
144
|
+
* the DOM instead of becoming a shadow root. Declaration-merge them if you
|
|
145
|
+
* emit full-document SSR strings, where the document parser does honor them.
|
|
146
|
+
*
|
|
147
|
+
* Attributes outside the Living Standard stay out even when browsers ship
|
|
148
|
+
* them: `<video disablepictureinpicture / disableremoteplayback>` live in
|
|
149
|
+
* separate W3C specs and only appear in video-player code, `<iframe
|
|
150
|
+
* credentialless>` is engine-specific (in the standard only as a COEP value,
|
|
151
|
+
* not an iframe attribute), and `<iframe allowpaymentrequest>` was removed
|
|
152
|
+
* from the standard outright. Declaration merging is the path for all of
|
|
153
|
+
* them.
|
|
36
154
|
*/
|
|
37
155
|
|
|
38
156
|
/**
|
|
@@ -44,6 +162,45 @@ import { B as Binding } from './bindings-CYwoJpQb.js';
|
|
|
44
162
|
type AttrValue = string | number | boolean | null | undefined | SafeHtml | ReadonlySignal<unknown>;
|
|
45
163
|
/** A typed-narrowing helper: `AttrLike<'a'|'b'>` accepts the literals plus the runtime fall-throughs. */
|
|
46
164
|
type AttrLike<T = string> = T | SafeHtml | null | undefined | ReadonlySignal<unknown>;
|
|
165
|
+
/**
|
|
166
|
+
* An HTML **enumerated** attribute whose keywords are the literal strings
|
|
167
|
+
* `"true"` / `"false"` — NOT a boolean attribute.
|
|
168
|
+
*
|
|
169
|
+
* This is the shape that has to be got right more than any other in this file,
|
|
170
|
+
* because getting it wrong is silent: omitting the attribute selects a third
|
|
171
|
+
* state (inherit, or auto), so `boolean` would render markup meaning something
|
|
172
|
+
* other than what was written. `draggable`, `spellcheck`, `contenteditable`,
|
|
173
|
+
* `translate`, `autocorrect`, and `writingsuggestions` are all this shape, and
|
|
174
|
+
* each was typed as a boolean at some point before being corrected.
|
|
175
|
+
*
|
|
176
|
+
* Naming it makes the classification greppable — `EnumeratedBool` answers
|
|
177
|
+
* "which attributes are in this family?" in one command, which is a question
|
|
178
|
+
* the docs repeatedly got wrong while it was six separate inline unions.
|
|
179
|
+
*
|
|
180
|
+
* The per-attribute JSDoc stays at the attribute: this alias says *what shape
|
|
181
|
+
* it is*, the attribute says *what omitting it means for that attribute*.
|
|
182
|
+
*/
|
|
183
|
+
type EnumeratedBool = AttrLike<'true' | 'false'>;
|
|
184
|
+
/**
|
|
185
|
+
* `contenteditable`'s value set — the enumerated-bool keywords plus
|
|
186
|
+
* `plaintext-only`, and `inherit`, which is NOT a spec keyword (it reaches the
|
|
187
|
+
* inherit state only via the invalid-value default; kept for React parity).
|
|
188
|
+
*/
|
|
189
|
+
type ContentEditableValue = AttrLike<'true' | 'false' | 'inherit' | 'plaintext-only'>;
|
|
190
|
+
/** Resource-loading priority hint: `<img>` / `<link>` / `<script>`. */
|
|
191
|
+
type FetchPriority = AttrLike<'high' | 'low' | 'auto'>;
|
|
192
|
+
/**
|
|
193
|
+
* The `blocking` token list. `render` is the only token the standard defines
|
|
194
|
+
* today — a union rather than a plain string so a typo fails to compile, and a
|
|
195
|
+
* one-line edit when the set grows.
|
|
196
|
+
*/
|
|
197
|
+
type BlockingToken = AttrLike<'render'>;
|
|
198
|
+
/** Lazy-loading behavior: `<img>` / `<iframe>`. */
|
|
199
|
+
type LoadingBehavior = AttrLike<'eager' | 'lazy'>;
|
|
200
|
+
/** Form submission method, on `<form method>` and the `form*` overrides. */
|
|
201
|
+
type FormMethod = AttrLike<'get' | 'post' | 'dialog'>;
|
|
202
|
+
/** What a popover invoker does to its target: `<button>` / `<input>`. */
|
|
203
|
+
type PopoverTargetAction = AttrLike<'toggle' | 'show' | 'hide'>;
|
|
47
204
|
/**
|
|
48
205
|
* `data-*` and `aria-*` index signatures. Applied via `KerfBaseAttrs` so
|
|
49
206
|
* every typed element accepts them without per-element enumeration.
|
|
@@ -68,26 +225,48 @@ interface KerfBaseAttrs extends DataAriaAttrs {
|
|
|
68
225
|
title?: AttrLike;
|
|
69
226
|
lang?: AttrLike;
|
|
70
227
|
dir?: AttrLike<'ltr' | 'rtl' | 'auto'>;
|
|
71
|
-
hidden?: AttrLike<boolean>;
|
|
72
|
-
draggable?: AttrLike<boolean>;
|
|
73
|
-
contentEditable?: AttrLike<boolean | 'true' | 'false' | 'inherit' | 'plaintext-only'>;
|
|
74
228
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
229
|
+
* A genuine HTML boolean attribute, so `hidden={true}` → ` hidden` is
|
|
230
|
+
* correct. `'until-found'` is the one non-boolean keyword: the element is
|
|
231
|
+
* hidden but still findable by find-in-page and fragment navigation, which
|
|
232
|
+
* reveals it.
|
|
233
|
+
*/
|
|
234
|
+
hidden?: AttrLike<boolean | 'until-found'>;
|
|
235
|
+
/**
|
|
236
|
+
* Enumerated, NOT boolean — write `draggable="true"` / `draggable="false"`.
|
|
237
|
+
* `boolean` is rejected because both directions would render the wrong
|
|
238
|
+
* state: `{true}` emits an empty value (invalid → the **auto** state, which
|
|
239
|
+
* for most elements means *not* draggable) and `{false}` omits the attribute
|
|
240
|
+
* (auto again — and auto for `<img>` / `<a href>` is *draggable*). Omit the
|
|
241
|
+
* attribute to mean auto. See the enumerated-attribute rule in this file's
|
|
242
|
+
* header.
|
|
79
243
|
*/
|
|
80
|
-
|
|
244
|
+
draggable?: EnumeratedBool;
|
|
245
|
+
/**
|
|
246
|
+
* Enumerated, NOT boolean — write `contentEditable="true"` / `="false"`.
|
|
247
|
+
* `contentEditable={false}` would omit the attribute, which means *inherit*,
|
|
248
|
+
* not false — so a child of an editable region would stay editable.
|
|
249
|
+
*
|
|
250
|
+
* `'inherit'` is not a spec keyword; it reaches the inherit state only
|
|
251
|
+
* through the invalid-value default. Accepted for React parity, but omitting
|
|
252
|
+
* the attribute is the spec-correct way to inherit.
|
|
253
|
+
*/
|
|
254
|
+
contentEditable?: ContentEditableValue;
|
|
255
|
+
/**
|
|
256
|
+
* KF-191 — lowercase HTML form accepted alongside `contentEditable` (same
|
|
257
|
+
* shape as `class` / `tabindex` / `autofocus` / `spellcheck`), with the same
|
|
258
|
+
* enumerated value set.
|
|
259
|
+
*/
|
|
260
|
+
contenteditable?: ContentEditableValue;
|
|
81
261
|
inputMode?: AttrLike<'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search'>;
|
|
82
|
-
spellCheck?: AttrLike<boolean>;
|
|
83
262
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* the
|
|
87
|
-
* attribute, and an HTML-savvy developer typing the lowercase form
|
|
88
|
-
* will naturally reach for `spellcheck="false"`.
|
|
263
|
+
* Enumerated, NOT boolean — write `spellCheck="false"` to turn spellchecking
|
|
264
|
+
* off. `spellCheck={false}` would omit the attribute, which means *inherit
|
|
265
|
+
* the default*, not off; the disable would silently never happen.
|
|
89
266
|
*/
|
|
90
|
-
|
|
267
|
+
spellCheck?: EnumeratedBool;
|
|
268
|
+
/** KF-183 — lowercase HTML form accepted alongside `spellCheck`. */
|
|
269
|
+
spellcheck?: EnumeratedBool;
|
|
91
270
|
tabIndex?: AttrLike<number>;
|
|
92
271
|
/**
|
|
93
272
|
* KF-191 — lowercase HTML form accepted alongside `tabIndex`. Widened to
|
|
@@ -102,14 +281,63 @@ interface KerfBaseAttrs extends DataAriaAttrs {
|
|
|
102
281
|
autoCapitalize?: AttrLike<'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters'>;
|
|
103
282
|
autoFocus?: AttrLike<boolean>;
|
|
104
283
|
/**
|
|
105
|
-
* KF-191 — lowercase HTML form accepted alongside `autoFocus`.
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
284
|
+
* KF-191 — lowercase HTML form accepted alongside `autoFocus`.
|
|
285
|
+
*
|
|
286
|
+
* A real boolean attribute, so only `boolean` is accepted. The string forms
|
|
287
|
+
* are deliberately NOT allowed: `autofocus="false"` is *present*, and a
|
|
288
|
+
* present boolean attribute is true regardless of its value — the spelling
|
|
289
|
+
* that reads like "off" turns autofocus **on**. Use `{false}` or omit it.
|
|
110
290
|
*/
|
|
111
|
-
autofocus?: AttrLike<boolean
|
|
291
|
+
autofocus?: AttrLike<boolean>;
|
|
112
292
|
accessKey?: AttrLike;
|
|
293
|
+
/**
|
|
294
|
+
* A genuine HTML boolean attribute (the subtree becomes non-interactive and
|
|
295
|
+
* invisible to assistive tech), so `inert={true}` → ` inert` is correct.
|
|
296
|
+
*/
|
|
297
|
+
inert?: AttrLike<boolean>;
|
|
298
|
+
/**
|
|
299
|
+
* Enumerated: `auto` / `hint` / `manual` — but the boolean forms are ALSO
|
|
300
|
+
* accepted, because both land on spec states, unlike `draggable`:
|
|
301
|
+
* `popover={true}` renders the bare attribute, whose empty value is a spec
|
|
302
|
+
* keyword for the **auto** state (`<div popover>` is the canonical
|
|
303
|
+
* spelling), and `popover={false}` omits it — the not-a-popover state.
|
|
304
|
+
*/
|
|
305
|
+
popover?: AttrLike<'auto' | 'hint' | 'manual' | boolean>;
|
|
306
|
+
/** CSP nonce. A global attribute — most useful on `<script>` / `<style>` / `<link>`. */
|
|
307
|
+
nonce?: AttrLike;
|
|
308
|
+
/** Shadow-DOM part name(s) this element exposes for `::part()` styling. */
|
|
309
|
+
part?: AttrLike;
|
|
310
|
+
/** All-lowercase in HTML (`exportparts`) — there is no camelCase form to alias. */
|
|
311
|
+
exportparts?: AttrLike;
|
|
312
|
+
enterKeyHint?: AttrLike<'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send'>;
|
|
313
|
+
/**
|
|
314
|
+
* Enumerated, NOT boolean — write `translate="yes"` / `translate="no"`.
|
|
315
|
+
* `translate={false}` would omit the attribute, which means *inherit*, not
|
|
316
|
+
* "no" — the opt-out would silently never happen. (The keywords are
|
|
317
|
+
* `yes` / `no`, not `true` / `false`.) See the enumerated-attribute rule in
|
|
318
|
+
* this file's header.
|
|
319
|
+
*/
|
|
320
|
+
translate?: AttrLike<'yes' | 'no'>;
|
|
321
|
+
/**
|
|
322
|
+
* Enumerated, NOT boolean — write `autocorrect="on"` / `autocorrect="off"`.
|
|
323
|
+
* `autocorrect={false}` would omit the attribute, which means *inherit the
|
|
324
|
+
* default* (on, for most editable elements), not off.
|
|
325
|
+
*/
|
|
326
|
+
autocorrect?: AttrLike<'on' | 'off'>;
|
|
327
|
+
/**
|
|
328
|
+
* Enumerated, NOT boolean — write `writingsuggestions="false"` to turn the
|
|
329
|
+
* browser's writing suggestions off. `writingsuggestions={false}` would omit
|
|
330
|
+
* the attribute, which means *inherit the default* (on, ultimately), not
|
|
331
|
+
* off — the same trap as `spellcheck`. Keywords are `true` / `false`.
|
|
332
|
+
* All-lowercase in HTML — there is no camelCase form to alias.
|
|
333
|
+
*/
|
|
334
|
+
writingsuggestions?: EnumeratedBool;
|
|
335
|
+
/** A genuine HTML boolean attribute: presence declares the item. */
|
|
336
|
+
itemScope?: AttrLike<boolean>;
|
|
337
|
+
itemProp?: AttrLike;
|
|
338
|
+
itemType?: AttrLike;
|
|
339
|
+
itemId?: AttrLike;
|
|
340
|
+
itemRef?: AttrLike;
|
|
113
341
|
/** `data-morph-skip` opts a subtree out of kerf's morph. Any value (incl. `true`) is treated as set. */
|
|
114
342
|
'data-morph-skip'?: AttrValue;
|
|
115
343
|
/** `data-morph-skip-children` (KF-152) — morph the element's attributes but leave its children verbatim. For client-hydrated slots whose loading/state classes still need to flow through. Any value (incl. `true`) is treated as set. */
|
|
@@ -123,7 +351,14 @@ interface HTMLAnchorAttrs extends KerfBaseAttrs {
|
|
|
123
351
|
href?: AttrLike;
|
|
124
352
|
target?: AttrLike<'_self' | '_blank' | '_parent' | '_top'>;
|
|
125
353
|
rel?: AttrLike;
|
|
126
|
-
|
|
354
|
+
/**
|
|
355
|
+
* Presence-or-value (see the third shape in this file's header):
|
|
356
|
+
* `download={true}` renders the bare attribute — download the resource and
|
|
357
|
+
* let the server's `Content-Disposition` / the URL decide the filename —
|
|
358
|
+
* while a string overrides the filename. `download={false}` omits it, which
|
|
359
|
+
* is ordinary navigation. All three are real states, so both forms are typed.
|
|
360
|
+
*/
|
|
361
|
+
download?: AttrLike<boolean | string>;
|
|
127
362
|
hrefLang?: AttrLike;
|
|
128
363
|
ping?: AttrLike;
|
|
129
364
|
referrerPolicy?: AttrLike;
|
|
@@ -136,6 +371,10 @@ interface HTMLAreaAttrs extends KerfBaseAttrs {
|
|
|
136
371
|
href?: AttrLike;
|
|
137
372
|
target?: AttrLike;
|
|
138
373
|
rel?: AttrLike;
|
|
374
|
+
/** Presence-or-value, same as `<a download>` — see that attribute's note. */
|
|
375
|
+
download?: AttrLike<boolean | string>;
|
|
376
|
+
ping?: AttrLike;
|
|
377
|
+
referrerPolicy?: AttrLike;
|
|
139
378
|
}
|
|
140
379
|
interface HTMLImgAttrs extends KerfBaseAttrs {
|
|
141
380
|
src?: AttrLike;
|
|
@@ -144,12 +383,14 @@ interface HTMLImgAttrs extends KerfBaseAttrs {
|
|
|
144
383
|
height?: AttrLike<number | string>;
|
|
145
384
|
srcSet?: AttrLike;
|
|
146
385
|
sizes?: AttrLike;
|
|
147
|
-
loading?:
|
|
386
|
+
loading?: LoadingBehavior;
|
|
148
387
|
decoding?: AttrLike<'sync' | 'async' | 'auto'>;
|
|
149
388
|
crossOrigin?: AttrLike<'anonymous' | 'use-credentials' | ''>;
|
|
150
389
|
referrerPolicy?: AttrLike;
|
|
151
390
|
useMap?: AttrLike;
|
|
152
|
-
fetchPriority?:
|
|
391
|
+
fetchPriority?: FetchPriority;
|
|
392
|
+
/** A genuine HTML boolean attribute: inside `<a href>`, clicks send the click coordinates to the server. */
|
|
393
|
+
isMap?: AttrLike<boolean>;
|
|
153
394
|
}
|
|
154
395
|
interface HTMLInputAttrs extends KerfBaseAttrs {
|
|
155
396
|
type?: AttrLike<'text' | 'password' | 'email' | 'number' | 'tel' | 'url' | 'search' | 'date' | 'datetime-local' | 'time' | 'month' | 'week' | 'color' | 'checkbox' | 'radio' | 'file' | 'hidden' | 'submit' | 'reset' | 'button' | 'image' | 'range'>;
|
|
@@ -175,7 +416,7 @@ interface HTMLInputAttrs extends KerfBaseAttrs {
|
|
|
175
416
|
autocomplete?: AttrLike;
|
|
176
417
|
form?: AttrLike;
|
|
177
418
|
formAction?: AttrLike;
|
|
178
|
-
formMethod?:
|
|
419
|
+
formMethod?: FormMethod;
|
|
179
420
|
formTarget?: AttrLike;
|
|
180
421
|
formEncType?: AttrLike;
|
|
181
422
|
formNoValidate?: AttrLike<boolean>;
|
|
@@ -186,6 +427,15 @@ interface HTMLInputAttrs extends KerfBaseAttrs {
|
|
|
186
427
|
height?: AttrLike<number | string>;
|
|
187
428
|
accept?: AttrLike;
|
|
188
429
|
capture?: AttrLike<boolean | 'user' | 'environment'>;
|
|
430
|
+
/** Submits the field's text direction alongside its value, under this name. */
|
|
431
|
+
dirName?: AttrLike;
|
|
432
|
+
/**
|
|
433
|
+
* Popover invokers apply to button-state `<input>`s (`type="button"` /
|
|
434
|
+
* `"submit"` / `"reset"` / `"image"`) exactly as they do to `<button>` —
|
|
435
|
+
* the standard lists both elements.
|
|
436
|
+
*/
|
|
437
|
+
popoverTarget?: AttrLike;
|
|
438
|
+
popoverTargetAction?: PopoverTargetAction;
|
|
189
439
|
}
|
|
190
440
|
interface HTMLButtonAttrs extends KerfBaseAttrs {
|
|
191
441
|
type?: AttrLike<'button' | 'submit' | 'reset'>;
|
|
@@ -198,14 +448,39 @@ interface HTMLButtonAttrs extends KerfBaseAttrs {
|
|
|
198
448
|
formTarget?: AttrLike;
|
|
199
449
|
formEncType?: AttrLike;
|
|
200
450
|
formNoValidate?: AttrLike<boolean>;
|
|
451
|
+
popoverTarget?: AttrLike;
|
|
452
|
+
popoverTargetAction?: PopoverTargetAction;
|
|
453
|
+
/**
|
|
454
|
+
* Invoker Commands: a spec keyword — `show-modal` / `close` / `request-close`
|
|
455
|
+
* for a `<dialog>` target, `toggle-popover` / `show-popover` / `hide-popover`
|
|
456
|
+
* for a popover target — or a custom command, which the spec requires to
|
|
457
|
+
* start with `--`.
|
|
458
|
+
*
|
|
459
|
+
* **This union is a snapshot of a moving target.** The keyword set is still
|
|
460
|
+
* being extended (menu elements and `interestfor` are open in the HTML
|
|
461
|
+
* standard's invoker pipeline; `show-picker`, media, and fullscreen commands
|
|
462
|
+
* are staged behind them), so a keyword can ship in browsers before it is
|
|
463
|
+
* listed here. When that happens the compile error is kerf being out of
|
|
464
|
+
* date, not your markup being wrong — please file an issue so the union can
|
|
465
|
+
* be updated.
|
|
466
|
+
*
|
|
467
|
+
* Two ways through in the meantime, in preference order: use the custom
|
|
468
|
+
* `--*` form if the behavior is yours to define, or assert the value
|
|
469
|
+
* (`command={'show-picker' as never}`) at the one call site. The custom-command
|
|
470
|
+
* arm below is part of the design, not a workaround.
|
|
471
|
+
*/
|
|
472
|
+
command?: AttrLike<'show-modal' | 'close' | 'request-close' | 'toggle-popover' | 'show-popover' | 'hide-popover' | `--${string}`>;
|
|
473
|
+
commandFor?: AttrLike;
|
|
201
474
|
}
|
|
202
475
|
interface HTMLFormAttrs extends KerfBaseAttrs {
|
|
203
476
|
action?: AttrLike;
|
|
204
|
-
method?:
|
|
477
|
+
method?: FormMethod;
|
|
205
478
|
encType?: AttrLike;
|
|
206
479
|
target?: AttrLike;
|
|
207
480
|
name?: AttrLike;
|
|
208
481
|
noValidate?: AttrLike<boolean>;
|
|
482
|
+
/** Link types for the form's submission navigation — `noopener` / `noreferrer` / `opener`, the pairing `target` warrants. */
|
|
483
|
+
rel?: AttrLike;
|
|
209
484
|
acceptCharset?: AttrLike;
|
|
210
485
|
autoComplete?: AttrLike;
|
|
211
486
|
/** KF-183 — lowercase HTML form accepted alongside `autoComplete`. */
|
|
@@ -228,10 +503,14 @@ interface HTMLOptgroupAttrs extends KerfBaseAttrs {
|
|
|
228
503
|
label?: AttrLike;
|
|
229
504
|
disabled?: AttrLike<boolean>;
|
|
230
505
|
}
|
|
506
|
+
/**
|
|
507
|
+
* No `value` / `defaultValue`: `<select>` has no `value` content attribute, so
|
|
508
|
+
* rendering one is inert markup. The selection is expressed on the options —
|
|
509
|
+
* `<option value="b" selected>` — which is also the form kerf's morph keeps in
|
|
510
|
+
* sync with the live `selected` property after the user has picked.
|
|
511
|
+
*/
|
|
231
512
|
interface HTMLSelectAttrs extends KerfBaseAttrs {
|
|
232
513
|
name?: AttrLike;
|
|
233
|
-
value?: AttrLike;
|
|
234
|
-
defaultValue?: AttrLike;
|
|
235
514
|
multiple?: AttrLike<boolean>;
|
|
236
515
|
required?: AttrLike<boolean>;
|
|
237
516
|
disabled?: AttrLike<boolean>;
|
|
@@ -241,10 +520,13 @@ interface HTMLSelectAttrs extends KerfBaseAttrs {
|
|
|
241
520
|
/** KF-183 — lowercase HTML form accepted alongside `autoComplete`. */
|
|
242
521
|
autocomplete?: AttrLike;
|
|
243
522
|
}
|
|
523
|
+
/**
|
|
524
|
+
* No `value` / `defaultValue`: a `<textarea>`'s value is its child text, and
|
|
525
|
+
* there is no `value` content attribute to render. Write the text as a child —
|
|
526
|
+
* `<textarea>{draft}</textarea>` — which is what kerf's morph reconciles.
|
|
527
|
+
*/
|
|
244
528
|
interface HTMLTextareaAttrs extends KerfBaseAttrs {
|
|
245
529
|
name?: AttrLike;
|
|
246
|
-
value?: AttrLike;
|
|
247
|
-
defaultValue?: AttrLike;
|
|
248
530
|
placeholder?: AttrLike;
|
|
249
531
|
rows?: AttrLike<number>;
|
|
250
532
|
cols?: AttrLike<number>;
|
|
@@ -254,13 +536,17 @@ interface HTMLTextareaAttrs extends KerfBaseAttrs {
|
|
|
254
536
|
maxLength?: AttrLike<number>;
|
|
255
537
|
minLength?: AttrLike<number>;
|
|
256
538
|
wrap?: AttrLike<'hard' | 'soft' | 'off'>;
|
|
539
|
+
/** Submits the field's text direction alongside its value, under this name. */
|
|
540
|
+
dirName?: AttrLike;
|
|
257
541
|
autoComplete?: AttrLike;
|
|
258
542
|
/** KF-183 — lowercase HTML form accepted alongside `autoComplete`. */
|
|
259
543
|
autocomplete?: AttrLike;
|
|
260
544
|
form?: AttrLike;
|
|
261
545
|
}
|
|
262
546
|
interface HTMLTableAttrs extends KerfBaseAttrs {
|
|
547
|
+
/** @deprecated Obsolete presentational attribute — use CSS `padding` on the cells. Typed so legacy markup still compiles. */
|
|
263
548
|
cellPadding?: AttrLike<number | string>;
|
|
549
|
+
/** @deprecated Obsolete presentational attribute — use CSS `border-spacing`. Typed so legacy markup still compiles. */
|
|
264
550
|
cellSpacing?: AttrLike<number | string>;
|
|
265
551
|
}
|
|
266
552
|
interface HTMLTableCellAttrs extends KerfBaseAttrs {
|
|
@@ -278,6 +564,13 @@ interface HTMLMetaAttrs extends KerfBaseAttrs {
|
|
|
278
564
|
content?: AttrLike;
|
|
279
565
|
charSet?: AttrLike;
|
|
280
566
|
httpEquiv?: AttrLike;
|
|
567
|
+
media?: AttrLike;
|
|
568
|
+
/**
|
|
569
|
+
* Open Graph (`og:title` etc.) — NOT in the HTML standard, typed because it
|
|
570
|
+
* is universal in real documents. See the deviations list in this file's
|
|
571
|
+
* header.
|
|
572
|
+
*/
|
|
573
|
+
property?: AttrLike;
|
|
281
574
|
}
|
|
282
575
|
interface HTMLLinkAttrs extends KerfBaseAttrs {
|
|
283
576
|
href?: AttrLike;
|
|
@@ -290,7 +583,13 @@ interface HTMLLinkAttrs extends KerfBaseAttrs {
|
|
|
290
583
|
crossOrigin?: AttrLike;
|
|
291
584
|
integrity?: AttrLike;
|
|
292
585
|
referrerPolicy?: AttrLike;
|
|
293
|
-
fetchPriority?:
|
|
586
|
+
fetchPriority?: FetchPriority;
|
|
587
|
+
/** A genuine HTML boolean attribute on `<link>`: the stylesheet is not applied (and for a stylesheet link, not fetched) until it's removed. */
|
|
588
|
+
disabled?: AttrLike<boolean>;
|
|
589
|
+
/** For `rel="preload" as="image"`: the srcset the preload should match. */
|
|
590
|
+
imageSrcSet?: AttrLike;
|
|
591
|
+
imageSizes?: AttrLike;
|
|
592
|
+
blocking?: BlockingToken;
|
|
294
593
|
}
|
|
295
594
|
interface HTMLScriptAttrs extends KerfBaseAttrs {
|
|
296
595
|
src?: AttrLike;
|
|
@@ -301,12 +600,14 @@ interface HTMLScriptAttrs extends KerfBaseAttrs {
|
|
|
301
600
|
integrity?: AttrLike;
|
|
302
601
|
crossOrigin?: AttrLike;
|
|
303
602
|
referrerPolicy?: AttrLike;
|
|
304
|
-
|
|
603
|
+
blocking?: BlockingToken;
|
|
604
|
+
fetchPriority?: FetchPriority;
|
|
305
605
|
}
|
|
606
|
+
/** No `scoped`: the proposal was removed from the HTML standard and never shipped in any engine. */
|
|
306
607
|
interface HTMLStyleAttrs extends KerfBaseAttrs {
|
|
307
608
|
type?: AttrLike;
|
|
308
609
|
media?: AttrLike;
|
|
309
|
-
|
|
610
|
+
blocking?: BlockingToken;
|
|
310
611
|
}
|
|
311
612
|
interface HTMLIframeAttrs extends KerfBaseAttrs {
|
|
312
613
|
src?: AttrLike;
|
|
@@ -317,7 +618,7 @@ interface HTMLIframeAttrs extends KerfBaseAttrs {
|
|
|
317
618
|
allowFullScreen?: AttrLike<boolean>;
|
|
318
619
|
width?: AttrLike<number | string>;
|
|
319
620
|
height?: AttrLike<number | string>;
|
|
320
|
-
loading?:
|
|
621
|
+
loading?: LoadingBehavior;
|
|
321
622
|
referrerPolicy?: AttrLike;
|
|
322
623
|
}
|
|
323
624
|
interface HTMLMediaAttrs extends KerfBaseAttrs {
|
|
@@ -341,6 +642,9 @@ interface HTMLSourceAttrs extends KerfBaseAttrs {
|
|
|
341
642
|
srcSet?: AttrLike;
|
|
342
643
|
sizes?: AttrLike;
|
|
343
644
|
media?: AttrLike;
|
|
645
|
+
/** Valid when the parent is `<picture>`: intrinsic dimensions for the candidate image, so layout is stable before selection. */
|
|
646
|
+
width?: AttrLike<number | string>;
|
|
647
|
+
height?: AttrLike<number | string>;
|
|
344
648
|
}
|
|
345
649
|
interface HTMLTrackAttrs extends KerfBaseAttrs {
|
|
346
650
|
src?: AttrLike;
|
package/dist/jsx-runtime.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { Fragment, SafeHtml, assertEmittableAttrName as _assertEmittableAttrName, _renderAttrVerbatim, _toSegment, granularListSafeHtml, isSafeHtml, jsx, jsx as jsxDEV, jsx as jsxs, listSafeHtml, raw } from './chunk-
|
|
1
|
+
export { Fragment, SafeHtml, assertEmittableAttrName as _assertEmittableAttrName, _renderAttrVerbatim, _toSegment, granularListSafeHtml, isSafeHtml, jsx, jsx as jsxDEV, jsx as jsxs, listSafeHtml, raw } from './chunk-JXAR5J54.js';
|
|
2
2
|
import './chunk-GY4XV2UV.js';
|
|
3
3
|
import './chunk-3APBEVHF.js';
|
|
4
4
|
import './chunk-VVDJLWMP.js';
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# kerf
|
|
2
2
|
|
|
3
|
-
> A tiny (~
|
|
3
|
+
> A tiny (~12 KB minified + gzipped including its one runtime dependency `@preact/signals-core`; ~13 KB with `arraySignal`) reactive UI framework — fine-grained signals + DOM morphing + JSX. No virtual DOM, no compiler. Apply the smallest possible cut to update your DOM.
|
|
4
4
|
|
|
5
5
|
kerf renders JSX to a structured `SafeHtml` (string for static content; tagged "list"/"mixed" segments where `each(...)` was used) and reconciles it against the live tree with a custom segment-aware morph. Static surrounds go through a general-purpose tree-morph; list contents go through a keyed reconciler that operates directly on live children — partial-update on huge lists is O(changes), not O(rows). Reactivity is provided by [@preact/signals-core](https://github.com/preactjs/signals). It pairs well with server-rendered HTML, embedded widgets, and any UI where preserving focus / selection across re-renders matters. Public API is one import: `signal`, `computed`, `effect`, `batch`, `defineStore`, `resetAllStores`, `mount`, `morph`, `each`, `attr`, `delegate`, `delegateCapture`, `toElement`, `SafeHtml`, `isSafeHtml`, `raw`, `Fragment`. (Two more subpaths: `kerfjs/testing` exposes `clearStoreRegistry` for unit-test isolation; `kerfjs/jsx-runtime` exposes the typed JSX building blocks for declaration-merging custom-element types.) An optional subpath at `kerfjs/array-signal` adds `arraySignal()` — a granular keyed-list signal whose patch events let `each()` reconcile in O(patches) instead of O(N). An optional subpath at `kerfjs/dev` installs the development diagnostics — kerf does NOT infer dev mode, so you import it behind your own build's dev flag (`if (import.meta.env.DEV) await import('kerfjs/dev');`); omitting it is production and sheds ~4.7 KB min+gzip. Another optional subpath at `kerfjs/html` adds the `html` tagged template — JSX-identical runtime semantics with no JSX transform, so CDN/importmap projects can author kerf UIs with literally no build step.
|
|
6
6
|
|
|
@@ -30,11 +30,12 @@ kerf renders JSX to a structured `SafeHtml` (string for static content; tagged "
|
|
|
30
30
|
- [API reference](https://github.com/brianwestphal/kerf/blob/main/docs/8-api-reference.md): every export, every option.
|
|
31
31
|
- [Live demo](https://github.com/brianwestphal/kerf/blob/main/docs/9-live-demo.md): the GitHub Pages deploy of `examples/reactivity-demo`.
|
|
32
32
|
- [Migrating](https://github.com/brianwestphal/kerf/blob/main/docs/10-migrating.md): the `/kerf/migrating/` comparison hub — coming-from-React/Alpine/Lit/vanjs pages with side-by-side todo-list translations.
|
|
33
|
-
- [Dev-mode warnings](https://github.com/brianwestphal/kerf/blob/main/docs/11-dev-warnings.md): the opt-in `KERF_DEV_WARN_*` env-gated dev-warn family (rebuilt listeners, untracked signals, narrow store sets, delegate-in-effect, each-in-morph-skip, duplicate keys, value-only re-renders, stale bindings), how the diagnostics are installed via the `kerfjs/dev` subpath rather than inferred from the environment, and the rules each new warning must follow.
|
|
33
|
+
- [Dev-mode warnings](https://github.com/brianwestphal/kerf/blob/main/docs/11-dev-warnings.md): the opt-in `KERF_DEV_WARN_*` env-gated dev-warn family (rebuilt listeners, untracked signals, narrow store sets, delegate-in-effect, each-in-morph-skip, duplicate keys, value-only re-renders, stale bindings, list rebinds, stale row indices, parser repairs) plus the `KERF_DEV_INVARIANTS` structural checks, how the diagnostics are installed via the `kerfjs/dev` subpath rather than inferred from the environment, and the rules each new warning must follow.
|
|
34
34
|
- [AI-assistant configs](https://github.com/brianwestphal/kerf/blob/main/docs/12-ai-assistant-configs.md): how the drop-in Claude Code skill + Cursor rules ship inside the `kerfjs` npm package at `ai/skill.md` / `ai/cursorrules` / `ai/manifest.json`, the version + marker contract for customization preservation, and the `kerfjs/ai-assistant-configs` ESLint rule that surfaces drift on every lint pass.
|
|
35
35
|
- [Component packages](https://github.com/brianwestphal/kerf/blob/main/docs/13-component-packages.md): building and publishing reusable kerf components as npm packages — the no-instance component model, per-instance state via factories, event/cleanup patterns, and `kerfjs`-as-peer-dependency packaging modeled on `eslint-plugin-kerfjs`. Scaffold one with `npm create kerf-component@latest <dir>` (the `create-kerf-component` initializer).
|
|
36
36
|
- [Feature coverage](https://github.com/brianwestphal/kerf/blob/main/docs/14-feature-coverage.md): the per-behavior coverage axis orthogonal to line coverage — an index mapping each behavior (especially list-reconciler *state transitions*) to its guarding test, enforced by `npm run check:features`.
|
|
37
37
|
- [No-build example](https://github.com/brianwestphal/kerf/blob/main/docs/15-no-build-example.md): the served-as-source `live-poll` example app — plain JS + importmap + the `html` tagged template, zero tooling — and the vendor-copy contract that ships it.
|
|
38
|
+
- [List identity](https://github.com/brianwestphal/kerf/blob/main/docs/16-list-identity.md): why an `each()` list's call-order identity is not stable, what the source guard fixes and what it doesn't, the five constraints any scheme must survive, and the explicit-key recommendation now shipped as `each(items, render, { key })`.
|
|
38
39
|
|
|
39
40
|
## Examples
|
|
40
41
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kerfjs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Tiny reactive UI framework — fine-grained signals + DOM morphing + JSX. Apply the smallest possible cut to update your DOM.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"bench:serve": "bash bench/site.sh",
|
|
92
92
|
"lint": "eslint src tests",
|
|
93
93
|
"typecheck": "node node_modules/typescript7/bin/tsc --noEmit",
|
|
94
|
-
"check": "npm run lint && npm run typecheck && node scripts/check-doc-test-inventory.mjs && node scripts/check-doc-api-coverage.mjs && node scripts/check-doc-site-tickets.mjs && node scripts/check-feature-coverage.mjs && node scripts/check-ai-bundle.mjs && npm test && npm run build && node scripts/check-bundle-size.mjs && node scripts/check-doc-api-signatures.mjs && vitest run --config vitest.config.dist.ts && vitest run --config vitest.config.dist-full.ts && node node_modules/typescript7/bin/tsc -p tests/dist/jsx-typing/tsconfig.json && node node_modules/typescript7/bin/tsc -p site/src/examples/complete/tsconfig.json && node node_modules/typescript7/bin/tsc -p tests/dist/scaffold-typing/tsconfig.json && node scripts/check-docs-examples.mjs",
|
|
94
|
+
"check": "npm run lint && npm run typecheck && node scripts/check-doc-test-inventory.mjs && node scripts/check-doc-api-coverage.mjs && node scripts/check-doc-site-tickets.mjs && node scripts/check-dev-warn-docs.mjs && node scripts/check-skill-freshness.mjs && node scripts/check-design-rule-5.mjs && node scripts/check-feature-coverage.mjs && node scripts/check-ai-bundle.mjs && npm test && npm run build && node scripts/check-bundle-size.mjs && node scripts/check-doc-api-signatures.mjs && vitest run --config vitest.config.dist.ts && vitest run --config vitest.config.dist-full.ts && node node_modules/typescript7/bin/tsc -p tests/dist/jsx-typing/tsconfig.json && node node_modules/typescript7/bin/tsc -p site/src/examples/complete/tsconfig.json && node node_modules/typescript7/bin/tsc -p tests/dist/scaffold-typing/tsconfig.json && node scripts/check-docs-examples.mjs",
|
|
95
95
|
"check:docs:examples": "node scripts/check-docs-examples.mjs",
|
|
96
96
|
"check:full": "npm run check && playwright test",
|
|
97
97
|
"check:docs:test-inventory": "node scripts/check-doc-test-inventory.mjs",
|
|
@@ -113,7 +113,10 @@
|
|
|
113
113
|
"site:dev": "cd site && npm install && npm run dev",
|
|
114
114
|
"site:dev:hmr": "cd site && npm install && npm run dev:hmr",
|
|
115
115
|
"site:build": "cd site && npm install && npm run build",
|
|
116
|
-
"check:bundle-size": "npm run build && node scripts/check-bundle-size.mjs"
|
|
116
|
+
"check:bundle-size": "npm run build && node scripts/check-bundle-size.mjs",
|
|
117
|
+
"check:skills": "node scripts/check-skill-freshness.mjs",
|
|
118
|
+
"check:design-rule-5": "node scripts/check-design-rule-5.mjs",
|
|
119
|
+
"check:docs:dev-warns": "node scripts/check-dev-warn-docs.mjs"
|
|
117
120
|
},
|
|
118
121
|
"dependencies": {
|
|
119
122
|
"@preact/signals-core": "^1.14.1"
|
|
@@ -137,5 +140,16 @@
|
|
|
137
140
|
"typescript": "^6.0.3",
|
|
138
141
|
"typescript7": "npm:typescript@^7.0.2",
|
|
139
142
|
"vitest": "^3.0.0"
|
|
143
|
+
},
|
|
144
|
+
"gitgist": {
|
|
145
|
+
"exclude": [
|
|
146
|
+
"site/public/demos/*.svg",
|
|
147
|
+
"site/src/content/docs/docs/*",
|
|
148
|
+
"site/src/content/docs/api.md",
|
|
149
|
+
"ai/*",
|
|
150
|
+
"site/public/llms.txt",
|
|
151
|
+
"bench/results.json",
|
|
152
|
+
"bench/results.md"
|
|
153
|
+
]
|
|
140
154
|
}
|
|
141
155
|
}
|