@microsoft/fast-html 1.0.0-alpha.2 → 1.0.0-alpha.21

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.
Files changed (52) hide show
  1. package/README.md +111 -18
  2. package/dist/dts/components/element.d.ts +10 -0
  3. package/dist/dts/components/index.d.ts +2 -0
  4. package/dist/dts/components/observer-map.d.ts +26 -0
  5. package/dist/dts/components/schema.d.ts +134 -0
  6. package/dist/dts/components/template.d.ts +39 -5
  7. package/dist/dts/components/utilities.d.ts +92 -19
  8. package/dist/dts/fixtures/observer-map/main.d.ts +1 -0
  9. package/dist/dts/fixtures/observer-map/observer-map.spec.d.ts +1 -0
  10. package/dist/dts/index.d.ts +1 -1
  11. package/dist/esm/components/element.js +27 -0
  12. package/dist/esm/components/index.js +2 -0
  13. package/dist/esm/components/observer-map.js +49 -0
  14. package/dist/esm/components/observer-map.spec.js +19 -0
  15. package/dist/esm/components/schema.js +215 -0
  16. package/dist/esm/components/schema.spec.js +257 -0
  17. package/dist/esm/components/template.js +154 -99
  18. package/dist/esm/components/utilities.js +553 -43
  19. package/dist/esm/components/utilities.spec.js +246 -44
  20. package/dist/esm/fixtures/attribute/main.js +3 -2
  21. package/dist/esm/fixtures/binding/binding.spec.js +6 -0
  22. package/dist/esm/fixtures/binding/main.js +13 -2
  23. package/dist/esm/fixtures/children/children.spec.js +4 -0
  24. package/dist/esm/fixtures/children/main.js +3 -2
  25. package/dist/esm/fixtures/dot-syntax/dot-syntax.spec.js +109 -2
  26. package/dist/esm/fixtures/dot-syntax/main.js +30 -4
  27. package/dist/esm/fixtures/event/event.spec.js +28 -5
  28. package/dist/esm/fixtures/event/main.js +21 -5
  29. package/dist/esm/fixtures/observer-map/main.js +304 -0
  30. package/dist/esm/fixtures/observer-map/observer-map.spec.js +174 -0
  31. package/dist/esm/fixtures/ref/main.js +3 -2
  32. package/dist/esm/fixtures/ref/ref.spec.js +2 -6
  33. package/dist/esm/fixtures/repeat/main.js +27 -2
  34. package/dist/esm/fixtures/repeat/repeat.spec.js +16 -6
  35. package/dist/esm/fixtures/slotted/main.js +15 -4
  36. package/dist/esm/fixtures/slotted/slotted.spec.js +18 -19
  37. package/dist/esm/fixtures/when/main.js +139 -2
  38. package/dist/esm/fixtures/when/when.spec.js +64 -1
  39. package/dist/esm/index.js +1 -1
  40. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  41. package/dist/fast-html.api.json +279 -0
  42. package/dist/fast-html.d.ts +219 -5
  43. package/dist/fast-html.untrimmed.d.ts +219 -5
  44. package/package.json +12 -9
  45. package/rules/attribute-directives.yml +38 -0
  46. package/rules/call-expression-with-event-argument.yml +41 -0
  47. package/rules/member-expression.yml +33 -0
  48. package/rules/tag-function-to-template-literal.yml +16 -0
  49. package/dist/esm/fixtures/partial/main.js +0 -31
  50. package/dist/esm/fixtures/partial/partial.spec.js +0 -14
  51. /package/dist/dts/{fixtures/partial/main.d.ts → components/observer-map.spec.d.ts} +0 -0
  52. /package/dist/dts/{fixtures/partial/partial.spec.d.ts → components/schema.spec.d.ts} +0 -0
@@ -1,5 +1,196 @@
1
+ import { Constructable } from '@microsoft/fast-element';
1
2
  import { FASTElement } from '@microsoft/fast-element';
2
3
 
4
+ declare interface AccessCachedPath extends CachedPathCommon {
5
+ type: AccessCachedPathType;
6
+ }
7
+
8
+ declare type AccessCachedPathType = "access";
9
+
10
+ declare type CachedPath = DefaultCachedPath | RepeatCachedPath | AccessCachedPath | EventCachedPath;
11
+
12
+ declare interface CachedPathCommon {
13
+ parentContext: string | null;
14
+ currentContext: string | null;
15
+ path: string;
16
+ }
17
+
18
+ declare interface DefaultCachedPath extends CachedPathCommon {
19
+ type: DefaultCachedPathType;
20
+ }
21
+
22
+ declare type DefaultCachedPathType = "default";
23
+
24
+ declare interface ElementOptions {
25
+ observerMap?: ObserverMapOption | undefined;
26
+ }
27
+
28
+ /**
29
+ * A dictionary of element options the TemplateElement will use to update the registered element
30
+ */
31
+ declare interface ElementOptionsDictionary<ElementOptionsType = ElementOptions> {
32
+ [key: string]: ElementOptionsType;
33
+ }
34
+
35
+ declare interface EventCachedPath extends CachedPathCommon {
36
+ type: EventCachedPathType;
37
+ }
38
+
39
+ declare type EventCachedPathType = "event";
40
+
41
+ declare interface JSONSchema extends JSONSchemaCommon {
42
+ $schema: string;
43
+ $id: string;
44
+ $defs?: Record<string, JSONSchemaDefinition>;
45
+ $ref?: string;
46
+ }
47
+
48
+ declare interface JSONSchemaCommon {
49
+ type?: string;
50
+ properties?: any;
51
+ items?: any;
52
+ }
53
+
54
+ declare interface JSONSchemaDefinition extends JSONSchemaCommon {
55
+ $fast_context: string;
56
+ $fast_parent_contexts: Array<string>;
57
+ }
58
+
59
+ /**
60
+ * ObserverMap provides functionality for caching binding paths, extracting root properties,
61
+ * and defining observable properties on class prototypes
62
+ */
63
+ export declare class ObserverMap {
64
+ private schema;
65
+ private classPrototype;
66
+ constructor(classPrototype: any, schema: Schema);
67
+ defineProperties(): void;
68
+ /**
69
+ * Creates a proxy for an object that intercepts property mutations and triggers Observable notifications
70
+ * @param target - The target instance that owns the root property
71
+ * @param rootProperty - The name of the root property for notification purposes
72
+ * @param object - The object to wrap with a proxy
73
+ * @returns A proxy that triggers notifications on property mutations
74
+ */
75
+ private getAndAssignObservables;
76
+ /**
77
+ * Creates a property change handler function for observable properties
78
+ * This handler is called when an observable property transitions from undefined to a defined value
79
+ * @param propertyName - The name of the property for which to create the change handler
80
+ * @returns A function that handles property changes and sets up proxies for object values
81
+ */
82
+ private defineChanged;
83
+ }
84
+
85
+ declare type ObserverMapOption = "all";
86
+
87
+ declare interface RegisterPathConfig {
88
+ rootPropertyName: string;
89
+ pathConfig: CachedPath;
90
+ }
91
+
92
+ /**
93
+ * A mixin function that extends a base class with additional functionality for
94
+ * rendering and hydration.
95
+ *
96
+ * @param BaseCtor - The base class to extend.
97
+ * @returns A new class that extends the provided base class with additional functionality for rendering and hydration.
98
+ * @public
99
+ */
100
+ export declare function RenderableFASTElement<T extends Constructable<FASTElement>>(BaseCtor: T): T;
101
+
102
+ declare interface RepeatCachedPath extends CachedPathCommon {
103
+ type: RepeatCachedPathType;
104
+ }
105
+
106
+ declare type RepeatCachedPathType = "repeat";
107
+
108
+ /**
109
+ * A constructed JSON schema from a template
110
+ */
111
+ declare class Schema {
112
+ /**
113
+ * The name of the custom element
114
+ */
115
+ private customElementName;
116
+ /**
117
+ * A JSON schema describing each root schema
118
+ */
119
+ private jsonSchemaMap;
120
+ constructor(name: string);
121
+ /**
122
+ * Add a path to a schema
123
+ * @param config RegisterPathConfig
124
+ */
125
+ addPath(config: RegisterPathConfig): void;
126
+ /**
127
+ * Gets the JSON schema for a property name
128
+ * @param rootPropertyName - the root property the JSON schema is mapped to
129
+ * @returns The JSON schema for the root property
130
+ */
131
+ getSchema(rootPropertyName: string): JSONSchema | null;
132
+ /**
133
+ * Gets root properties
134
+ * @returns IterableIterator<string>
135
+ */
136
+ getRootProperties(): IterableIterator<string>;
137
+ /**
138
+ * Get a path split into property names
139
+ * @param path The dot syntax path e.g. a.b.c
140
+ * @returns An array of items in the path
141
+ */
142
+ private getSplitPath;
143
+ /**
144
+ * Gets the path to the $def
145
+ * @param context The context name e.g. {{item in items}} in a repeat creates the "item" context
146
+ * @returns A string to use as a $ref
147
+ */
148
+ private getDefsPath;
149
+ /**
150
+ * Add a new JSON schema to the JSON schema map
151
+ * @param propertyName The name of the property to assign this JSON schema to
152
+ */
153
+ private addNewSchema;
154
+ /**
155
+ * Add properties to a context
156
+ * @param schema The schema to add the properties to
157
+ * @param splitPath The path split into property/context names
158
+ * @param context The paths context
159
+ */
160
+ private addPropertiesToAContext;
161
+ /**
162
+ * Add properties to an object
163
+ * @param schema The schema to add the properties to
164
+ * @param splitPath The path split into property/context names
165
+ * @param context The paths context
166
+ * @param type The data type (see JSON schema for details)
167
+ */
168
+ private addPropertiesToAnObject;
169
+ /**
170
+ * Add an array to an object property
171
+ * @param schema The schema to add the properties to
172
+ * @param context The name of the context
173
+ */
174
+ private addArrayToAnObject;
175
+ /**
176
+ * Add a context to the $defs property
177
+ * @param schema The schema to use
178
+ * @param propertyName The name of the property the context belongs to
179
+ * @param currentContext The current context
180
+ * @param parentContext The parent context
181
+ * @returns
182
+ */
183
+ private addContext;
184
+ /**
185
+ * Get parent contexts
186
+ * @param schema The schema to use
187
+ * @param parentContext The parent context
188
+ * @param contexts A list of parent contexts
189
+ * @returns
190
+ */
191
+ private getParentContexts;
192
+ }
193
+
3
194
  /**
4
195
  * The <f-template> custom element that will provide view logic to the element
5
196
  */
@@ -8,12 +199,36 @@ export declare class TemplateElement extends FASTElement {
8
199
  * The name of the custom element this template will be applied to
9
200
  */
10
201
  name?: string;
202
+ /**
203
+ * A dictionary of custom element options
204
+ */
205
+ static elementOptions: ElementOptionsDictionary;
11
206
  private partials;
207
+ /**
208
+ * ObserverMap instance for caching binding paths
209
+ */
210
+ private observerMap?;
211
+ /**
212
+ * Default element options
213
+ */
214
+ private static defaultElementOptions;
215
+ /**
216
+ * Metadata containing JSON schema for properties on a custom eleemnt
217
+ */
218
+ private schema?;
219
+ static options(elementOptions?: ElementOptionsDictionary): typeof TemplateElement;
220
+ constructor();
221
+ /**
222
+ * Set options for a custom element
223
+ * @param name - The name of the custom element to set options for.
224
+ */
225
+ private static setOptions;
12
226
  connectedCallback(): void;
13
227
  /**
14
228
  * Resolve strings and values from an innerHTML string
15
229
  * @param innerHTML - The innerHTML.
16
230
  * @param self - Indicates that this should refer to itself instead of a property when creating bindings.
231
+ * @param observerMap - ObserverMap instance for caching binding paths (optional).
17
232
  */
18
233
  private resolveStringsAndValues;
19
234
  /**
@@ -27,6 +242,8 @@ export declare class TemplateElement extends FASTElement {
27
242
  * @param behaviorConfig - The directive behavior configuration object.
28
243
  * @param externalValues - The interpreted values from the parent.
29
244
  * @param innerHTML - The innerHTML.
245
+ * @param self - Indicates that this should refer to itself instead of a property when creating bindings.
246
+ * @param observerMap - ObserverMap instance for caching binding paths (optional).
30
247
  */
31
248
  private resolveTemplateDirective;
32
249
  /**
@@ -43,6 +260,7 @@ export declare class TemplateElement extends FASTElement {
43
260
  * @param values - The interpreted values.
44
261
  * @param self - Indicates that this should refer to itself instead of a property when creating bindings.
45
262
  * @param behaviorConfig - The binding behavior configuration object.
263
+ * @param observerMap - ObserverMap instance for caching binding paths (optional).
46
264
  */
47
265
  private resolveDataBinding;
48
266
  /**
@@ -51,13 +269,9 @@ export declare class TemplateElement extends FASTElement {
51
269
  * @param strings - The strings array.
52
270
  * @param values - The interpreted values.
53
271
  * @param self - Indicates that this should refer to itself instead of a property when creating bindings.
272
+ * @param observerMap - ObserverMap instance for caching binding paths (optional).
54
273
  */
55
274
  private resolveInnerHTML;
56
- /**
57
- * Resolve all partial templates
58
- * @param unresolvedInnerHTML - The innerHTML.
59
- */
60
- private resolveAllPartials;
61
275
  }
62
276
 
63
277
  export { }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/fast-html",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.21",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "Microsoft",
@@ -17,7 +17,8 @@
17
17
  "url": "https://github.com/Microsoft/fast/issues/new/choose"
18
18
  },
19
19
  "files": [
20
- "./dist"
20
+ "./dist",
21
+ "./rules/*.yml"
21
22
  ],
22
23
  "scripts": {
23
24
  "clean": "tsc -b --clean src",
@@ -28,12 +29,12 @@
28
29
  "build:binding": "webpack --config ./src/fixtures/binding/webpack.config.js",
29
30
  "build:children": "webpack --config ./src/fixtures/children/webpack.config.js",
30
31
  "build:dot-syntax": "webpack --config ./src/fixtures/dot-syntax/webpack.config.js",
31
- "build:partial": "webpack --config ./src/fixtures/partial/webpack.config.js",
32
32
  "build:when": "webpack --config ./src/fixtures/when/webpack.config.js",
33
33
  "build:ref": "webpack --config ./src/fixtures/ref/webpack.config.js",
34
34
  "build:repeat": "webpack --config ./src/fixtures/repeat/webpack.config.js",
35
+ "build:observer-map": "webpack --config ./src/fixtures/observer-map/webpack.config.js",
35
36
  "build:slotted": "webpack --config ./src/fixtures/slotted/webpack.config.js",
36
- "build-app": "npm run build:attribute && npm run build:dot-syntax && npm run build:partial && npm run build:event && npm run build:children && npm run build:binding && npm run build:when && npm run build:ref && npm run build:repeat && npm run build:slotted",
37
+ "build-app": "npm run build:attribute && npm run build:dot-syntax && npm run build:event && npm run build:children && npm run build:binding && npm run build:when && npm run build:ref && npm run build:repeat && npm run build:observer-map && npm run build:slotted",
37
38
  "build-server": "tsc -b server",
38
39
  "doc": "api-extractor run --local",
39
40
  "doc:ci": "api-extractor run",
@@ -43,8 +44,9 @@
43
44
  "pretest": "npm run build && npm run build-server",
44
45
  "prettier:diff": "prettier --config ../../../.prettierrc \"**/*.{ts,html}\" --list-different",
45
46
  "prettier": "prettier --config ../../../.prettierrc --write \"**/*.{ts,html}\"",
46
- "test": "npm run build-app && playwright test --config=playwright.config.cjs",
47
+ "test": "npm run build-app && playwright test --config=playwright.config.cjs && npm run test:rules",
47
48
  "test-server": "node server/dist/server.js",
49
+ "test:rules": "sg test --skip-snapshot-tests",
48
50
  "install-playwright-browsers": "npm run playwright install",
49
51
  "dev": "npm run build && npm run build-app && npm run build-server && npm run test-server"
50
52
  },
@@ -54,17 +56,19 @@
54
56
  "types": "./dist/dts/index.d.ts",
55
57
  "default": "./dist/esm/index.js"
56
58
  },
59
+ "./rules/*.yml": "./rules/*.yml",
57
60
  "./package.json": "./package.json"
58
61
  },
59
62
  "sideEffects": [
60
63
  "./dist/esm/index.js"
61
64
  ],
62
65
  "peerDependencies": {
63
- "@microsoft/fast-element": "^2.2.0"
66
+ "@microsoft/fast-element": "^2.7.0"
64
67
  },
65
68
  "devDependencies": {
69
+ "@ast-grep/cli": "^0.37.0",
66
70
  "@microsoft/api-extractor": "^7.47.0",
67
- "@microsoft/fast-element": "^2.2.0",
71
+ "@microsoft/fast-element": "^2.7.0",
68
72
  "@playwright/test": "^1.49.0",
69
73
  "@types/express": "^4.17.21",
70
74
  "@types/node": "^17.0.17",
@@ -79,7 +83,6 @@
79
83
  "major",
80
84
  "minor",
81
85
  "patch"
82
- ],
83
- "tag": "alpha"
86
+ ]
84
87
  }
85
88
  }
@@ -0,0 +1,38 @@
1
+ # https://ast-grep.github.io/guide/rule-config.html#rule
2
+ # from: ${ref("defaultSlot")}
3
+ # to: f-ref="{defaultSlot}"
4
+ id: binding - convert attribute directives
5
+ language: typescript
6
+ utils:
7
+ call-expression:
8
+ has:
9
+ nthChild: 1
10
+ kind: call_expression
11
+ all:
12
+ - matches: identifier
13
+ - matches: arguments
14
+ identifier:
15
+ has:
16
+ nthChild: 1
17
+ kind: identifier
18
+ pattern: $DIRECTIVE
19
+ arguments:
20
+ has:
21
+ kind: arguments
22
+ matches: string
23
+ string:
24
+ has:
25
+ kind: string
26
+ matches: string-fragment
27
+ string-fragment:
28
+ has:
29
+ kind: string_fragment
30
+ pattern: $STRING
31
+ constraints:
32
+ DIRECTIVE:
33
+ regex: ref|slotted|children
34
+ rule:
35
+ kind: template_substitution
36
+ matches: call-expression
37
+ fix:
38
+ 'f-$DIRECTIVE="{$STRING}"'
@@ -0,0 +1,41 @@
1
+ # https://ast-grep.github.io/guide/rule-config.html#rule
2
+ # from: ${(x, c) => x.foo(c.event)}
3
+ # to: {foo(event)}
4
+ id: binding - convert call expression with event argument
5
+ language: typescript
6
+ utils:
7
+ arrow-function:
8
+ has:
9
+ kind: arrow_function
10
+ matches: call-expression
11
+ call-expression:
12
+ has:
13
+ kind: call_expression
14
+ all:
15
+ - matches: handler-arguments
16
+ - matches: handler-expression
17
+ handler-expression:
18
+ has:
19
+ kind: member_expression
20
+ matches: handler-expression-property
21
+ handler-expression-property:
22
+ has:
23
+ kind: property_identifier
24
+ pattern: $A
25
+ handler-arguments:
26
+ has:
27
+ kind: arguments
28
+ matches: handler-arguments-member-expression
29
+ handler-arguments-member-expression:
30
+ has:
31
+ kind: member_expression
32
+ matches: handler-arguments-property-identifier
33
+ handler-arguments-property-identifier:
34
+ has:
35
+ kind: property_identifier
36
+ pattern: $B
37
+ rule:
38
+ kind: template_substitution
39
+ matches: arrow-function
40
+ fix:
41
+ '{$A($B)}'
@@ -0,0 +1,33 @@
1
+ # https://ast-grep.github.io/guide/rule-config.html#rule
2
+ # from: ${x => x.foo}
3
+ # to: {{foo}}
4
+ id: binding - convert member expression
5
+ language: typescript
6
+ utils:
7
+ arrow-function:
8
+ has:
9
+ kind: arrow_function
10
+ all:
11
+ - matches: identifier
12
+ - matches: member-expression
13
+ member-expression:
14
+ has:
15
+ kind: member_expression
16
+ nthChild: 2
17
+ all:
18
+ - matches: identifier
19
+ - matches: property-identifier
20
+ identifier:
21
+ has:
22
+ kind: identifier
23
+ nthChild: 1
24
+ property-identifier:
25
+ has:
26
+ kind: property_identifier
27
+ nthChild: 2
28
+ pattern: $A
29
+ rule:
30
+ kind: template_substitution
31
+ matches: arrow-function
32
+ fix:
33
+ '{{$A}}'
@@ -0,0 +1,16 @@
1
+ # https://ast-grep.github.io/guide/rule-config.html#rule
2
+ # from: export const template = html`<slot></slot>`
3
+ # to: `<slot></slot>`
4
+ id: convert tag function to template literal
5
+ language: typescript
6
+ utils:
7
+ is-tag-template:
8
+ has:
9
+ kind: template_string
10
+ pattern: $B
11
+ rule:
12
+ kind: call_expression
13
+ matches: is-tag-template
14
+ pattern: $A
15
+ fix:
16
+ '$B'
@@ -1,31 +0,0 @@
1
- import { TemplateElement } from "@microsoft/fast-html";
2
- import { FASTElement } from "@microsoft/fast-element";
3
- class TestElement extends FASTElement {
4
- constructor() {
5
- super(...arguments);
6
- this.items = [
7
- {
8
- text: "Hello",
9
- },
10
- {
11
- text: "Earth",
12
- items: [
13
- {
14
- text: "Pluto",
15
- items: [
16
- {
17
- text: "Mars",
18
- },
19
- ],
20
- },
21
- ],
22
- },
23
- ];
24
- }
25
- }
26
- TestElement.define({
27
- name: "test-element",
28
- });
29
- TemplateElement.define({
30
- name: "f-template",
31
- });
@@ -1,14 +0,0 @@
1
- import { __awaiter } from "tslib";
2
- import { expect, test } from "@playwright/test";
3
- test.describe("f-template", () => __awaiter(void 0, void 0, void 0, function* () {
4
- test("create a partial", ({ page }) => __awaiter(void 0, void 0, void 0, function* () {
5
- yield page.goto("/partial");
6
- const customElement = yield page.locator("#test");
7
- let customElementListItems = yield customElement.locator("li");
8
- expect(yield customElementListItems.count()).toEqual(4);
9
- expect(yield customElementListItems.nth(0).textContent()).toEqual("Hello");
10
- expect(yield customElementListItems.nth(1).textContent()).toContain("Earth");
11
- expect(yield customElementListItems.nth(2).textContent()).toContain("Pluto");
12
- expect(yield customElementListItems.nth(3).textContent()).toContain("Mars");
13
- }));
14
- }));