fragtml 0.0.2 → 0.0.4

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/README.md CHANGED
@@ -156,45 +156,15 @@ html`<button ?disabled="${loading}">Save</button>`
156
156
  html`<button ?disabled='${loading}'>Save</button>`
157
157
  ```
158
158
 
159
- ## Bound tags
160
-
161
- `html(options)` returns a configured tag. This is useful for fragment rendering and for editor syntax highlighting, because many editors highlight tagged templates better when the tag is a simple identifier.
162
-
163
- ```js
164
- import { createHtml, render } from 'fragtml'
165
-
166
- export function view ({ fragmentId }) {
167
- const html = createHtml({ fragmentId })
168
-
169
- return render(html`
170
- <main>...</main>
171
- `)
172
- }
173
- ```
174
-
175
- `createHtml` is an alias of `html`:
176
-
177
- ```js
178
- import html, { createHtml } from 'fragtml'
179
-
180
- createHtml === html
181
- ```
182
-
183
- You can also use the short fragment-target form:
159
+ ## Fragments
184
160
 
185
- ```js
186
- const html = createHtml('archive-ui')
187
- ```
161
+ Fragments mark named ranges inside a larger template. Calling `html(fragmentId)` on that template renders either the full template or one selected fragment:
188
162
 
189
- which is equivalent to:
163
+ - `html()` / `html(undefined)` renders the full template.
164
+ - `html('archive-ui')` renders only the `archive-ui` fragment.
165
+ - `html({ fragmentId: 'archive-ui' })` is the options-object form.
190
166
 
191
- ```js
192
- const html = createHtml({ fragmentId: 'archive-ui' })
193
- ```
194
-
195
- ## Fragments
196
-
197
- Fragments mark a named range inside a larger template. Rendering without `fragmentId` returns the whole template. Rendering with `fragmentId` returns only that fragment.
167
+ This lets one view function serve both full-page requests and htmx-style fragment requests by passing the requested fragment ID through to `html(fragmentId)`.
198
168
 
199
169
  This mirrors the htmx article’s idea:
200
170
 
@@ -215,12 +185,10 @@ ${html.fragment.end}
215
185
  ### Example
216
186
 
217
187
  ```js
218
- import { createHtml, render } from 'fragtml'
188
+ import html, { render } from 'fragtml'
219
189
 
220
190
  export function contactDetail ({ contact, fragmentId }) {
221
- const html = createHtml({ fragmentId })
222
-
223
- return render(html`
191
+ return render(html(fragmentId)`
224
192
  <html>
225
193
  <body>
226
194
  <div hx-target="this">
@@ -253,6 +221,51 @@ contactDetail({ contact, fragmentId: 'archive-ui' })
253
221
 
254
222
  Fragment boundary tokens are not included in either output.
255
223
 
224
+ If you want a simple local tag name for editor highlighting or repeated use, `frag` is an alias of `html`:
225
+
226
+ ```js
227
+ import { frag, render } from 'fragtml'
228
+
229
+ export function contactDetail ({ contact, fragmentId }) {
230
+ const html = frag(fragmentId)
231
+
232
+ return render(html`
233
+ ${html.fragment.start('archive-ui')}
234
+ <button>${contact.archived ? 'Unarchive' : 'Archive'}</button>
235
+ ${html.fragment.end}
236
+ `)
237
+ }
238
+ ```
239
+
240
+ In TypeScript, you can use an explicit fragment-name union to type-check both incoming fragment IDs and declared fragment boundaries:
241
+
242
+ ```ts
243
+ import { frag, render } from 'fragtml'
244
+ import type { RenderOptions } from 'fragtml/types.js'
245
+
246
+ const contactFragments = {
247
+ archiveUi: 'archive-ui',
248
+ details: 'details'
249
+ } as const
250
+
251
+ type ContactFragment = typeof contactFragments[keyof typeof contactFragments]
252
+
253
+ export function contactDetail ({
254
+ contact,
255
+ fragmentId
256
+ }: {
257
+ contact: Contact
258
+ } & RenderOptions<ContactFragment>) {
259
+ const html = frag<ContactFragment>(fragmentId)
260
+
261
+ return render(html`
262
+ ${html.fragment.start(contactFragments.archiveUi)}
263
+ <button>${contact.archived ? 'Unarchive' : 'Archive'}</button>
264
+ ${html.fragment.end}
265
+ `)
266
+ }
267
+ ```
268
+
256
269
  ### Fragment rules
257
270
 
258
271
  - Fragment IDs must be unique within a rendered template.
@@ -266,12 +279,10 @@ Fragment boundary tokens are not included in either output.
266
279
  Nested fragments are supported with stack semantics. This is useful when a larger region can be re-rendered as a whole, but a smaller region inside it is also a valid htmx update target.
267
280
 
268
281
  ```js
269
- import { createHtml, render } from 'fragtml'
282
+ import html, { render } from 'fragtml'
270
283
 
271
284
  export function page ({ fragmentId }) {
272
- const html = createHtml({ fragmentId })
273
-
274
- return render(html`
285
+ return render(html(fragmentId)`
275
286
  ${html.fragment.start('outer')}
276
287
  <section>
277
288
  <h2>Outer</h2>
@@ -311,21 +322,21 @@ Safe-by-default template tag.
311
322
  html`<p>${value}</p>`
312
323
  ```
313
324
 
314
- Also acts as a factory for bound tags:
325
+ Pass a fragment ID before the tagged template to render a selected fragment from that template:
315
326
 
316
327
  ```js
317
- const h = html({ fragmentId: 'name' })
318
- const h = html('name')
328
+ html('name')`...`
329
+ html({ fragmentId: 'name' })`...`
319
330
  ```
320
331
 
321
- ### `createHtml`
332
+ ### `frag`
322
333
 
323
- Alias of `html`, intended for local tag naming:
334
+ Alias of `html`, useful when you want a local tag name for editor highlighting or repeated use:
324
335
 
325
336
  ```js
326
- import { createHtml } from 'fragtml'
337
+ import { frag } from 'fragtml'
327
338
 
328
- const html = createHtml({ fragmentId })
339
+ const html = frag(fragmentId)
329
340
  ```
330
341
 
331
342
  ### `render(value)`
@@ -344,6 +355,42 @@ Marks trusted HTML so it is inserted without escaping.
344
355
  html`<p>${raw('<strong>trusted</strong>')}</p>`
345
356
  ```
346
357
 
358
+ ### `HtmlResult`
359
+
360
+ Class returned by `html` and `frag` tagged templates.
361
+
362
+ ```js
363
+ import html, { HtmlResult } from 'fragtml'
364
+
365
+ const result = html`<p>Hello</p>`
366
+
367
+ result instanceof HtmlResult
368
+ ```
369
+
370
+ ### `RawHtml`
371
+
372
+ Class returned by `raw(value)` and `html.raw(value)`.
373
+
374
+ ```js
375
+ import { RawHtml, raw } from 'fragtml'
376
+
377
+ const trusted = raw('<strong>trusted</strong>')
378
+
379
+ trusted instanceof RawHtml
380
+ ```
381
+
382
+ ### Type guards
383
+
384
+ Use the public type guards to narrow unknown values without importing from internal `lib/` paths:
385
+
386
+ ```js
387
+ import {
388
+ isFragmentBoundary,
389
+ isHtmlResult,
390
+ isRawHtml
391
+ } from 'fragtml'
392
+ ```
393
+
347
394
  ### Boolean attributes
348
395
 
349
396
  Use unquoted `?name=${condition}` syntax to toggle a boolean attribute.
@@ -382,6 +429,40 @@ import {
382
429
 
383
430
  `fragtml` is written in typed JavaScript and ships generated declaration files.
384
431
 
432
+ Runtime classes such as `HtmlResult` and `RawHtml` are exported from the package root. Type-only aliases are exported from `fragtml/types.js`:
433
+
434
+ ```ts
435
+ import type {
436
+ FragmentBoundary,
437
+ FragmentEndBoundary,
438
+ FragmentHelpers,
439
+ FragmentStartBoundary,
440
+ HtmlArrayScalarSubstitution,
441
+ HtmlArraySubstitution,
442
+ HtmlPrimitiveSubstitution,
443
+ HtmlSubstitution,
444
+ HtmlTag,
445
+ RawHtml,
446
+ RenderOptions,
447
+ TemplateStrings
448
+ } from 'fragtml/types.js'
449
+ ```
450
+
451
+ `HtmlResult` is both a runtime class from the package root and an importable type from `fragtml/types.js`:
452
+
453
+ ```ts
454
+ import { HtmlResult } from 'fragtml'
455
+ import type { HtmlResult as HtmlResultType } from 'fragtml/types.js'
456
+
457
+ function sendHtml (result: HtmlResultType) {
458
+ return result.toString()
459
+ }
460
+
461
+ function isHtmlResultValue (value: unknown): value is HtmlResultType {
462
+ return value instanceof HtmlResult
463
+ }
464
+ ```
465
+
385
466
  ## License
386
467
 
387
468
  MIT
package/index.d.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  export default html;
2
+ export { isFragmentBoundary } from "./lib/fragment.js";
2
3
  import { html } from './lib/html.js';
3
- export const createHtml: import("./lib/create-tag.js").HtmlTag;
4
+ export const frag: import("./types.js").HtmlTag;
4
5
  import { raw } from './lib/raw.js';
5
6
  import { render } from './lib/render.js';
6
7
  export { html, raw, render };
8
+ export { HtmlResult, isHtmlResult } from "./lib/html-result.js";
9
+ export { RawHtml, isRawHtml } from "./lib/raw.js";
7
10
  export { DuplicateFragmentError, FragmentBoundaryError, FragmentNotFoundError } from "./lib/render.js";
8
11
  //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":";qBAAqB,eAAe;AAIpC,+DAAuB;oBAHH,cAAc;uBACX,iBAAiB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":";;qBAAqB,eAAe;AAIpC,gDAAiB;oBAHG,cAAc;uBACX,iBAAiB"}
package/index.js CHANGED
@@ -2,8 +2,11 @@ import { html } from './lib/html.js'
2
2
  import { raw } from './lib/raw.js'
3
3
  import { render } from './lib/render.js'
4
4
 
5
- const createHtml = html
5
+ const frag = html
6
6
 
7
7
  export default html
8
- export { createHtml, html, raw, render }
8
+ export { frag, html, raw, render }
9
+ export { isFragmentBoundary } from './lib/fragment.js'
10
+ export { HtmlResult, isHtmlResult } from './lib/html-result.js'
11
+ export { RawHtml, isRawHtml } from './lib/raw.js'
9
12
  export { DuplicateFragmentError, FragmentBoundaryError, FragmentNotFoundError } from './lib/render.js'
@@ -1,17 +1,3 @@
1
1
  export const html: HtmlTag;
2
- export type RenderOptions = {
3
- fragmentId?: string | undefined;
4
- };
5
- export type CompiledTemplate = {
6
- strings: readonly string[];
7
- };
8
- export type HtmlTag = ((strings: TemplateStrings, ...substitutions: HtmlSubstitution[]) => HtmlResult) & ((options?: RenderOptions | string) => HtmlTag) & {
9
- fragment: FragmentHelpers;
10
- raw: (value: unknown) => RawHtml;
11
- };
12
- import type { TemplateStrings } from './html-types.js';
13
- import type { HtmlSubstitution } from './html-types.js';
14
- import { HtmlResult } from './html-result.js';
15
- import type { FragmentHelpers } from './fragment.js';
16
- import type { RawHtml } from './raw.js';
2
+ import type { HtmlTag } from './html-types.js';
17
3
  //# sourceMappingURL=create-tag.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-tag.d.ts","sourceRoot":"","sources":["create-tag.js"],"names":[],"mappings":"AAqFA,mBADW,OAAO,CACoB;;iBA1ExB,MAAM,GAAG,SAAS;;;aAKlB,SAAS,MAAM,EAAE;;sBAwElB,CAAC,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,aAAa,EAAE,gBAAgB,EAAE,KAAK,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,KAAK,OAAO,CAAC,GAAG;IAAE,QAAQ,EAAE,eAAe,CAAC;IAAC,GAAG,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAA;CAAE;qCAvF1J,iBAAiB;sCAAjB,iBAAiB;2BAI7C,kBAAkB;qCALR,eAAe;6BAEvB,UAAU"}
1
+ {"version":3,"file":"create-tag.d.ts","sourceRoot":"","sources":["create-tag.js"],"names":[],"mappings":"AA8EA,mBADW,OAAO,CACoB;6BA9E4E,iBAAiB"}
package/lib/create-tag.js CHANGED
@@ -1,22 +1,10 @@
1
- /** @import { FragmentHelpers } from './fragment.js' */
2
- /** @import { HtmlSubstitution, TemplateStrings } from './html-types.js' */
3
- /** @import { RawHtml } from './raw.js' */
1
+ /** @import { CompiledTemplate, FragmentHelpers, HtmlSubstitution, HtmlTag, RenderOptions, TemplateStrings } from './html-types.js' */
4
2
 
5
3
  import { createFragmentHelpers } from './fragment.js'
6
4
  import { HtmlResult } from './html-result.js'
7
5
  import { raw } from './raw.js'
8
6
  import { renderResult } from './render.js'
9
7
 
10
- /**
11
- * @typedef {object} RenderOptions
12
- * @property {string | undefined} [fragmentId]
13
- */
14
-
15
- /**
16
- * @typedef {object} CompiledTemplate
17
- * @property {readonly string[]} strings
18
- */
19
-
20
8
  /** @type {WeakMap<TemplateStringsArray | readonly string[], CompiledTemplate>} */
21
9
  const templateCache = new WeakMap()
22
10
  const fragment = createFragmentHelpers()
@@ -44,26 +32,31 @@ function isTemplateStrings (value) {
44
32
  }
45
33
 
46
34
  /**
47
- * @param {RenderOptions | string | undefined} options
48
- * @returns {RenderOptions}
35
+ * @template {string} FragmentId
36
+ * @param {RenderOptions<FragmentId> | string | undefined} options
37
+ * @returns {RenderOptions<FragmentId>}
49
38
  */
50
39
  function normalizeOptions (options) {
51
- if (typeof options === 'string') return { fragmentId: options }
40
+ if (typeof options === 'string') {
41
+ return /** @type {RenderOptions<FragmentId>} */ ({ fragmentId: options })
42
+ }
52
43
  return options ? { ...options } : {}
53
44
  }
54
45
 
55
46
  /**
56
- * @param {RenderOptions} options
57
- * @returns {HtmlTag}
47
+ * @template {string} FragmentId
48
+ * @param {RenderOptions<FragmentId>} options
49
+ * @returns {HtmlTag<FragmentId>}
58
50
  */
59
51
  function createBoundTag (options) {
60
52
  /**
61
- * @param {TemplateStrings | RenderOptions | string | undefined} strings
62
- * @param {...HtmlSubstitution} substitutions
53
+ * @template {string} NextFragmentId
54
+ * @param {TemplateStrings | RenderOptions<NextFragmentId> | string | undefined} strings
55
+ * @param {...HtmlSubstitution<FragmentId>} substitutions
63
56
  */
64
57
  function tag (strings, ...substitutions) {
65
58
  if (!isTemplateStrings(strings)) {
66
- return createBoundTag(normalizeOptions(/** @type {RenderOptions | string | undefined} */ strings))
59
+ return createBoundTag(normalizeOptions(/** @type {RenderOptions<NextFragmentId> | string | undefined} */ strings))
67
60
  }
68
61
 
69
62
  return new HtmlResult(
@@ -74,9 +67,9 @@ function createBoundTag (options) {
74
67
  )
75
68
  }
76
69
 
77
- const htmlTag = /** @type {HtmlTag} */ (tag)
70
+ const htmlTag = /** @type {HtmlTag<FragmentId>} */ (tag)
78
71
 
79
- htmlTag.fragment = fragment
72
+ htmlTag.fragment = /** @type {FragmentHelpers<FragmentId>} */ (/** @type {unknown} */ (fragment))
80
73
  htmlTag.raw = raw
81
74
 
82
75
  return htmlTag
@@ -84,7 +77,3 @@ function createBoundTag (options) {
84
77
 
85
78
  /** @type {HtmlTag} */
86
79
  export const html = createBoundTag({})
87
-
88
- /**
89
- * @typedef {((strings: TemplateStrings, ...substitutions: HtmlSubstitution[]) => HtmlResult) & ((options?: RenderOptions | string) => HtmlTag) & { fragment: FragmentHelpers, raw: (value: unknown) => RawHtml }} HtmlTag
90
- */
package/lib/fragment.d.ts CHANGED
@@ -1,20 +1,5 @@
1
- export function createFragmentHelpers(): FragmentHelpers;
1
+ export function createFragmentHelpers<FragmentId extends string = string>(): FragmentHelpers<FragmentId>;
2
2
  export function isFragmentBoundary(value: unknown): value is FragmentBoundary;
3
3
  export const fragmentBoundarySymbol: unique symbol;
4
- export type FragmentStartBoundary = {
5
- [fragmentBoundarySymbol]: true;
6
- kind: "start";
7
- id: string;
8
- };
9
- export type FragmentEndBoundary = {
10
- [fragmentBoundarySymbol]: true;
11
- kind: "end";
12
- };
13
- export type FragmentBoundary = FragmentStartBoundary | FragmentEndBoundary;
14
- export type FragmentHelpers = {
15
- start: typeof start;
16
- end: FragmentEndBoundary;
17
- };
18
- declare function start(id: string): FragmentStartBoundary;
19
- export {};
4
+ import type { FragmentHelpers } from './html-types.js';
20
5
  //# sourceMappingURL=fragment.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fragment.d.ts","sourceRoot":"","sources":["fragment.js"],"names":[],"mappings":"AAiCA,yCAFa,eAAe,CAI3B;AAMD,0CAHW,OAAO,GACL,KAAK,IAAI,gBAAgB,CAQrC;AAxCD,mDAAwE;oCAN3D;IAAE,CAAC,sBAAsB,CAAC,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE;kCAC7D;IAAE,CAAC,sBAAsB,CAAC,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE;+BAC/C,qBAAqB,GAAG,mBAAmB;8BAC3C;IAAE,KAAK,EAAE,OAAO,KAAK,CAAC;IAAC,GAAG,EAAE,mBAAmB,CAAA;CAAE;AAc9D,2BAHW,MAAM,GACJ,qBAAqB,CAYjC"}
1
+ {"version":3,"file":"fragment.d.ts","sourceRoot":"","sources":["fragment.js"],"names":[],"mappings":"AAgCA,sCAHuB,UAAU,SAApB,MAAQ,cACR,gBAAgB,UAAU,CAAC,CAIvC;AAMD,0CAHW,OAAO,GACL,KAAK,IAAI,gBAAgB,CAQrC;AA5CD,mDAAwE;qCAFS,iBAAiB"}
package/lib/fragment.js CHANGED
@@ -1,9 +1,4 @@
1
- /**
2
- * @typedef {{ [fragmentBoundarySymbol]: true, kind: 'start', id: string }} FragmentStartBoundary
3
- * @typedef {{ [fragmentBoundarySymbol]: true, kind: 'end' }} FragmentEndBoundary
4
- * @typedef {FragmentStartBoundary | FragmentEndBoundary} FragmentBoundary
5
- * @typedef {{ start: typeof start, end: FragmentEndBoundary }} FragmentHelpers
6
- */
1
+ /** @import { FragmentEndBoundary, FragmentHelpers, FragmentStartBoundary } from './html-types.js' */
7
2
 
8
3
  export const fragmentBoundarySymbol = Symbol('fragtml.fragmentBoundary')
9
4
 
@@ -13,23 +8,27 @@ const end = Object.freeze(/** @type {FragmentEndBoundary} */ ({
13
8
  }))
14
9
 
15
10
  /**
16
- * @param {string} id
17
- * @returns {FragmentStartBoundary}
11
+ * @template {string} FragmentId
12
+ * @param {FragmentId} id
13
+ * @returns {FragmentStartBoundary<FragmentId>}
18
14
  */
19
15
  function start (id) {
20
16
  if (typeof id !== 'string' || id.length === 0) {
21
17
  throw new TypeError('fragment.start(id) requires a non-empty string id')
22
18
  }
23
19
 
24
- return {
20
+ const boundary = {
25
21
  [fragmentBoundarySymbol]: true,
26
22
  kind: 'start',
27
23
  id
28
24
  }
25
+
26
+ return /** @type {FragmentStartBoundary<FragmentId>} */ (boundary)
29
27
  }
30
28
 
31
29
  /**
32
- * @returns {FragmentHelpers}
30
+ * @template {string} [FragmentId=string]
31
+ * @returns {FragmentHelpers<FragmentId>}
33
32
  */
34
33
  export function createFragmentHelpers () {
35
34
  return Object.freeze({ start, end })
@@ -11,7 +11,7 @@ export class HtmlResult {
11
11
  [Symbol.toPrimitive](): string;
12
12
  [htmlResultSymbol]: boolean;
13
13
  }
14
- import type { CompiledTemplate } from './create-tag.js';
14
+ import type { CompiledTemplate } from './html-types.js';
15
15
  import type { HtmlSubstitution } from './html-types.js';
16
- import type { RenderOptions } from './create-tag.js';
16
+ import type { RenderOptions } from './html-types.js';
17
17
  //# sourceMappingURL=html-result.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"html-result.d.ts","sourceRoot":"","sources":["html-result.js"],"names":[],"mappings":"AAqCA,oCAHW,OAAO,GACL,KAAK,IAAI,UAAU,CAQ/B;AAxCD,6CAA4D;AAE5D;IAOE,sBALW,gBAAgB,iBAChB,gBAAgB,EAAE,WAClB,aAAa,UACb,CAAC,MAAM,EAAE,UAAU,KAAK,MAAM,EAQxC;IAJC,2BAAwB;IACxB,kCAAkC;IAClC,uBAAsB;IACtB,iBAPkB,UAAU,KAAK,MAAM,CAOnB;IAGtB,mBAEC;IAED,kBAEC;IAED,+BAEC;IAjBC,4BAA6B;CAkBhC;sCA/BoD,iBAAiB;sCAChC,iBAAiB;mCADF,iBAAiB"}
1
+ {"version":3,"file":"html-result.d.ts","sourceRoot":"","sources":["html-result.js"],"names":[],"mappings":"AAoCA,oCAHW,OAAO,GACL,KAAK,IAAI,UAAU,CAQ/B;AAxCD,6CAA4D;AAE5D;IAOE,sBALW,gBAAgB,iBAChB,gBAAgB,EAAE,WAClB,aAAa,UACb,CAAC,MAAM,EAAE,UAAU,KAAK,MAAM,EAQxC;IAJC,2BAAwB;IACxB,kCAAkC;IAClC,uBAAsB;IACtB,iBAPkB,UAAU,KAAK,MAAM,CAOnB;IAGtB,mBAEC;IAED,kBAEC;IAED,+BAEC;IAjBC,4BAA6B;CAkBhC;sCA9BsE,iBAAiB;sCAAjB,iBAAiB;mCAAjB,iBAAiB"}
@@ -1,5 +1,4 @@
1
- /** @import { CompiledTemplate, RenderOptions } from './create-tag.js' */
2
- /** @import { HtmlSubstitution } from './html-types.js' */
1
+ /** @import { CompiledTemplate, HtmlSubstitution, RenderOptions } from './html-types.js' */
3
2
 
4
3
  export const htmlResultSymbol = Symbol('fragtml.htmlResult')
5
4
 
@@ -1,9 +1,30 @@
1
- import type { FragmentBoundary } from './fragment.js';
2
1
  import type { HtmlResult } from './html-result.js';
3
2
  import type { RawHtml } from './raw.js';
3
+ export type FragmentStartBoundary<FragmentId extends string = string> = {
4
+ readonly kind: 'start';
5
+ readonly id: FragmentId;
6
+ };
7
+ export type FragmentEndBoundary = {
8
+ readonly kind: 'end';
9
+ };
10
+ export type FragmentBoundary<FragmentId extends string = string> = FragmentStartBoundary<FragmentId> | FragmentEndBoundary;
11
+ export type FragmentHelpers<FragmentId extends string = string> = {
12
+ start: (id: FragmentId) => FragmentStartBoundary<FragmentId>;
13
+ end: FragmentEndBoundary;
14
+ };
15
+ export type RenderOptions<FragmentId extends string = string> = {
16
+ fragmentId?: FragmentId | undefined;
17
+ };
18
+ export type CompiledTemplate = {
19
+ strings: readonly string[];
20
+ };
4
21
  export type HtmlPrimitiveSubstitution = string | number | bigint | boolean | null | undefined;
5
22
  export type HtmlArrayScalarSubstitution = HtmlPrimitiveSubstitution | HtmlResult | RawHtml;
6
23
  export type HtmlArraySubstitution = HtmlArrayScalarSubstitution | readonly HtmlArraySubstitution[];
7
- export type HtmlSubstitution = HtmlArraySubstitution | FragmentBoundary;
24
+ export type HtmlSubstitution<FragmentId extends string = string> = HtmlArraySubstitution | FragmentBoundary<FragmentId>;
8
25
  export type TemplateStrings = TemplateStringsArray | readonly string[];
26
+ export type HtmlTag<FragmentId extends string = string> = ((strings: TemplateStrings, ...substitutions: HtmlSubstitution<FragmentId>[]) => HtmlResult) & (<NextFragmentId extends string = string>(options?: RenderOptions<NextFragmentId> | string) => HtmlTag<NextFragmentId>) & {
27
+ fragment: FragmentHelpers<FragmentId>;
28
+ raw: (value: unknown) => RawHtml;
29
+ };
9
30
  //# sourceMappingURL=html-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"html-types.d.ts","sourceRoot":"","sources":["html-types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAEvC,MAAM,MAAM,yBAAyB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAA;AAC7F,MAAM,MAAM,2BAA2B,GAAG,yBAAyB,GAAG,UAAU,GAAG,OAAO,CAAA;AAC1F,MAAM,MAAM,qBAAqB,GAAG,2BAA2B,GAAG,SAAS,qBAAqB,EAAE,CAAA;AAClG,MAAM,MAAM,gBAAgB,GAAG,qBAAqB,GAAG,gBAAgB,CAAA;AACvE,MAAM,MAAM,eAAe,GAAG,oBAAoB,GAAG,SAAS,MAAM,EAAE,CAAA"}
1
+ {"version":3,"file":"html-types.d.ts","sourceRoot":"","sources":["html-types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAEvC,MAAM,MAAM,qBAAqB,CAAC,UAAU,SAAS,MAAM,GAAG,MAAM,IAAI;IACtE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAA;CACxB,CAAA;AACD,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CACrB,CAAA;AACD,MAAM,MAAM,gBAAgB,CAAC,UAAU,SAAS,MAAM,GAAG,MAAM,IAC7D,qBAAqB,CAAC,UAAU,CAAC,GAAG,mBAAmB,CAAA;AACzD,MAAM,MAAM,eAAe,CAAC,UAAU,SAAS,MAAM,GAAG,MAAM,IAAI;IAChE,KAAK,EAAE,CAAC,EAAE,EAAE,UAAU,KAAK,qBAAqB,CAAC,UAAU,CAAC,CAAA;IAC5D,GAAG,EAAE,mBAAmB,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,aAAa,CAAC,UAAU,SAAS,MAAM,GAAG,MAAM,IAAI;IAC9D,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAA;AAC7F,MAAM,MAAM,2BAA2B,GAAG,yBAAyB,GAAG,UAAU,GAAG,OAAO,CAAA;AAC1F,MAAM,MAAM,qBAAqB,GAC/B,2BAA2B,GAAG,SAAS,qBAAqB,EAAE,CAAA;AAChE,MAAM,MAAM,gBAAgB,CAAC,UAAU,SAAS,MAAM,GAAG,MAAM,IAC7D,qBAAqB,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAA;AACtD,MAAM,MAAM,eAAe,GAAG,oBAAoB,GAAG,SAAS,MAAM,EAAE,CAAA;AACtE,MAAM,MAAM,OAAO,CAAC,UAAU,SAAS,MAAM,GAAG,MAAM,IACpD,CAAC,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,aAAa,EAAE,gBAAgB,CAAC,UAAU,CAAC,EAAE,KAAK,UAAU,CAAC,GAC5F,CAAC,CAAC,cAAc,SAAS,MAAM,GAAG,MAAM,EACtC,OAAO,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,GAAG,MAAM,KAC7C,OAAO,CAAC,cAAc,CAAC,CAAC,GAAG;IAC9B,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,CAAA;IACrC,GAAG,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAA;CACjC,CAAA"}
package/lib/html-types.ts CHANGED
@@ -1,10 +1,41 @@
1
1
  // Type exports only. Do not add runtime implementations to this module.
2
- import type { FragmentBoundary } from './fragment.js'
3
2
  import type { HtmlResult } from './html-result.js'
4
3
  import type { RawHtml } from './raw.js'
5
4
 
5
+ export type FragmentStartBoundary<FragmentId extends string = string> = {
6
+ readonly kind: 'start'
7
+ readonly id: FragmentId
8
+ }
9
+ export type FragmentEndBoundary = {
10
+ readonly kind: 'end'
11
+ }
12
+ export type FragmentBoundary<FragmentId extends string = string> =
13
+ FragmentStartBoundary<FragmentId> | FragmentEndBoundary
14
+ export type FragmentHelpers<FragmentId extends string = string> = {
15
+ start: (id: FragmentId) => FragmentStartBoundary<FragmentId>
16
+ end: FragmentEndBoundary
17
+ }
18
+
19
+ export type RenderOptions<FragmentId extends string = string> = {
20
+ fragmentId?: FragmentId | undefined
21
+ }
22
+
23
+ export type CompiledTemplate = {
24
+ strings: readonly string[]
25
+ }
26
+
6
27
  export type HtmlPrimitiveSubstitution = string | number | bigint | boolean | null | undefined
7
28
  export type HtmlArrayScalarSubstitution = HtmlPrimitiveSubstitution | HtmlResult | RawHtml
8
- export type HtmlArraySubstitution = HtmlArrayScalarSubstitution | readonly HtmlArraySubstitution[]
9
- export type HtmlSubstitution = HtmlArraySubstitution | FragmentBoundary
29
+ export type HtmlArraySubstitution =
30
+ HtmlArrayScalarSubstitution | readonly HtmlArraySubstitution[]
31
+ export type HtmlSubstitution<FragmentId extends string = string> =
32
+ HtmlArraySubstitution | FragmentBoundary<FragmentId>
10
33
  export type TemplateStrings = TemplateStringsArray | readonly string[]
34
+ export type HtmlTag<FragmentId extends string = string> =
35
+ ((strings: TemplateStrings, ...substitutions: HtmlSubstitution<FragmentId>[]) => HtmlResult) &
36
+ (<NextFragmentId extends string = string>(
37
+ options?: RenderOptions<NextFragmentId> | string
38
+ ) => HtmlTag<NextFragmentId>) & {
39
+ fragment: FragmentHelpers<FragmentId>
40
+ raw: (value: unknown) => RawHtml
41
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fragtml",
3
3
  "description": "WIP - nothing to see here",
4
- "version": "0.0.2",
4
+ "version": "0.0.4",
5
5
  "author": "Bret Comnes <bcomnes@gmail.com> (https://bret.io)",
6
6
  "bugs": {
7
7
  "url": "https://github.com/bcomnes/fragtml/issues"
@@ -30,6 +30,8 @@
30
30
  "index.js",
31
31
  "index.d.ts",
32
32
  "index.d.ts.map",
33
+ "types.d.ts",
34
+ "types.d.ts.map",
33
35
  "lib"
34
36
  ],
35
37
  "repository": {
package/types.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export type { CompiledTemplate, FragmentBoundary, FragmentEndBoundary, FragmentHelpers, FragmentStartBoundary, HtmlArrayScalarSubstitution, HtmlArraySubstitution, HtmlPrimitiveSubstitution, HtmlSubstitution, HtmlTag, RenderOptions, TemplateStrings } from './lib/html-types.js';
2
+ export type { HtmlResult } from './lib/html-result.js';
3
+ export type { RawHtml } from './lib/raw.js';
4
+ //# sourceMappingURL=types.d.ts.map
package/types.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AACA,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,EACrB,yBAAyB,EACzB,gBAAgB,EAChB,OAAO,EACP,aAAa,EACb,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA"}