@jay-framework/runtime 0.16.4 → 0.17.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/dist/index.d.ts CHANGED
@@ -65,6 +65,7 @@ type PreRenderElement<ViewState extends object, Refs extends object, JayElementT
65
65
  type RenderElement<ViewState extends object, Refs extends object, JayElementT extends JayElement<ViewState, Refs>> = (vs: ViewState) => JayElementT;
66
66
  interface RenderElementOptions {
67
67
  eventWrapper?: JayEventHandlerWrapper<any, any, any>;
68
+ sanitizeHtml?: (html: string) => string;
68
69
  }
69
70
  type JayEventHandlerWrapper<EventType, ViewState, Returns> = (orig: JayEventHandler<EventType, ViewState, Returns>, event: JayEvent<EventType, ViewState>) => Returns;
70
71
  interface ContextMarker<ContextType> {
@@ -505,11 +506,18 @@ interface WithData<ParentViewState, ChildViewState> {
505
506
  }
506
507
  declare function mkUpdateCollection<ViewState, Item>(child: ForEach<ViewState, Item>, group: KindergartenGroup): [updateFunc<ViewState>, MountFunc, MountFunc];
507
508
  declare function dynamicText<ViewState>(textContent: (vs: ViewState) => string | number | boolean): TextElement<ViewState>;
508
- type ElementChildren<ViewState> = Array<BaseJayElement<ViewState> | TextElement<ViewState> | string>;
509
+ interface HtmlContent<ViewState> {
510
+ __htmlContent: true;
511
+ htmlAccessor: (vs: ViewState) => string;
512
+ }
513
+ declare function dynamicHtml<ViewState>(htmlContent: (vs: ViewState) => string): HtmlContent<ViewState>;
514
+ declare function isHtmlContent(child: any): child is HtmlContent<any>;
515
+ declare function applyHtmlContent<ViewState>(child: HtmlContent<ViewState>, parentElement: Element, updates: updateFunc<ViewState>[], skipInitial?: boolean): void;
516
+ type ElementChildren<ViewState> = Array<BaseJayElement<ViewState> | TextElement<ViewState> | HtmlContent<ViewState> | string>;
509
517
  declare const element: <ViewState>(tagName: string, attributes: Attributes<ViewState>, children?: ElementChildren<ViewState>, ref?: PrivateRef<ViewState, BaseJayElement<ViewState>>) => BaseJayElement<ViewState>;
510
518
  declare const svgElement: <ViewState>(tagName: string, attributes: Attributes<ViewState>, children?: ElementChildren<ViewState>, ref?: PrivateRef<ViewState, BaseJayElement<ViewState>>) => BaseJayElement<ViewState>;
511
519
  declare const mathMLElement: <ViewState>(tagName: string, attributes: Attributes<ViewState>, children?: ElementChildren<ViewState>, ref?: PrivateRef<ViewState, BaseJayElement<ViewState>>) => BaseJayElement<ViewState>;
512
- type DynamicElementChildren<ViewState> = Array<Conditional<ViewState> | ForEach<ViewState, any> | WithData<ViewState, any> | TextElement<ViewState> | BaseJayElement<ViewState> | When<ViewState, any> | string>;
520
+ type DynamicElementChildren<ViewState> = Array<Conditional<ViewState> | ForEach<ViewState, any> | WithData<ViewState, any> | TextElement<ViewState> | BaseJayElement<ViewState> | HtmlContent<ViewState> | When<ViewState, any> | string>;
513
521
  declare const dynamicElementNS: (ns: string) => <ViewState>(tagName: string, attributes: Attributes<ViewState>, children?: DynamicElementChildren<ViewState>, ref?: PrivateRef<ViewState, BaseJayElement<ViewState>>) => BaseJayElement<ViewState>;
514
522
  declare const dynamicElement: <ViewState>(tagName: string, attributes: Attributes<ViewState>, children?: DynamicElementChildren<ViewState>, ref?: PrivateRef<ViewState, BaseJayElement<ViewState>>) => BaseJayElement<ViewState>;
515
523
  declare const svgDynamicElement: <ViewState>(tagName: string, attributes: Attributes<ViewState>, children?: DynamicElementChildren<ViewState>, ref?: PrivateRef<ViewState, BaseJayElement<ViewState>>) => BaseJayElement<ViewState>;
@@ -571,7 +579,8 @@ declare class ConstructContext<ViewState> {
571
579
  private readonly _coordinateMap?;
572
580
  private readonly _rootElement?;
573
581
  private readonly _dataIds;
574
- constructor(data: ViewState, forStaticElements?: boolean, coordinateBase?: Coordinate, coordinateMap?: Map<string, Element[]>, rootElement?: Element, dataIds?: Coordinate);
582
+ readonly sanitizeHtml?: (html: string) => string;
583
+ constructor(data: ViewState, forStaticElements?: boolean, coordinateBase?: Coordinate, coordinateMap?: Map<string, Element[]>, rootElement?: Element, dataIds?: Coordinate, sanitizeHtml?: (html: string) => string);
575
584
  get currData(): ViewState;
576
585
  /** The accumulated trackBy values from ancestor forEach loops (for __headlessInstances key lookup) */
577
586
  get dataIds(): Coordinate;
@@ -620,7 +629,7 @@ declare class ConstructContext<ViewState> {
620
629
  * hydrateForEach due to JavaScript argument evaluation order).
621
630
  */
622
631
  peekCoordinate(key: string): Element | undefined;
623
- static withRootContext<ViewState, Refs>(viewState: ViewState, refManager: ReferencesManager, elementConstructor: () => BaseJayElement<ViewState>): JayElement<ViewState, Refs>;
632
+ static withRootContext<ViewState, Refs>(viewState: ViewState, refManager: ReferencesManager, elementConstructor: () => BaseJayElement<ViewState>, sanitizeHtml?: (html: string) => string): JayElement<ViewState, Refs>;
624
633
  /**
625
634
  * Hydrate a child component's inline template within the parent's coordinate scope.
626
635
  *
@@ -679,7 +688,7 @@ declare function adoptText<ViewState>(coordinate: string, accessor: (vs: ViewSta
679
688
  * Hydration counterpart to element() — adopts server-rendered HTML and wires
680
689
  * up dynamic attribute bindings and children.
681
690
  */
682
- declare function adoptElement<ViewState>(coordinate: string, attributes: Attributes<ViewState>, children?: BaseJayElement<ViewState>[], ref?: PrivateRef<ViewState, BaseJayElement<ViewState>>): BaseJayElement<ViewState>;
691
+ declare function adoptElement<ViewState>(coordinate: string, attributes: Attributes<ViewState>, children?: (BaseJayElement<ViewState> | HtmlContent<ViewState>)[], ref?: PrivateRef<ViewState, BaseJayElement<ViewState>>): BaseJayElement<ViewState>;
683
692
  /**
684
693
  * Adopt an existing element that has interactive children (forEach/conditional).
685
694
  *
@@ -733,4 +742,4 @@ declare function hydrateForEach<ViewState, Item>(accessor: (vs: ViewState) => It
733
742
  */
734
743
  declare function childCompHydrate<ParentVS, Props, ChildT, ChildElement extends BaseJayElement<ChildT>, ChildComp extends JayComponent<Props, ChildT, ChildElement>>(compCreator: JayComponentConstructor<Props>, getProps: (t: ParentVS) => Props, scopeRootCoordinate?: string, ref?: PrivateRef<ParentVS, ChildComp>): BaseJayElement<ParentVS>;
735
744
 
736
- export { type Attribute, type Attributes, type BaseJayElement, BaseReferencesManager, type ComponentCollectionProxy, ComponentCollectionRefImpl, type ComponentProxy, ComponentRefImpl, ComponentRefsImpl, type Conditional, ConstructContext, type ContextMarker, type Coordinate, type DynamicAttributeOrProperty, EVENT_TRAP, type ElementFrom, type EventEmitter, type EventTypeFrom, type ExtractFastViewState, type ExtractInteractiveViewState, type ExtractProps, type ExtractRefs, type ExtractSlowViewState, type ExtractViewState, type ForEach, GetTrapProxy, type GlobalJayEvents, type HTMLElementCollectionProxy, type HTMLElementCollectionProxyTarget, type HTMLElementProxy, type HTMLElementProxyTarget, type HTMLNativeExec, type HeadLink, type JayComponent, type JayComponentConstructor, type JayContract, type JayElement, type JayEvent, type JayEventHandler, type JayEventHandlerWrapper, type JayLog, type JayNativeEventBuilder, type JayNativeFunction, LogType, type ManagedRefConstructor, ManagedRefType, type ManagedRefs, type MapEventEmitterViewState, type MountFunc, type OnlyEventEmitters, type PreRenderElement, type PrivateRef, type PrivateRefConstructor, PrivateRefs, type PropsFrom, ReferencesManager, type RenderElement, type RenderElementOptions, STATIC, type TextElement, VIEW_STATE_CHANGE_EVENT, type ViewStateFrom, type When, WhenRole, type WithData, adoptDynamicElement, adoptElement, adoptText, booleanAttribute, childComp, childCompHydrate, clearGlobalContextRegistry, conditional, createJayContext, currentConstructionContext, defaultEventWrapper, dynamicAttribute, dynamicElement, dynamicElementNS, dynamicProperty, dynamicText, element, findContext, forEach, hydrateConditional, hydrateForEach, injectHeadLinks, isCondition, isForEach, isWhen, isWithData, jayLog, mathMLDynamicElement, mathMLElement, mkUpdateCollection, noop, noopMount, noopUpdate, normalizeMount, normalizeUpdates, pending, registerGlobalContext, rejected, resolved, restoreContext, saveContext, slowForEachItem, svgDynamicElement, svgElement, type updateFunc, useContext, useGlobalContext, withContext, withData };
745
+ export { type Attribute, type Attributes, type BaseJayElement, BaseReferencesManager, type ComponentCollectionProxy, ComponentCollectionRefImpl, type ComponentProxy, ComponentRefImpl, ComponentRefsImpl, type Conditional, ConstructContext, type ContextMarker, type Coordinate, type DynamicAttributeOrProperty, EVENT_TRAP, type ElementFrom, type EventEmitter, type EventTypeFrom, type ExtractFastViewState, type ExtractInteractiveViewState, type ExtractProps, type ExtractRefs, type ExtractSlowViewState, type ExtractViewState, type ForEach, GetTrapProxy, type GlobalJayEvents, type HTMLElementCollectionProxy, type HTMLElementCollectionProxyTarget, type HTMLElementProxy, type HTMLElementProxyTarget, type HTMLNativeExec, type HeadLink, type HtmlContent, type JayComponent, type JayComponentConstructor, type JayContract, type JayElement, type JayEvent, type JayEventHandler, type JayEventHandlerWrapper, type JayLog, type JayNativeEventBuilder, type JayNativeFunction, LogType, type ManagedRefConstructor, ManagedRefType, type ManagedRefs, type MapEventEmitterViewState, type MountFunc, type OnlyEventEmitters, type PreRenderElement, type PrivateRef, type PrivateRefConstructor, PrivateRefs, type PropsFrom, ReferencesManager, type RenderElement, type RenderElementOptions, STATIC, type TextElement, VIEW_STATE_CHANGE_EVENT, type ViewStateFrom, type When, WhenRole, type WithData, adoptDynamicElement, adoptElement, adoptText, applyHtmlContent, booleanAttribute, childComp, childCompHydrate, clearGlobalContextRegistry, conditional, createJayContext, currentConstructionContext, defaultEventWrapper, dynamicAttribute, dynamicElement, dynamicElementNS, dynamicHtml, dynamicProperty, dynamicText, element, findContext, forEach, hydrateConditional, hydrateForEach, injectHeadLinks, isCondition, isForEach, isHtmlContent, isWhen, isWithData, jayLog, mathMLDynamicElement, mathMLElement, mkUpdateCollection, noop, noopMount, noopUpdate, normalizeMount, normalizeUpdates, pending, registerGlobalContext, rejected, resolved, restoreContext, saveContext, slowForEachItem, svgDynamicElement, svgElement, type updateFunc, useContext, useGlobalContext, withContext, withData };
package/dist/index.js CHANGED
@@ -175,10 +175,11 @@ function wrapWithModifiedCheck(initialData, baseJayElement) {
175
175
  return baseJayElement;
176
176
  }
177
177
  class ConstructContext {
178
- constructor(data, forStaticElements = true, coordinateBase = [], coordinateMap, rootElement, dataIds) {
178
+ constructor(data, forStaticElements = true, coordinateBase = [], coordinateMap, rootElement, dataIds, sanitizeHtml) {
179
179
  __publicField(this, "_coordinateMap");
180
180
  __publicField(this, "_rootElement");
181
181
  __publicField(this, "_dataIds");
182
+ __publicField(this, "sanitizeHtml");
182
183
  __publicField(this, "coordinate", (refName) => {
183
184
  return [...this.coordinateBase, refName];
184
185
  });
@@ -188,6 +189,7 @@ class ConstructContext {
188
189
  this._coordinateMap = coordinateMap;
189
190
  this._rootElement = rootElement;
190
191
  this._dataIds = dataIds ?? coordinateBase;
192
+ this.sanitizeHtml = sanitizeHtml;
191
193
  }
192
194
  get currData() {
193
195
  return this.data;
@@ -213,7 +215,8 @@ class ConstructContext {
213
215
  [...this.coordinateBase, id],
214
216
  this._coordinateMap,
215
217
  this._rootElement,
216
- [...this._dataIds, id]
218
+ [...this._dataIds, id],
219
+ this.sanitizeHtml
217
220
  );
218
221
  }
219
222
  /**
@@ -232,7 +235,8 @@ class ConstructContext {
232
235
  this.coordinateBase,
233
236
  localMap,
234
237
  scopeRootElement,
235
- this._dataIds
238
+ this._dataIds,
239
+ this.sanitizeHtml
236
240
  );
237
241
  }
238
242
  forAsync(childViewState) {
@@ -242,7 +246,8 @@ class ConstructContext {
242
246
  [...this.coordinateBase],
243
247
  this._coordinateMap,
244
248
  this._rootElement,
245
- this._dataIds
249
+ this._dataIds,
250
+ this.sanitizeHtml
246
251
  );
247
252
  }
248
253
  /** Whether this context is in hydration mode (adopting existing DOM). */
@@ -286,8 +291,16 @@ class ConstructContext {
286
291
  return void 0;
287
292
  return elements[0];
288
293
  }
289
- static withRootContext(viewState, refManager, elementConstructor) {
290
- let context = new ConstructContext(viewState);
294
+ static withRootContext(viewState, refManager, elementConstructor, sanitizeHtml) {
295
+ let context = new ConstructContext(
296
+ viewState,
297
+ true,
298
+ [],
299
+ void 0,
300
+ void 0,
301
+ void 0,
302
+ sanitizeHtml
303
+ );
291
304
  let element2 = withContext(
292
305
  CONSTRUCTION_CONTEXT_MARKER,
293
306
  context,
@@ -716,9 +729,35 @@ function dynamicText(textContent) {
716
729
  unmount: noopMount
717
730
  };
718
731
  }
732
+ function dynamicHtml(htmlContent) {
733
+ return { __htmlContent: true, htmlAccessor: htmlContent };
734
+ }
735
+ function isHtmlContent(child) {
736
+ return child && child.__htmlContent;
737
+ }
738
+ function applyHtmlContent(child, parentElement, updates, skipInitial = false) {
739
+ const accessor = child.htmlAccessor;
740
+ const context = currentConstructionContext();
741
+ const sanitize = context.sanitizeHtml;
742
+ let content = accessor(context.currData);
743
+ if (!skipInitial) {
744
+ parentElement.innerHTML = sanitize ? sanitize(content) : content;
745
+ }
746
+ updates.push((newData) => {
747
+ const newContent = accessor(newData);
748
+ if (newContent !== content) {
749
+ parentElement.innerHTML = sanitize ? sanitize(newContent) : newContent;
750
+ content = newContent;
751
+ }
752
+ });
753
+ }
719
754
  const elementNS = (ns) => (tagName, attributes, children = [], ref) => {
720
755
  let { e, updates, mounts, unmounts } = createBaseElement(ns, tagName, attributes, ref);
721
756
  children.forEach((child) => {
757
+ if (isHtmlContent(child)) {
758
+ applyHtmlContent(child, e, updates);
759
+ return;
760
+ }
722
761
  if (typeof child === "string")
723
762
  child = text(child);
724
763
  e.append(child.dom);
@@ -746,6 +785,10 @@ const dynamicElementNS = (ns) => (tagName, attributes, children = [], ref) => {
746
785
  let { e, updates, mounts, unmounts } = createBaseElement(ns, tagName, attributes, ref);
747
786
  let kindergarten = new Kindergarten(e);
748
787
  children.forEach((child) => {
788
+ if (isHtmlContent(child)) {
789
+ applyHtmlContent(child, e, updates);
790
+ return;
791
+ }
749
792
  if (typeof child === "string")
750
793
  child = text(child);
751
794
  let group = kindergarten.newGroup();
@@ -1303,6 +1346,10 @@ function adoptElement(coordinate, attributes, children = [], ref) {
1303
1346
  return NOOP_ELEMENT;
1304
1347
  const { element: element2, updates, mounts, unmounts } = base;
1305
1348
  for (const child of children) {
1349
+ if (isHtmlContent(child)) {
1350
+ applyHtmlContent(child, element2, updates, true);
1351
+ continue;
1352
+ }
1306
1353
  collectChild(child, updates, mounts, unmounts);
1307
1354
  }
1308
1355
  return {
@@ -1594,6 +1641,7 @@ export {
1594
1641
  adoptDynamicElement,
1595
1642
  adoptElement,
1596
1643
  adoptText,
1644
+ applyHtmlContent,
1597
1645
  booleanAttribute,
1598
1646
  childComp,
1599
1647
  childCompHydrate,
@@ -1605,6 +1653,7 @@ export {
1605
1653
  dynamicAttribute,
1606
1654
  dynamicElement,
1607
1655
  dynamicElementNS,
1656
+ dynamicHtml,
1608
1657
  dynamicProperty,
1609
1658
  dynamicText,
1610
1659
  element,
@@ -1615,6 +1664,7 @@ export {
1615
1664
  injectHeadLinks,
1616
1665
  isCondition,
1617
1666
  isForEach,
1667
+ isHtmlContent,
1618
1668
  isWhen,
1619
1669
  isWithData,
1620
1670
  jayLog,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/runtime",
3
- "version": "0.16.4",
3
+ "version": "0.17.0",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",
@@ -23,11 +23,11 @@
23
23
  "test:watch": "vitest"
24
24
  },
25
25
  "dependencies": {
26
- "@jay-framework/list-compare": "^0.16.4",
27
- "@jay-framework/reactive": "^0.16.4"
26
+ "@jay-framework/list-compare": "^0.17.0",
27
+ "@jay-framework/reactive": "^0.17.0"
28
28
  },
29
29
  "devDependencies": {
30
- "@jay-framework/dev-environment": "^0.16.4",
30
+ "@jay-framework/dev-environment": "^0.17.0",
31
31
  "@testing-library/jest-dom": "^6.2.0",
32
32
  "@types/jsdom": "^21.1.6",
33
33
  "@types/node": "^20.11.5",