From 996655446a4e2d8f634318d9834fd4a2a899658c Mon Sep 17 00:00:00 2001 From: Jane Chu <7559015+janechu@users.noreply.github.com> Date: Fri, 29 May 2026 14:47:02 -0700 Subject: [PATCH] docs(fast-element): clean up API report surface Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- packages/fast-element/docs/api-report.api.md | 81 ++++++++-------- .../docs/declarative/api-report.api.md | 62 ++++++++++-- .../docs/hydration/api-report.api.md | 38 ++++++++ packages/fast-element/src/binding/binding.ts | 30 +++++- packages/fast-element/src/binding/one-time.ts | 2 +- packages/fast-element/src/binding/one-way.ts | 2 +- packages/fast-element/src/binding/signal.ts | 2 +- packages/fast-element/src/binding/two-way.ts | 2 +- .../fast-element/src/components/attributes.ts | 2 +- .../src/components/fast-element.ts | 95 +++++++++++++++---- .../fast-element/src/declarative/index.ts | 12 ++- packages/fast-element/src/dom-policy.ts | 34 ++++++- packages/fast-element/src/dom.ts | 29 +----- packages/fast-element/src/hydration.ts | 11 ++- packages/fast-element/src/index.ts | 13 ++- packages/fast-element/src/platform.ts | 4 +- .../fast-element/src/templating/compiler.ts | 3 +- .../src/templating/html-binding-directive.ts | 12 ++- .../src/templating/html-directive.ts | 3 +- .../fast-element/src/templating/render.ts | 4 +- .../fast-element/src/templating/template.ts | 2 +- 21 files changed, 323 insertions(+), 120 deletions(-) diff --git a/packages/fast-element/docs/api-report.api.md b/packages/fast-element/docs/api-report.api.md index 8e3e048863c..4d0ee2c9b95 100644 --- a/packages/fast-element/docs/api-report.api.md +++ b/packages/fast-element/docs/api-report.api.md @@ -80,25 +80,17 @@ export class AttributeDefinition implements Accessor { setValue(source: HTMLElement, newValue: any): void; } -// Warning: (ae-forgotten-export) The symbol "reflectMode" needs to be exported by the entry point index.d.ts -// Warning: (ae-forgotten-export) The symbol "booleanMode" needs to be exported by the entry point index.d.ts -// // @public -export type AttributeMode = typeof reflectMode | typeof booleanMode | "fromView"; +export type AttributeMode = "reflect" | "boolean" | "fromView"; // @public export abstract class Binding { - constructor(evaluate: Expression, policy?: DOMPolicy_2 | undefined, isVolatile?: boolean); + constructor(evaluate: Expression, policy?: DOMPolicy, isVolatile?: boolean); abstract createObserver(subscriber: Subscriber, directive: BindingDirective): ExpressionObserver; - // (undocumented) evaluate: Expression; - // (undocumented) isVolatile: boolean; options?: any; - // Warning: (ae-forgotten-export) The symbol "DOMPolicy_2" needs to be exported by the entry point index.d.ts - // - // (undocumented) - policy?: DOMPolicy_2 | undefined; + policy?: DOMPolicy; } // @public @@ -171,16 +163,16 @@ export type Class = C & Constructable & { export type CompilationStrategy = ( html: string | HTMLTemplateElement, factories: Record, -policy: DOMPolicy_2) => HTMLTemplateCompilationResult; +policy: DOMPolicy) => HTMLTemplateCompilationResult; // @public export type CompiledViewBehaviorFactory = Required; // @public export const Compiler: { - compile(html: string | HTMLTemplateElement, factories: Record, policy?: DOMPolicy_2): HTMLTemplateCompilationResult; + compile(html: string | HTMLTemplateElement, factories: Record, policy?: DOMPolicy): HTMLTemplateCompilationResult; setDefaultStrategy(strategy: CompilationStrategy): void; - aggregate(parts: (string | ViewBehaviorFactory)[], policy?: DOMPolicy_2): ViewBehaviorFactory; + aggregate(parts: (string | ViewBehaviorFactory)[], policy?: DOMPolicy): ViewBehaviorFactory; }; // @public @@ -305,8 +297,8 @@ export interface Disposable { // @public export const DOM: Readonly<{ - readonly policy: DOMPolicy_2; - setPolicy(value: DOMPolicy_2): void; + readonly policy: DOMPolicy; + setPolicy(value: DOMPolicy): void; setAttribute(element: HTMLElement, attributeName: string, value: any): void; setBooleanAttribute(element: HTMLElement, attributeName: string, value: boolean): void; }>; @@ -344,9 +336,15 @@ export type DOMGuards = { aspects: DOMAspectGuards; }; +// @public +export interface DOMPolicy { + createHTML(value: string): string; + protect(tagName: string | null, aspect: DOMAspect, aspectName: string, sink: DOMSink): DOMSink; +} + // @public export const DOMPolicy: Readonly<{ - create(options?: DOMPolicyOptions): Readonly; + create(options?: DOMPolicyOptions): Readonly; }>; // @public @@ -535,12 +533,19 @@ export interface FASTElement extends HTMLElement { } // @public -export const FASTElement: { +export const FASTElement: FASTElementConstructor; + +// @public +export interface FASTElementConstructor { new (): FASTElement; - define: typeof define; - compose: typeof compose; - from: typeof from; -}; + compose = Constructable>(this: TType, nameOrDef: string | PartialFASTElementDefinition): Promise>; + compose = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition): Promise>; + define = Constructable>(this: TType, nameOrDef: string | PartialFASTElementDefinition, extensions?: FASTElementExtension[]): Promise; + define = Constructable>(type: TType, nameOrDef?: string | PartialFASTElementDefinition, extensions?: FASTElementExtension[]): Promise; + from(BaseType: TBase): { + new (): InstanceType & FASTElement; + }; +} // @public export class FASTElementDefinition = Constructable> { @@ -608,14 +613,13 @@ export class HTMLBindingDirective implements HTMLDirective, ViewBehaviorFactory, bind(controller: ViewController): void; createBehavior(): ViewBehavior; createHTML(add: AddViewBehaviorFactory): string; - // (undocumented) dataBinding: Binding; // @internal handleChange(binding: Expression, observer: ExpressionObserver): void; // @internal handleEvent(event: Event): void; id: string; - policy: DOMPolicy_2; + policy: DOMPolicy; sourceAspect: string; targetAspect: string; targetNodeId: string; @@ -804,10 +808,10 @@ export interface ObservationRecord { } // @public -export function oneTime(expression: Expression, policy?: DOMPolicy_2): Binding; +export function oneTime(expression: Expression, policy?: DOMPolicy): Binding; // @public -export function oneWay(expression: Expression, policy?: DOMPolicy_2, isVolatile?: boolean): Binding; +export function oneWay(expression: Expression, policy?: DOMPolicy, isVolatile?: boolean): Binding; // @beta export type OwnedState = ReadonlyOwnedState & { @@ -973,7 +977,7 @@ export const Signal: Readonly<{ }>; // @public -export function signal(expression: Expression, options: string | Expression, policy?: DOMPolicy_2): Binding; +export function signal(expression: Expression, options: string | Expression, policy?: DOMPolicy): Binding; // @public export function slotted(propertyOrOptions: (keyof TSource & string) | SlottedDirectiveOptions): CaptureType; @@ -1159,7 +1163,7 @@ export type TrustedTypesPolicy = { }; // @public -export function twoWay(expression: Expression, optionsOrChangeEvent?: TwoWayBindingOptions | string, policy?: DOMPolicy_2, isBindingVolatile?: boolean): Binding; +export function twoWay(expression: Expression, optionsOrChangeEvent?: TwoWayBindingOptions | string, policy?: DOMPolicy, isBindingVolatile?: boolean): Binding; // @public export type TwoWayBindingOptions = { @@ -1177,11 +1181,12 @@ export const TwoWaySettings: Readonly<{ configure(settings: TwoWaySettings): void; }>; -// Warning: (ae-forgotten-export) The symbol "TypeDefinition" needs to be exported by the entry point index.d.ts // Warning: (ae-internal-missing-underscore) The name "TypeRegistry" should be prefixed with an underscore because the declaration is marked as @internal // // @internal -export interface TypeRegistry { +export interface TypeRegistry { // (undocumented) getByType(key: Function): TDefinition | undefined; // (undocumented) @@ -1236,7 +1241,7 @@ export interface ViewBehavior { export interface ViewBehaviorFactory { createBehavior(): ViewBehavior; id?: string; - policy?: DOMPolicy_2; + policy?: DOMPolicy; targetNodeId?: string; targetTagName?: string | null; } @@ -1270,16 +1275,16 @@ export interface ViewController extends Expression // @public export class ViewTemplate implements ElementViewTemplate, SyntheticViewTemplate { - constructor(html: string | HTMLTemplateElement, factories?: Record, policy?: DOMPolicy_2 | undefined); + constructor(html: string | HTMLTemplateElement, factories?: Record, policy?: DOMPolicy | undefined); // @internal (undocumented) compile(): HTMLTemplateCompilationResult; create(hostBindingTarget?: Element): HTMLView; - static create(strings: string[], values: TemplateValue[], policy?: DOMPolicy_2): ViewTemplate; + static create(strings: string[], values: TemplateValue[], policy?: DOMPolicy): ViewTemplate; readonly factories: Record; readonly html: string | HTMLTemplateElement; inline(): CaptureType; render(source: TSource, host: Node, hostBindingTarget?: Element): HTMLView; - withPolicy(policy: DOMPolicy_2): this; + withPolicy(policy: DOMPolicy): this; } // @public @@ -1291,12 +1296,4 @@ export function watch(object: any, subscriber: Subscriber | ((subject: any, args // @public export function when(condition: Expression | boolean, templateOrTemplateBinding: SyntheticViewTemplate | Expression, TParent>, elseTemplateOrTemplateBinding?: SyntheticViewTemplate | Expression, TParent>): CaptureType; -// Warnings were encountered during analysis: -// -// dist/dts/components/fast-element.d.ts:60:5 - (ae-forgotten-export) The symbol "define" needs to be exported by the entry point index.d.ts -// dist/dts/components/fast-element.d.ts:61:5 - (ae-forgotten-export) The symbol "compose" needs to be exported by the entry point index.d.ts -// dist/dts/components/fast-element.d.ts:62:5 - (ae-forgotten-export) The symbol "from" needs to be exported by the entry point index.d.ts - -// (No @packageDocumentation comment for this package) - ``` diff --git a/packages/fast-element/docs/declarative/api-report.api.md b/packages/fast-element/docs/declarative/api-report.api.md index dca727a0dab..43aef16819e 100644 --- a/packages/fast-element/docs/declarative/api-report.api.md +++ b/packages/fast-element/docs/declarative/api-report.api.md @@ -46,11 +46,8 @@ export class AttributeDefinition implements Accessor { setValue(source: HTMLElement, newValue: any): void; } -// Warning: (ae-forgotten-export) The symbol "reflectMode" needs to be exported by the entry point index.d.ts -// Warning: (ae-forgotten-export) The symbol "booleanMode" needs to be exported by the entry point index.d.ts -// // @public -export type AttributeMode = typeof reflectMode | typeof booleanMode | "fromView"; +export type AttributeMode = "reflect" | "boolean" | "fromView"; // @public export type CachedPath = DefaultCachedPath | RepeatCachedPath | AccessCachedPath | EventCachedPath; @@ -102,14 +99,62 @@ export interface DefaultCachedPath extends CachedPathCommon { type: "default"; } +// @public +export const DOMAspect: Readonly<{ + readonly none: 0; + readonly attribute: 1; + readonly booleanAttribute: 2; + readonly property: 3; + readonly content: 4; + readonly tokenList: 5; + readonly event: 6; +}>; + +// @public +export type DOMAspect = (typeof DOMAspect)[Exclude]; + +// @public +export type DOMAspectGuards = { + [DOMAspect.attribute]?: DOMSinkGuards; + [DOMAspect.booleanAttribute]?: DOMSinkGuards; + [DOMAspect.property]?: DOMSinkGuards; + [DOMAspect.content]?: DOMSinkGuards; + [DOMAspect.tokenList]?: DOMSinkGuards; + [DOMAspect.event]?: DOMSinkGuards; +}; + +// @public +export type DOMElementGuards = Record; + +// @public +export type DOMGuards = { + elements: DOMElementGuards; + aspects: DOMAspectGuards; +}; + // @public export interface DOMPolicy { createHTML(value: string): string; - // Warning: (ae-forgotten-export) The symbol "DOMAspect" needs to be exported by the entry point index.d.ts - // Warning: (ae-forgotten-export) The symbol "DOMSink" needs to be exported by the entry point index.d.ts protect(tagName: string | null, aspect: DOMAspect, aspectName: string, sink: DOMSink): DOMSink; } +// @public +export const DOMPolicy: Readonly<{ + create(options?: DOMPolicyOptions): Readonly; +}>; + +// @public +export type DOMPolicyOptions = { + trustedType?: TrustedTypesPolicy; + guards?: Partial; +}; + +// @public +export type DOMSink = (target: Node, aspectName: string, value: any, ...args: any[]) => void; + +// @public +export type DOMSinkGuards = Record DOMSink>; + // @public export class ElementStyles { constructor(styles: ReadonlyArray); @@ -357,6 +402,11 @@ export class TemplateParser { // @public export type TemplateValue = Expression | Binding | HTMLDirective | CaptureType; +// @public +export type TrustedTypesPolicy = { + createHTML(html: string): string; +}; + // @public export interface ValueConverter { fromView(value: any): any; diff --git a/packages/fast-element/docs/hydration/api-report.api.md b/packages/fast-element/docs/hydration/api-report.api.md index 890f9cc360d..9263a30d26f 100644 --- a/packages/fast-element/docs/hydration/api-report.api.md +++ b/packages/fast-element/docs/hydration/api-report.api.md @@ -62,15 +62,48 @@ export const DOMAspect: Readonly<{ // @public export type DOMAspect = (typeof DOMAspect)[Exclude]; +// @public +export type DOMAspectGuards = { + [DOMAspect.attribute]?: DOMSinkGuards; + [DOMAspect.booleanAttribute]?: DOMSinkGuards; + [DOMAspect.property]?: DOMSinkGuards; + [DOMAspect.content]?: DOMSinkGuards; + [DOMAspect.tokenList]?: DOMSinkGuards; + [DOMAspect.event]?: DOMSinkGuards; +}; + +// @public +export type DOMElementGuards = Record; + +// @public +export type DOMGuards = { + elements: DOMElementGuards; + aspects: DOMAspectGuards; +}; + // @public export interface DOMPolicy { createHTML(value: string): string; protect(tagName: string | null, aspect: DOMAspect, aspectName: string, sink: DOMSink): DOMSink; } +// @public +export const DOMPolicy: Readonly<{ + create(options?: DOMPolicyOptions): Readonly; +}>; + +// @public +export type DOMPolicyOptions = { + trustedType?: TrustedTypesPolicy; + guards?: Partial; +}; + // @public export type DOMSink = (target: Node, aspectName: string, value: any, ...args: any[]) => void; +// @public +export type DOMSinkGuards = Record DOMSink>; + // @public export interface ElementView extends View { appendTo(node: Node): void; @@ -221,6 +254,11 @@ export interface SyntheticViewTemplate { inline(): CaptureType; } +// @public +export type TrustedTypesPolicy = { + createHTML(html: string): string; +}; + // @public export interface View extends Disposable_2 { bind(source: TSource, context?: ExecutionContext): void; diff --git a/packages/fast-element/src/binding/binding.ts b/packages/fast-element/src/binding/binding.ts index 6c02df40652..566b5e61447 100644 --- a/packages/fast-element/src/binding/binding.ts +++ b/packages/fast-element/src/binding/binding.ts @@ -1,4 +1,5 @@ -import type { DOMAspect, DOMPolicy } from "../dom.js"; +import type { DOMAspect } from "../dom.js"; +import type { DOMPolicy } from "../dom-policy.js"; import type { Subscriber } from "../observation/notifier.js"; import type { Expression, ExpressionObserver } from "../observation/observable.js"; @@ -35,6 +36,21 @@ export abstract class Binding { */ options?: any; + /** + * Evaluates the binding. + */ + public evaluate: Expression; + + /** + * The security policy to associate with this binding. + */ + public policy?: DOMPolicy; + + /** + * Indicates whether the binding is volatile. + */ + public isVolatile: boolean; + /** * Creates a binding. * @param evaluate - Evaluates the binding. @@ -42,10 +58,14 @@ export abstract class Binding { * @param isVolatile - Indicates whether the binding is volatile. */ public constructor( - public evaluate: Expression, - public policy?: DOMPolicy, - public isVolatile: boolean = false, - ) {} + evaluate: Expression, + policy?: DOMPolicy, + isVolatile: boolean = false, + ) { + this.evaluate = evaluate; + this.policy = policy; + this.isVolatile = isVolatile; + } /** * Creates an observer capable of notifying a subscriber when the output of a binding changes. diff --git a/packages/fast-element/src/binding/one-time.ts b/packages/fast-element/src/binding/one-time.ts index a8a5f344095..af7e9b6a652 100644 --- a/packages/fast-element/src/binding/one-time.ts +++ b/packages/fast-element/src/binding/one-time.ts @@ -1,4 +1,4 @@ -import type { DOMPolicy } from "../dom.js"; +import type { DOMPolicy } from "../dom-policy.js"; import type { Expression, ExpressionController, diff --git a/packages/fast-element/src/binding/one-way.ts b/packages/fast-element/src/binding/one-way.ts index b5faf3d2547..336593eb1b8 100644 --- a/packages/fast-element/src/binding/one-way.ts +++ b/packages/fast-element/src/binding/one-way.ts @@ -1,4 +1,4 @@ -import type { DOMPolicy } from "../dom.js"; +import type { DOMPolicy } from "../dom-policy.js"; import type { Subscriber } from "../observation/notifier.js"; import { type Expression, diff --git a/packages/fast-element/src/binding/signal.ts b/packages/fast-element/src/binding/signal.ts index 35260876091..1d3c4a4b62e 100644 --- a/packages/fast-element/src/binding/signal.ts +++ b/packages/fast-element/src/binding/signal.ts @@ -1,4 +1,4 @@ -import type { DOMPolicy } from "../dom.js"; +import type { DOMPolicy } from "../dom-policy.js"; import { isString } from "../interfaces.js"; import type { Subscriber } from "../observation/notifier.js"; import type { diff --git a/packages/fast-element/src/binding/two-way.ts b/packages/fast-element/src/binding/two-way.ts index 293eaf48077..fdf6e0d0e72 100644 --- a/packages/fast-element/src/binding/two-way.ts +++ b/packages/fast-element/src/binding/two-way.ts @@ -1,4 +1,4 @@ -import type { DOMPolicy } from "../dom.js"; +import type { DOMPolicy } from "../dom-policy.js"; import { isString, Message } from "../interfaces.js"; import type { Subscriber } from "../observation/notifier.js"; import { diff --git a/packages/fast-element/src/components/attributes.ts b/packages/fast-element/src/components/attributes.ts index 9c6f352da52..3029f63c397 100644 --- a/packages/fast-element/src/components/attributes.ts +++ b/packages/fast-element/src/components/attributes.ts @@ -38,7 +38,7 @@ const reflectMode = "reflect"; * changes in the DOM, but does not reflect property changes back. * @public */ -export type AttributeMode = typeof reflectMode | typeof booleanMode | "fromView"; +export type AttributeMode = "reflect" | "boolean" | "fromView"; /** * Metadata used to configure a custom attribute's behavior. diff --git a/packages/fast-element/src/components/fast-element.ts b/packages/fast-element/src/components/fast-element.ts index 37ca2924f95..15172df4366 100644 --- a/packages/fast-element/src/components/fast-element.ts +++ b/packages/fast-element/src/components/fast-element.ts @@ -176,37 +176,96 @@ function from(BaseType: TBase) { } /** - * A minimal base class for FASTElements that also provides - * static helpers for working with FASTElements. + * The FASTElement constructor and static registration helpers. * @public */ -export const FASTElement: { +export interface FASTElementConstructor { + /** + * Creates a FASTElement instance. + */ new (): FASTElement; - define: typeof define; - compose: typeof compose; - from: typeof from; -} = Object.assign(createFASTElement(HTMLElement), { + /** - * Creates a new FASTElement base class inherited from the - * provided base type. - * @param BaseType - The base element type to inherit from. + * Defines a platform custom element based on the provided type and definition. + * @param nameOrDef - The name of the element to define or a definition object. + * @param extensions - Optional callbacks to run before registration. */ - from, + define = Constructable>( + this: TType, + nameOrDef: string | PartialFASTElementDefinition, + extensions?: FASTElementExtension[], + ): Promise; /** * Defines a platform custom element based on the provided type and definition. * @param type - The custom element type to define. - * @param nameOrDef - The name of the element to define or a definition object - * that describes the element to define. + * @param nameOrDef - The name of the element to define or a definition object. + * @param extensions - Optional callbacks to run before registration. + */ + define = Constructable>( + type: TType, + nameOrDef?: string | PartialFASTElementDefinition, + extensions?: FASTElementExtension[], + ): Promise; + + /** + * Composes FASTElement metadata without registering the element. + * @param nameOrDef - The name of the element to compose or a definition object. */ - define, + compose = Constructable>( + this: TType, + nameOrDef: string | PartialFASTElementDefinition, + ): Promise>; /** - * Defines metadata for a FASTElement which can be used to later define the element. - * @public + * Composes FASTElement metadata without registering the element. + * @param type - The custom element type to compose. + * @param nameOrDef - The name of the element to compose or a definition object. */ - compose, -}); + compose = Constructable>( + type: TType, + nameOrDef?: string | PartialFASTElementDefinition, + ): Promise>; + + /** + * Creates a new FASTElement base class inherited from the provided base type. + * @param BaseType - The base element type to inherit from. + */ + from( + BaseType: TBase, + ): { new (): InstanceType & FASTElement }; +} + +/** + * A minimal base class for FASTElements that also provides + * static helpers for working with FASTElements. + * @public + */ +export const FASTElement: FASTElementConstructor = Object.assign( + createFASTElement(HTMLElement), + { + /** + * Creates a new FASTElement base class inherited from the + * provided base type. + * @param BaseType - The base element type to inherit from. + */ + from, + + /** + * Defines a platform custom element based on the provided type and definition. + * @param type - The custom element type to define. + * @param nameOrDef - The name of the element to define or a definition object + * that describes the element to define. + */ + define, + + /** + * Defines metadata for a FASTElement which can be used to later define the element. + * @public + */ + compose, + }, +); /** * Decorator: Defines a platform custom element based on `FASTElement`. diff --git a/packages/fast-element/src/declarative/index.ts b/packages/fast-element/src/declarative/index.ts index 3f4906a62e7..725204e0d25 100644 --- a/packages/fast-element/src/declarative/index.ts +++ b/packages/fast-element/src/declarative/index.ts @@ -28,8 +28,16 @@ export { Schema, schemaRegistry, } from "../components/schema.js"; -export type { DOMPolicy } from "../dom.js"; -export type { Constructable } from "../interfaces.js"; +export type { DOMAspect, DOMSink } from "../dom.js"; +export { + type DOMAspectGuards, + type DOMElementGuards, + type DOMGuards, + DOMPolicy, + type DOMPolicyOptions, + type DOMSinkGuards, +} from "../dom-policy.js"; +export type { Constructable, TrustedTypesPolicy } from "../interfaces.js"; export type { Accessor } from "../observation/observable.js"; export type { ComposableStyles, diff --git a/packages/fast-element/src/dom-policy.ts b/packages/fast-element/src/dom-policy.ts index 7bc35d597a5..5bb97c29dce 100644 --- a/packages/fast-element/src/dom-policy.ts +++ b/packages/fast-element/src/dom-policy.ts @@ -1,7 +1,33 @@ -import { DOMAspect, type DOMSink, type DOMPolicy as IDOMPolicy } from "./dom.js"; +import { DOMAspect, type DOMSink } from "./dom.js"; import { isString, Message, type TrustedTypesPolicy } from "./interfaces.js"; import { FAST } from "./platform.js"; +/** + * A policy that controls whether values can be written to DOM sinks. + * @public + */ +export interface DOMPolicy { + /** + * Creates safe HTML from the provided value. + * @param value - The source to convert to safe HTML. + */ + createHTML(value: string): string; + + /** + * Protects a DOM sink that intends to write to the DOM. + * @param tagName - The tag name for the element to write to. + * @param aspect - The aspect of the DOM to write to. + * @param aspectName - The name of the aspect to write to. + * @param sink - The sink that is used to write to the DOM. + */ + protect( + tagName: string | null, + aspect: DOMAspect, + aspectName: string, + sink: DOMSink, + ): DOMSink; +} + /** * A specific DOM sink guard for a node aspect. * @public @@ -452,13 +478,13 @@ export type DOMPolicyOptions = { * A helper for creating DOM policies. * @public */ -const DOMPolicy = Object.freeze({ +export const DOMPolicy = Object.freeze({ /** * Creates a new DOM Policy object. * @param options - The options to use in creating the policy. * @returns The newly created DOMPolicy. */ - create(options: DOMPolicyOptions = {}): Readonly { + create(options: DOMPolicyOptions = {}): Readonly { const trustedType = options.trustedType ?? createTrustedType(); const guards = createDOMGuards(options.guards ?? {}, defaultDOMGuards); @@ -498,5 +524,3 @@ const DOMPolicy = Object.freeze({ }); }, }); - -export { DOMPolicy }; diff --git a/packages/fast-element/src/dom.ts b/packages/fast-element/src/dom.ts index a5c0baae7cf..d9825fe69b3 100644 --- a/packages/fast-element/src/dom.ts +++ b/packages/fast-element/src/dom.ts @@ -1,3 +1,4 @@ +import type { DOMPolicy as DOMPolicyDefinition } from "./dom-policy.js"; import { Message, type TrustedTypesPolicy } from "./interfaces.js"; import { FAST } from "./platform.js"; @@ -63,34 +64,14 @@ export type DOMSink = ( * A security policy that FAST can use to interact with the DOM. * @public */ -export interface DOMPolicy { - /** - * Creates safe HTML from the provided value. - * @param value - The source to convert to safe HTML. - */ - createHTML(value: string): string; - - /** - * Protects a DOM sink that intends to write to the DOM. - * @param tagName - The tag name for the element to write to. - * @param aspect - The aspect of the DOM to write to. - * @param aspectName - The name of the aspect to write to. - * @param sink - The sink that is used to write to the DOM. - */ - protect( - tagName: string | null, - aspect: DOMAspect, - aspectName: string, - sink: DOMSink, - ): DOMSink; -} +export interface DOMPolicy extends DOMPolicyDefinition {} const createHTML = html => html; const fastTrustedType: TrustedTypesPolicy = globalThis.trustedTypes ? globalThis.trustedTypes.createPolicy("fast-element", { createHTML }) : { createHTML }; -let defaultPolicy: DOMPolicy = Object.freeze({ +let defaultPolicy: DOMPolicyDefinition = Object.freeze({ createHTML(value: string): string { return fastTrustedType.createHTML(value); }, @@ -115,7 +96,7 @@ export const DOM = Object.freeze({ /** * Gets the dom policy used by the templating system. */ - get policy(): DOMPolicy { + get policy(): DOMPolicyDefinition { return defaultPolicy; }, @@ -126,7 +107,7 @@ export const DOM = Object.freeze({ * This API can only be called once, for security reasons. It should be * called by the application developer at the start of their program. */ - setPolicy(value: DOMPolicy): void { + setPolicy(value: DOMPolicyDefinition): void { if (defaultPolicy !== fastPolicy) { throw FAST.error(Message.onlySetDOMPolicyOnce); } diff --git a/packages/fast-element/src/hydration.ts b/packages/fast-element/src/hydration.ts index a9ef628458c..3b840aba0de 100644 --- a/packages/fast-element/src/hydration.ts +++ b/packages/fast-element/src/hydration.ts @@ -7,14 +7,21 @@ export { isHydratable } from "./components/hydration.js"; export { HydrationTracker } from "./components/hydration-tracker.js"; export type { DOMAspect, - DOMPolicy, DOMSink, } from "./dom.js"; +export { + type DOMAspectGuards, + type DOMElementGuards, + type DOMGuards, + DOMPolicy, + type DOMPolicyOptions, + type DOMSinkGuards, +} from "./dom-policy.js"; export type { ViewBehaviorBoundaries, ViewBoundaries, } from "./hydration/target-builder.js"; -export type { Disposable } from "./interfaces.js"; +export type { Disposable, TrustedTypesPolicy } from "./interfaces.js"; export type { ExecutionContext, ExpressionController, diff --git a/packages/fast-element/src/index.ts b/packages/fast-element/src/index.ts index 6422c0b9c99..5f4a2897edf 100644 --- a/packages/fast-element/src/index.ts +++ b/packages/fast-element/src/index.ts @@ -1,3 +1,8 @@ +/** + * Core APIs for building standards-based Web Components with FAST Element. + * @packageDocumentation + */ + // Kernel // Components @@ -40,7 +45,11 @@ export { fastElementRegistry, type TemplateLifecycleCallbacks, } from "./components/fast-definitions.js"; -export { customElement, FASTElement } from "./components/fast-element.js"; +export { + customElement, + FASTElement, + type FASTElementConstructor, +} from "./components/fast-element.js"; export { enableDebug } from "./debug.js"; // Directives export { @@ -69,7 +78,7 @@ export { slotted, } from "./directives/slotted.js"; export { when } from "./directives/when.js"; -export * from "./dom.js"; +export { DOM, DOMAspect, type DOMSink } from "./dom.js"; export { type DOMAspectGuards, type DOMElementGuards, diff --git a/packages/fast-element/src/platform.ts b/packages/fast-element/src/platform.ts index 715e7b45edb..5b7a8cb435b 100644 --- a/packages/fast-element/src/platform.ts +++ b/packages/fast-element/src/platform.ts @@ -61,7 +61,7 @@ export interface TypeDefinition { * Do not change. Part of shared kernel contract. * @internal */ -export interface TypeRegistry { +export interface TypeRegistry { register(definition: TDefinition): boolean; getByType(key: Function): TDefinition | undefined; getForInstance(object: any): TDefinition | undefined; @@ -72,7 +72,7 @@ export interface TypeRegistry { * @internal */ export function createTypeRegistry< - TDefinition extends TypeDefinition, + TDefinition extends { type: Function }, >(): TypeRegistry { const typeToDefinition = new Map(); diff --git a/packages/fast-element/src/templating/compiler.ts b/packages/fast-element/src/templating/compiler.ts index 8f912130af4..2e1fdd80ba2 100644 --- a/packages/fast-element/src/templating/compiler.ts +++ b/packages/fast-element/src/templating/compiler.ts @@ -1,6 +1,7 @@ import { oneTime } from "../binding/one-time.js"; import { oneWay } from "../binding/one-way.js"; -import { DOM, type DOMPolicy } from "../dom.js"; +import { DOM } from "../dom.js"; +import type { DOMPolicy } from "../dom-policy.js"; import { isFunction, isString, Message } from "../interfaces.js"; import type { ExecutionContext } from "../observation/observable.js"; import { FAST } from "../platform.js"; diff --git a/packages/fast-element/src/templating/html-binding-directive.ts b/packages/fast-element/src/templating/html-binding-directive.ts index 5df23824c49..a315d11b184 100644 --- a/packages/fast-element/src/templating/html-binding-directive.ts +++ b/packages/fast-element/src/templating/html-binding-directive.ts @@ -1,6 +1,7 @@ import type { Binding, BindingDirective } from "../binding/binding.js"; import { isHydratable } from "../components/hydration.js"; -import { DOM, DOMAspect, type DOMPolicy } from "../dom.js"; +import { DOM, DOMAspect } from "../dom.js"; +import type { DOMPolicy } from "../dom-policy.js"; import { Message } from "../interfaces.js"; import { ExecutionContext, @@ -315,11 +316,18 @@ export class HTMLBindingDirective */ aspectType: DOMAspect = DOMAspect.content; + /** + * The binding configuration to apply. + */ + dataBinding: Binding; + /** * Creates an instance of HTMLBindingDirective. * @param dataBinding - The binding configuration to apply. */ - constructor(public dataBinding: Binding) {} + constructor(dataBinding: Binding) { + this.dataBinding = dataBinding; + } /** * Creates HTML to be used within a template. diff --git a/packages/fast-element/src/templating/html-directive.ts b/packages/fast-element/src/templating/html-directive.ts index 4f544a66406..82722a20842 100644 --- a/packages/fast-element/src/templating/html-directive.ts +++ b/packages/fast-element/src/templating/html-directive.ts @@ -1,5 +1,6 @@ import type { Binding } from "../binding/binding.js"; -import { DOMAspect, type DOMPolicy } from "../dom.js"; +import { DOMAspect } from "../dom.js"; +import type { DOMPolicy } from "../dom-policy.js"; import type { Constructable, Mutable } from "../interfaces.js"; import type { ExpressionController } from "../observation/observable.js"; import { createTypeRegistry, makeSerializationNoop } from "../platform.js"; diff --git a/packages/fast-element/src/templating/render.ts b/packages/fast-element/src/templating/render.ts index d8a52720086..7b783aba8cb 100644 --- a/packages/fast-element/src/templating/render.ts +++ b/packages/fast-element/src/templating/render.ts @@ -5,7 +5,7 @@ import { oneWay } from "../binding/one-way.js"; import { FASTElementDefinition } from "../components/fast-definitions.js"; import type { FASTElement } from "../components/fast-element.js"; import { isHydratable } from "../components/hydration.js"; -import type { DOMPolicy } from "../dom.js"; +import type { DOMPolicy } from "../dom-policy.js"; import { type Constructable, isFunction, isString } from "../interfaces.js"; import type { Subscriber } from "../observation/notifier.js"; import type { @@ -21,6 +21,7 @@ import { type ViewBehaviorFactory, type ViewController, } from "./html-directive.js"; +import { HydrationStage } from "./hydration-view.js"; import { Markup } from "./markup.js"; import { type CaptureType, @@ -29,7 +30,6 @@ import { type TemplateValue, ViewTemplate, } from "./template.js"; -import { HydrationStage } from "./hydration-view.js"; type ComposableView = ContentView & { isComposed?: boolean; diff --git a/packages/fast-element/src/templating/template.ts b/packages/fast-element/src/templating/template.ts index 0fff9d84cb5..67efa5d0de4 100644 --- a/packages/fast-element/src/templating/template.ts +++ b/packages/fast-element/src/templating/template.ts @@ -1,7 +1,7 @@ import { Binding } from "../binding/binding.js"; import { oneTime } from "../binding/one-time.js"; import { oneWay } from "../binding/one-way.js"; -import type { DOMPolicy } from "../dom.js"; +import type { DOMPolicy } from "../dom-policy.js"; import { isFunction, isString, Message } from "../interfaces.js"; import type { Expression } from "../observation/observable.js"; import { FAST, makeSerializationNoop } from "../platform.js";