Skip to content

Commit 2369257

Browse files
janechuCopilot
andcommitted
Rename schema hooks to transforms
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent ab3f528 commit 2369257

7 files changed

Lines changed: 72 additions & 69 deletions

File tree

packages/fast-element/DECLARATIVE_DESIGN.md

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ When connected to the DOM it:
7777
2. Publishes a template when a matching FAST element definition requests one.
7878
3. Delegates parsing of the inner `<template>` tag to `TemplateParser`, which
7979
converts declarative bindings into FAST `ViewTemplate` strings and values.
80-
4. Runs definition-scoped schema hooks, such as `attributeMap()` and
80+
4. Runs definition-scoped schema transforms, such as `attributeMap()` and
8181
`observerMap()`, before returning the concrete `ViewTemplate`.
8282

8383
### `TemplateParser` — declarative HTML parser
@@ -196,7 +196,7 @@ packages/fast-element/
196196
│ ├── index.ts # Declarative barrel export
197197
│ ├── interfaces.ts # Message enum (error codes)
198198
│ ├── debug.ts # Human-readable declarative debug messages
199-
│ ├── definition-options.ts # Definition-scoped schema hook storage
199+
│ ├── definition-options.ts # Definition-scoped schema transform storage
200200
│ ├── template.ts # declarativeTemplate(), internal <f-template> publisher, lifecycle orchestration
201201
│ ├── template-bridge.ts # Registry/name bridge between definitions and publishers
202202
│ ├── template-parser.ts # TemplateParser — converts declarative HTML to ViewTemplate strings/values
@@ -214,22 +214,22 @@ packages/fast-element/
214214
### Module dependency direction
215215

216216
The default `declarativeTemplate()` path avoids importing optional map
217-
implementations. Map helpers attach schema hooks to the definition only when the
218-
consumer passes them as define extensions.
217+
implementations. Map helpers attach schema transforms to the definition only
218+
when the consumer passes them as define extensions.
219219

220220
```
221-
template.ts ──imports──▶ definition-options.ts (schema hook reads)
221+
template.ts ──imports──▶ definition-options.ts (schema transform reads)
222222
template.ts ──imports──▶ schema.ts (Schema)
223-
attribute-map.ts ──imports──▶ definition-options.ts (register attribute-map hook)
224-
observer-map.ts ──imports──▶ definition-options.ts (register observer-map hook)
223+
attribute-map.ts ──imports──▶ definition-options.ts (register attribute-map transform)
224+
observer-map.ts ──imports──▶ definition-options.ts (register observer-map transform)
225225
observer-map.ts ──imports──▶ schema.ts (Schema types)
226226
attribute-map.ts ──imports──▶ schema.ts (Schema types)
227227
utilities.ts ──imports──▶ schema.ts (schemaRegistry for cross-element $ref resolution)
228228
```
229229

230-
Schema hooks are sorted by priority and insertion order. `attributeMap()` uses a
231-
higher-priority slot than `observerMap()`, so generated attributes are available
232-
before observer mapping runs.
230+
Schema transforms are sorted by priority and insertion order. `attributeMap()`
231+
uses a higher-priority slot than `observerMap()`, so generated attributes are
232+
available before observer mapping runs.
233233

234234
---
235235

@@ -332,7 +332,7 @@ via registry + name bridge"]
332332
G --> H[transformInnerHTML normalises HTML entities]
333333
H --> I["TemplateParser parses bindings/directives
334334
builds Schema, strings, values"]
335-
I --> J["Run definition schema hooks
335+
I --> J["Run definition schema transforms
336336
attributeMap before observerMap"]
337337
J --> K["ViewTemplate.create(strings, values)
338338
returned to definition"]
@@ -358,17 +358,18 @@ to the parser, keeping method signatures lean.
358358

359359
### Architecture
360360

361-
The parsing pipeline is split across two classes plus definition-scoped hooks:
361+
The parsing pipeline is split across two classes plus definition-scoped
362+
transforms:
362363

363364
- **Internal `<f-template>` publisher** (`template.ts`) — Custom element
364365
lifecycle, registry/name bridge registration, lifecycle callback dispatch, and
365-
schema-hook execution. It is a native `HTMLElement`, not a `FASTElement`.
366+
schema-transform execution. It is a native `HTMLElement`, not a `FASTElement`.
366367
- **`TemplateParser`** (`template-parser.ts`) — Synchronous template parser:
367368
converts declarative HTML into `strings`/`values` arrays for
368369
`ViewTemplate.create()`. Uses a `StringsAccumulator` to track the running
369370
previous-string in O(1) per binding site instead of O(N) `join("")` calls.
370371
Independently testable without DOM.
371-
- **Schema hooks** (`definition-options.ts`) — Extension-provided callbacks run
372+
- **Schema transforms** (`definition-options.ts`) — Extension-provided callbacks run
372373
after parsing and before `ViewTemplate.create()`. `attributeMap()` runs before
373374
`observerMap()`.
374375

@@ -379,7 +380,7 @@ sequenceDiagram
379380
participant TP as TemplateParser
380381
participant U as utilities.ts
381382
participant S as Schema
382-
participant Hooks as schema hooks
383+
participant Transforms as schema transforms
383384
384385
DOM->>FTE: connectedCallback()
385386
FTE->>FTE: register publisher with bridge
@@ -413,7 +414,7 @@ sequenceDiagram
413414
end
414415
end
415416
TP-->>FTE: { strings, values }
416-
FTE->>Hooks: attributeMap(), then observerMap()
417+
FTE->>Transforms: attributeMap(), then observerMap()
417418
FTE->>TP: parser.createTemplate(strings, values)
418419
FTE-->>DOM: return ViewTemplate to definition resolver
419420
```
@@ -518,11 +519,11 @@ When an `ObserverMapConfig` with a `properties` key is provided, `ObserverMap.de
518519

519520
### AttributeMap and leaf bindings
520521

521-
When `attributeMap()` is enabled, it registers a definition schema hook. After
522-
parsing, the hook constructs an `AttributeMap` implementation and calls
523-
`defineProperties()`. It iterates `Schema.getRootProperties()` and skips any
524-
property whose schema entry contains `properties`, `type`, or `anyOf` keeping
525-
only plain leaf bindings. For each leaf:
522+
When `attributeMap()` is enabled, it registers a definition schema transform.
523+
After parsing, the transform constructs an `AttributeMap` implementation and
524+
calls `defineProperties()`. It iterates `Schema.getRootProperties()` and skips
525+
any property whose schema entry contains `properties`, `type`, or `anyOf`
526+
keeping only plain leaf bindings. For each leaf:
526527

527528
1. The schema key is used as the **JS property name**.
528529
2. The **HTML attribute name** depends on the `attribute-name-strategy`:
@@ -536,7 +537,7 @@ accessed via bracket notation (e.g. `element["foo-bar"]`). When using
536537
`"camelCase"`, property names are standard JS identifiers (e.g.
537538
`element.fooBar`).
538539

539-
Because schema hooks are priority sorted, attribute mapping runs before observer
540+
Because schema transforms are priority sorted, attribute mapping runs before observer
540541
mapping when both extensions are supplied.
541542

542543
---
@@ -560,7 +561,7 @@ sequenceDiagram
560561
FTE->>FTE: bridge matches registry + name
561562
FTE->>PerEl: elementDidRegister('my-el')
562563
FTE->>PerEl: templateWillUpdate('my-el')
563-
FTE->>FTE: parse template → schema → hooks → ViewTemplate
564+
FTE->>FTE: parse template → schema → transforms → ViewTemplate
564565
FTE->>FER: return viewTemplate to resolver
565566
FER->>PerEl: templateDidUpdate('my-el')
566567
FER->>FER: customElements.define('my-el', MyElement)
@@ -608,7 +609,7 @@ tagged templates produce.
608609
|---|---|
609610
| `FASTElement` | Base class for user components; the internal `<f-template>` publisher is a native `HTMLElement` |
610611
| `FASTElementDefinition.register()` / template resolvers | Deferred element registration — element waits for its template |
611-
| `FASTElementExtension` | Extension callback mechanism used by `attributeMap()` and `observerMap()` to attach schema hooks before template resolution |
612+
| `FASTElementExtension` | Extension callback mechanism used by `attributeMap()` and `observerMap()` to attach schema transforms before template resolution |
612613
| `ViewTemplate.create(strings, values)` | Compiles the resolved strings/values arrays into a `ViewTemplate` |
613614
| `ElementController` | Automatically detects prerendered content (`isPrerendered`) and hydrates server-rendered DOM using `fe-b` comment/dataset markers via `template.hydrate()` |
614615
| `Observable.defineProperty()` | Defines observable root properties on element prototypes (ObserverMap) |

packages/fast-element/DESIGN.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,8 @@ the imperative `html` API:
339339
- `TemplateParser` lowers declarative syntax to the same `strings` / `values`
340340
shape used by `ViewTemplate.create()`.
341341
- `attributeMap()` and `observerMap()` are `FASTElementExtension` factories.
342-
They register schema hooks on the element definition, and those hooks run
343-
after parsing in deterministic order (`attributeMap()` before
342+
They register schema transforms on the element definition, and those
343+
transforms run after parsing in deterministic order (`attributeMap()` before
344344
`observerMap()`).
345345

346346
The `src/declarative.ts` entrypoint is pure at module evaluation time. Running a
@@ -557,7 +557,7 @@ src/
557557
│ ├── template.ts # declarativeTemplate() and internal f-template publisher
558558
│ ├── template-parser.ts # Declarative HTML parser → ViewTemplate strings/values
559559
│ ├── schema.ts # Binding schema builder + schemaRegistry
560-
│ ├── definition-options.ts # Definition-scoped declarative schema hooks
560+
│ ├── definition-options.ts # Definition-scoped declarative schema transforms
561561
│ ├── observer-map.ts # observerMap() extension and proxy-backed observation helpers
562562
│ ├── attribute-map.ts # attributeMap() extension and automatic @attr helpers
563563
│ ├── utilities.ts # Declarative parsing and proxy utilities

packages/fast-element/SIZES.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ Bundle sizes for `@microsoft/fast-element` exports.
2020
| css | 2.43 KB | 1.00 KB | 911 B |
2121
| enableHydration | 43.23 KB | 13.21 KB | 11.88 KB |
2222
| ArrayObserver | 12.51 KB | 4.45 KB | 4.01 KB |
23-
| declarativeTemplate | 58.66 KB | 18.50 KB | 16.46 KB |
24-
| observerMap | 13.62 KB | 5.08 KB | 4.58 KB |
25-
| attributeMap | 15.52 KB | 5.48 KB | 4.94 KB |
23+
| declarativeTemplate | 58.67 KB | 18.50 KB | 16.46 KB |
24+
| observerMap | 13.63 KB | 5.08 KB | 4.59 KB |
25+
| attributeMap | 15.53 KB | 5.49 KB | 4.94 KB |

packages/fast-element/src/declarative/attribute-map.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
trackLateAttributeDefinition,
66
} from "../components/fast-definitions.js";
77
import { Observable } from "../observation/observable.js";
8-
import { setDefinitionSchemaHook } from "./definition-options.js";
8+
import { setDefinitionSchemaTransform } from "./definition-options.js";
99
import type { Schema } from "./schema.js";
1010

1111
/**
@@ -28,8 +28,8 @@ export interface AttributeMapConfig {
2828
"attribute-name-strategy"?: "none" | "camelCase";
2929
}
3030

31-
const attributeMapSchemaHookKey = "attribute-map";
32-
const attributeMapSchemaHookPriority = 0;
31+
const attributeMapSchemaTransformKey = "attribute-map";
32+
const attributeMapSchemaTransformPriority = 0;
3333

3434
/**
3535
* Creates a FAST element extension that enables declarative attribute mapping
@@ -39,9 +39,9 @@ const attributeMapSchemaHookPriority = 0;
3939
*/
4040
export function attributeMap(config: AttributeMapConfig = {}): FASTElementExtension {
4141
return definition => {
42-
setDefinitionSchemaHook(
42+
setDefinitionSchemaTransform(
4343
definition,
44-
attributeMapSchemaHookKey,
44+
attributeMapSchemaTransformKey,
4545
({ definition, schema }) => {
4646
new AttributeMap(
4747
definition.type.prototype,
@@ -50,7 +50,7 @@ export function attributeMap(config: AttributeMapConfig = {}): FASTElementExtens
5050
config,
5151
).defineProperties();
5252
},
53-
attributeMapSchemaHookPriority,
53+
attributeMapSchemaTransformPriority,
5454
);
5555
};
5656
}
Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,60 @@
11
import type { FASTElementDefinition } from "../components/fast-definitions.js";
22
import type { Schema } from "./schema.js";
33

4-
const definitionSchemaHooksKey = Symbol("definitionSchemaHooks");
4+
const definitionSchemaTransformsKey = Symbol("definitionSchemaTransforms");
55

6-
let schemaHookOrder = 0;
6+
let schemaTransformOrder = 0;
77

8-
type FASTElementDefinitionWithSchemaHooks = FASTElementDefinition & {
9-
[definitionSchemaHooksKey]?: DefinitionSchemaHookRecord[];
8+
type FASTElementDefinitionWithSchemaTransforms = FASTElementDefinition & {
9+
[definitionSchemaTransformsKey]?: DefinitionSchemaTransformRecord[];
1010
};
1111

12-
interface DefinitionSchemaHookRecord {
12+
interface DefinitionSchemaTransformRecord {
1313
key: string;
14-
hook: DeclarativeSchemaHook;
14+
transform: DeclarativeSchemaTransform;
1515
order: number;
1616
priority: number;
1717
}
1818

19-
export interface DeclarativeSchemaHookContext {
19+
export interface DeclarativeSchemaTransformContext {
2020
definition: FASTElementDefinition;
2121
schema: Schema;
2222
}
2323

24-
export type DeclarativeSchemaHook = (context: DeclarativeSchemaHookContext) => void;
24+
export type DeclarativeSchemaTransform = (
25+
context: DeclarativeSchemaTransformContext,
26+
) => void;
2527

26-
export function setDefinitionSchemaHook(
28+
export function setDefinitionSchemaTransform(
2729
definition: FASTElementDefinition,
2830
key: string,
29-
hook: DeclarativeSchemaHook,
31+
transform: DeclarativeSchemaTransform,
3032
priority: number,
3133
): void {
32-
const target = definition as FASTElementDefinitionWithSchemaHooks;
33-
const hooks = (target[definitionSchemaHooksKey] ??= []);
34-
const existingIndex = hooks.findIndex(record => record.key === key);
34+
const target = definition as FASTElementDefinitionWithSchemaTransforms;
35+
const transforms = (target[definitionSchemaTransformsKey] ??= []);
36+
const existingIndex = transforms.findIndex(record => record.key === key);
3537

3638
if (existingIndex !== -1) {
37-
hooks.splice(existingIndex, 1);
39+
transforms.splice(existingIndex, 1);
3840
}
3941

40-
hooks.push({
42+
transforms.push({
4143
key,
42-
hook,
43-
order: schemaHookOrder++,
44+
transform,
45+
order: schemaTransformOrder++,
4446
priority,
4547
});
4648

47-
hooks.sort((a, b) => a.priority - b.priority || a.order - b.order);
49+
transforms.sort((a, b) => a.priority - b.priority || a.order - b.order);
4850
}
4951

50-
export function getDefinitionSchemaHooks(
52+
export function getDefinitionSchemaTransforms(
5153
definition?: FASTElementDefinition,
52-
): readonly DeclarativeSchemaHook[] {
53-
const hooks = (definition as FASTElementDefinitionWithSchemaHooks | undefined)?.[
54-
definitionSchemaHooksKey
55-
];
54+
): readonly DeclarativeSchemaTransform[] {
55+
const transforms = (
56+
definition as FASTElementDefinitionWithSchemaTransforms | undefined
57+
)?.[definitionSchemaTransformsKey];
5658

57-
return hooks?.map(record => record.hook) ?? [];
59+
return transforms?.map(record => record.transform) ?? [];
5860
}

packages/fast-element/src/declarative/observer-map.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { FASTElementExtension } from "../components/fast-definitions.js";
22
import { Observable } from "../observation/observable.js";
3-
import { setDefinitionSchemaHook } from "./definition-options.js";
3+
import { setDefinitionSchemaTransform } from "./definition-options.js";
44
import type { JSONSchema, Schema } from "./schema.js";
55
import { assignObservables, deepMerge } from "./utilities.js";
66

@@ -46,8 +46,8 @@ export interface ObserverMapConfig {
4646
};
4747
}
4848

49-
const observerMapSchemaHookKey = "observer-map";
50-
const observerMapSchemaHookPriority = 1;
49+
const observerMapSchemaTransformKey = "observer-map";
50+
const observerMapSchemaTransformPriority = 1;
5151

5252
/**
5353
* Creates a FAST element extension that enables declarative observer mapping
@@ -57,17 +57,17 @@ const observerMapSchemaHookPriority = 1;
5757
*/
5858
export function observerMap(config: ObserverMapConfig = {}): FASTElementExtension {
5959
return definition => {
60-
setDefinitionSchemaHook(
60+
setDefinitionSchemaTransform(
6161
definition,
62-
observerMapSchemaHookKey,
62+
observerMapSchemaTransformKey,
6363
({ definition, schema }) => {
6464
new ObserverMap(
6565
definition.type.prototype,
6666
schema,
6767
config,
6868
).defineProperties();
6969
},
70-
observerMapSchemaHookPriority,
70+
observerMapSchemaTransformPriority,
7171
);
7272
};
7373
}

packages/fast-element/src/declarative/template.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type {
55
} from "../components/fast-definitions.js";
66
import { FAST } from "../platform.js";
77
import type { ElementViewTemplate } from "../templating/template.js";
8-
import { getDefinitionSchemaHooks } from "./definition-options.js";
8+
import { getDefinitionSchemaTransforms } from "./definition-options.js";
99
import { Message } from "./interfaces.js";
1010
import { ensureDeclarativeRuntime } from "./runtime.js";
1111
import { Schema } from "./schema.js";
@@ -203,8 +203,8 @@ class FTemplateElement extends HTMLElement implements TemplatePublisher {
203203
const parser = new TemplateParser();
204204
const { strings, values } = parser.parse(innerHTML, schema);
205205

206-
for (const hook of getDefinitionSchemaHooks(definition)) {
207-
hook({ definition, schema });
206+
for (const transform of getDefinitionSchemaTransforms(definition)) {
207+
transform({ definition, schema });
208208
}
209209

210210
return parser.createTemplate(strings, values);

0 commit comments

Comments
 (0)