@lushly-dev/fast-element 0.0.0-bootstrap.0 → 3.0.1-preview.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/CHANGELOG.md +1053 -0
- package/LICENSE +23 -0
- package/README.md +280 -2
- package/migration/fast-html/rules/README.md +15 -0
- package/migration/fast-html/rules/attribute-directives.yml +38 -0
- package/migration/fast-html/rules/call-expression-with-event-argument.yml +41 -0
- package/migration/fast-html/rules/member-expression.yml +33 -0
- package/migration/fast-html/rules/tag-function-to-template-literal.yml +16 -0
- package/package.json +233 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
FAST - https://www.fast.design/
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE
|
package/README.md
CHANGED
|
@@ -1,3 +1,281 @@
|
|
|
1
|
-
#
|
|
1
|
+
# FAST Element
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://badge.fury.io/js/%40microsoft%2Ffast-element)
|
|
5
|
+
|
|
6
|
+
The `fast-element` library is a lightweight means to easily build performant, memory-efficient, standards-compliant Web Components. FAST Elements work in every major browser and can be used in combination with any front-end framework or even without a framework.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
### From NPM
|
|
11
|
+
|
|
12
|
+
To install the latest `fast-element` library using `npm`:
|
|
13
|
+
|
|
14
|
+
```shell
|
|
15
|
+
npm install --save @lushly-dev/fast-element
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Within your JavaScript or TypeScript code, you can then import library APIs like this:
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { FASTElement } from '@lushly-dev/fast-element';
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### From CDN
|
|
25
|
+
|
|
26
|
+
A pre-bundled script that contains all APIs needed to build web components with FAST Element is available on CDN. You can use this script by adding [`type="module"`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) to the script element and then importing from the CDN.
|
|
27
|
+
|
|
28
|
+
```html
|
|
29
|
+
<!DOCTYPE html>
|
|
30
|
+
<html lang="en">
|
|
31
|
+
<head>
|
|
32
|
+
<script type="module">
|
|
33
|
+
import { FASTElement } from "https://cdn.jsdelivr.net/npm/@lushly-dev/fast-element/dist/fast-element.min.js";
|
|
34
|
+
|
|
35
|
+
// your code here
|
|
36
|
+
</script>
|
|
37
|
+
</head>
|
|
38
|
+
<!-- ... -->
|
|
39
|
+
</html>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The markup above always references the latest release. When deploying to production, you will want to ship with a specific version. Here's an example of the markup for that:
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@lushly-dev/fast-element@1.6.2/dist/fast-element.min.js"></script>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
:::note
|
|
49
|
+
For simplicity, examples throughout the documentation will assume the library has been installed from NPM, but you can always replace the import location with the CDN URL.
|
|
50
|
+
:::
|
|
51
|
+
|
|
52
|
+
:::tip
|
|
53
|
+
Looking for a quick guide on building components? Check out [our Cheat Sheet](../resources/cheat-sheet.md#building-components).
|
|
54
|
+
:::
|
|
55
|
+
|
|
56
|
+
## Browser Requirements
|
|
57
|
+
|
|
58
|
+
FAST Element v3 assumes a client-side browser `Window` runtime with native
|
|
59
|
+
`globalThis`, Custom Elements, DOM, Shadow DOM, and `requestAnimationFrame`.
|
|
60
|
+
The `FAST` object is now a module-scoped export (not on `globalThis`). If you
|
|
61
|
+
need to support an older browser without `globalThis`, load that polyfill before
|
|
62
|
+
importing `@lushly-dev/fast-element`.
|
|
63
|
+
|
|
64
|
+
The FAST Element client runtime is not intended to execute in workers,
|
|
65
|
+
server-side JavaScript runtimes, or other non-window hosts. Use server-side
|
|
66
|
+
rendering tools to produce HTML for the browser, and run FAST Element in the
|
|
67
|
+
client window where custom elements connect, render, update, and hydrate.
|
|
68
|
+
|
|
69
|
+
## Debug entrypoint
|
|
70
|
+
|
|
71
|
+
`@lushly-dev/fast-element/debug.js` exports `enableDebug()` instead of configuring
|
|
72
|
+
FAST at import time. The development root export and debug rollup bundle still
|
|
73
|
+
enable debug behavior automatically.
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { enableDebug } from "@lushly-dev/fast-element/debug.js";
|
|
77
|
+
|
|
78
|
+
enableDebug();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Export Sizes
|
|
82
|
+
|
|
83
|
+
Bundle sizes for each tree-shakeable export are tracked in [`SIZES.md`](./SIZES.md) and regenerated on every build. See the [Export Sizes](https://www.fast.design/docs/3.x/resources/export-sizes/) documentation page for the latest numbers.
|
|
84
|
+
|
|
85
|
+
## Root Imports and Path Exports
|
|
86
|
+
|
|
87
|
+
The root `@lushly-dev/fast-element` entrypoint exports the FAST Element
|
|
88
|
+
implementation APIs, including the element base class, kernel, controller,
|
|
89
|
+
definition APIs, template APIs, binding helpers, directives, styles, and schema
|
|
90
|
+
helpers. The FAST element registry is also available from
|
|
91
|
+
`@lushly-dev/fast-element/registry.js` for focused definition lookups and
|
|
92
|
+
`fastElementRegistry.whenRegistered(tagName)` registration promises.
|
|
93
|
+
Declarative, hydration, context, and dependency injection APIs are available
|
|
94
|
+
from their focused path exports.
|
|
95
|
+
|
|
96
|
+
Focused package path exports remain available for consumers that want to import
|
|
97
|
+
a narrower entrypoint directly. The website's
|
|
98
|
+
[Path Exports](https://www.fast.design/docs/3.x/advanced/path-exports/) page is
|
|
99
|
+
generated from `package.json` and lists each supported path.
|
|
100
|
+
|
|
101
|
+
## Dynamic Style Application
|
|
102
|
+
|
|
103
|
+
Import `css`, `CSSTemplateTag`, `CSSValue`, and style APIs such as
|
|
104
|
+
`ElementStyles`, `CSSDirective`, `cssDirective`, `ComposableStyles`,
|
|
105
|
+
`HostBehavior`, `HostController`, `StyleStrategy`, and `StyleTarget` from
|
|
106
|
+
`@lushly-dev/fast-element`:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { ElementStyles, css } from "@lushly-dev/fast-element";
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
When runtime state or external signals need to add or remove styles, create the
|
|
113
|
+
`ElementStyles` with `css` and toggle it through
|
|
114
|
+
`this.$fastController.addStyles()` / `this.$fastController.removeStyles()` from
|
|
115
|
+
the element lifecycle or change handlers.
|
|
116
|
+
|
|
117
|
+
`css` templates remain static style definitions. Runtime CSS bindings and
|
|
118
|
+
behavior-producing CSS directives are no longer supported; keep the condition on
|
|
119
|
+
the element and toggle a separate `ElementStyles` instance through the
|
|
120
|
+
controller when styles need to change.
|
|
121
|
+
|
|
122
|
+
## Declarative HTML
|
|
123
|
+
|
|
124
|
+
FAST Element publishes its declarative HTML runtime from
|
|
125
|
+
`@lushly-dev/fast-element/declarative.js`. This entrypoint exports the
|
|
126
|
+
functional APIs for declarative templates: `declarativeTemplate()`,
|
|
127
|
+
`TemplateParser`, and related configuration types. `attributeMap()` and
|
|
128
|
+
`observerMap()` are available from their own focused path exports. The
|
|
129
|
+
declarative runtime is pure at import time; declarative APIs lazily install only
|
|
130
|
+
declarative debug messages. Hydration is separate and remains opt-in through
|
|
131
|
+
`enableHydration()` from `@lushly-dev/fast-element/hydration.js`.
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
import { FASTElement } from "@lushly-dev/fast-element";
|
|
135
|
+
import { declarativeTemplate } from "@lushly-dev/fast-element/declarative.js";
|
|
136
|
+
|
|
137
|
+
class MyElement extends FASTElement {}
|
|
138
|
+
|
|
139
|
+
MyElement.define({
|
|
140
|
+
name: "my-element",
|
|
141
|
+
template: declarativeTemplate(),
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`declarativeTemplate()` automatically defines FAST's internal native
|
|
146
|
+
`<f-template>` publisher in the relevant registry, resolves the matching
|
|
147
|
+
`<f-template name="my-element">`, and keeps the definition template concrete
|
|
148
|
+
before `define()` resolves. If multiple matching `<f-template>` elements are
|
|
149
|
+
connected, the first connected element supplies the template and later duplicates
|
|
150
|
+
do not reassign it. Consumers should not import or define the `<f-template>`
|
|
151
|
+
implementation directly.
|
|
152
|
+
|
|
153
|
+
Declarative schema behavior is enabled with define extensions:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
import { attributeMap } from "@lushly-dev/fast-element/attribute-map.js";
|
|
157
|
+
import { declarativeTemplate } from "@lushly-dev/fast-element/declarative.js";
|
|
158
|
+
import { observerMap } from "@lushly-dev/fast-element/observer-map.js";
|
|
159
|
+
|
|
160
|
+
MyElement.define(
|
|
161
|
+
{
|
|
162
|
+
name: "my-element",
|
|
163
|
+
template: declarativeTemplate(),
|
|
164
|
+
},
|
|
165
|
+
[attributeMap(), observerMap()],
|
|
166
|
+
);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`attributeMap()` creates `@attr`-style accessors for leaf bindings, and
|
|
170
|
+
`observerMap()` creates deep observable accessors for discovered root
|
|
171
|
+
properties. Declarative templates assign `definition.schema` during template
|
|
172
|
+
resolution so these extensions always have schema data when used with
|
|
173
|
+
`declarativeTemplate()`. For non-declarative/manual schema use, import `Schema`
|
|
174
|
+
from `@lushly-dev/fast-element` and pass it on the element definition;
|
|
175
|
+
`observerMap()` can also receive
|
|
176
|
+
`observerMap({ schema })` directly. When both extensions are present, attribute
|
|
177
|
+
mapping runs before observer mapping.
|
|
178
|
+
|
|
179
|
+
Declarative utilities such as `deepMerge` are available from
|
|
180
|
+
`@lushly-dev/fast-element/declarative-utilities.js`. See
|
|
181
|
+
[`docs/declarative/syntax.md`](./docs/declarative/syntax.md) for declarative implementation
|
|
182
|
+
details and the
|
|
183
|
+
[Declarative HTML docs](https://fast.design/docs/3.x/declarative-templates/overview/)
|
|
184
|
+
for guides on writing f-templates, defining declarative elements, and
|
|
185
|
+
server-side rendering. Declarative event bindings use `$e` for the DOM event
|
|
186
|
+
object and `$c` for the execution context.
|
|
187
|
+
|
|
188
|
+
## Prerendered Content Optimization
|
|
189
|
+
|
|
190
|
+
Hydration of prerendered content is **opt-in**. Call `enableHydration()` from `@lushly-dev/fast-element/hydration.js` before any FAST elements connect to activate the hydration path:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
import { enableHydration } from "@lushly-dev/fast-element/hydration.js";
|
|
194
|
+
|
|
195
|
+
const hydration = enableHydration();
|
|
196
|
+
|
|
197
|
+
await hydration.whenHydrated();
|
|
198
|
+
console.log("hydration complete");
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
By default, hydration handles the initial prerendered batch and then no-ops
|
|
202
|
+
after the active hydration batch completes. If your app streams Declarative
|
|
203
|
+
Shadow DOM after the initial batch, keep the hydration hook active. In this
|
|
204
|
+
mode, `enableHydration().whenHydrated()` intentionally remains pending because
|
|
205
|
+
hydration never reaches a global completion point.
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import { enableHydration, StopHydration } from "@lushly-dev/fast-element/hydration.js";
|
|
209
|
+
|
|
210
|
+
enableHydration({
|
|
211
|
+
stopHydration: StopHydration.never,
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
When hydration is enabled and a FAST element connects with an existing shadow root (from server-side rendering or declarative shadow DOM), `ElementController` detects this and hydrates instead of re-rendering. Two properties on the controller let you inspect the result:
|
|
216
|
+
|
|
217
|
+
- **`isPrerendered: Promise<boolean>`** — resolves `true` when the element had a declarative shadow root (DSD) at connect time, regardless of whether hydration ran.
|
|
218
|
+
- **`isHydrated: Promise<boolean>`** — resolves `true` only when hydration actually ran successfully.
|
|
219
|
+
|
|
220
|
+
This enables several optimizations:
|
|
221
|
+
|
|
222
|
+
- **Hydration instead of re-render**: The template uses `hydrate()` to map existing DOM nodes to binding targets rather than cloning new DOM.
|
|
223
|
+
- **Declarative template resolution**: `declarativeTemplate()` waits for the
|
|
224
|
+
matching `<f-template>` before `define()` completes, so connected elements
|
|
225
|
+
hydrate with a concrete template.
|
|
226
|
+
- **Attribute skip**: `onAttributeChangedCallback()` skips processing during initial upgrade when the element is prerendered, since server-rendered attribute values are already correct.
|
|
227
|
+
- **Binding skip**: `HTMLBindingDirective.bind()` skips `updateTarget` for `attribute` and `booleanAttribute` aspect types when the view is prerendered.
|
|
228
|
+
|
|
229
|
+
### Hydration Mismatch Diagnostics
|
|
230
|
+
|
|
231
|
+
If a prerendered DOM diverges from the client template in a way FAST cannot
|
|
232
|
+
reconcile (the `render()` empty-boundary and `repeat()` count-mismatch cases
|
|
233
|
+
recover silently), `HydrationBindingError` or `HydrationTargetElementError` is
|
|
234
|
+
thrown. By default the message is a single line pointing at the opt-in
|
|
235
|
+
`hydrationDebugger()`. Install the debugger to get a rich
|
|
236
|
+
"Expected … / Received …" report with the SSR HTML snippet and structured
|
|
237
|
+
`expected` / `received` fields on the thrown error:
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
import { enableHydration, hydrationDebugger } from "@lushly-dev/fast-element/hydration.js";
|
|
241
|
+
|
|
242
|
+
enableHydration({ debugger: hydrationDebugger() });
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
The debugger module is tree-shaken out of production hydration bundles when
|
|
246
|
+
not imported, so the rich diagnostic helpers only land in builds that opt in.
|
|
247
|
+
|
|
248
|
+
Component authors can await both promises to distinguish prerendered content from successful hydration:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
const controller = this.$fastController;
|
|
252
|
+
const prerendered = await controller.isPrerendered;
|
|
253
|
+
const hydrated = await controller.isHydrated;
|
|
254
|
+
|
|
255
|
+
if (prerendered && !hydrated) {
|
|
256
|
+
// Had DSD but hydration wasn't enabled — client-side rendered
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Custom directives can also await `controller.isPrerendered` and `controller.isHydrated` (both `Promise<boolean>` on the `ViewController` interface) to determine how the view's content was rendered.
|
|
261
|
+
|
|
262
|
+
## Define Extensions
|
|
263
|
+
|
|
264
|
+
The static `define()` method on a `FASTElement` subclass accepts an optional second argument — an array of extension callbacks that are invoked with the resolved element definition before the element is registered with the platform. This enables a plugin pattern where reusable behaviors can hook into element registration.
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
import { FASTElement, type FASTElementExtension } from "@lushly-dev/fast-element";
|
|
268
|
+
|
|
269
|
+
function logger(): FASTElementExtension {
|
|
270
|
+
return definition => {
|
|
271
|
+
console.log(`Defining element: ${definition.name}`);
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
class MyComponent extends FASTElement {
|
|
276
|
+
// component code
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
MyComponent.define({ name: "my-component", template, styles }, [logger()]);
|
|
280
|
+
```
|
|
281
|
+
Each extension receives the full `FASTElementDefinition`, which includes the resolved element name, type, template, styles, and attribute metadata. Extensions run before `customElements.define()`, so any setup they perform is available when existing DOM elements are upgraded.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# FAST HTML to declarative HTML migration rules
|
|
2
|
+
|
|
3
|
+
This folder contains `.yml` rules for converting common FAST tagged-template
|
|
4
|
+
patterns to FAST Element v3 declarative HTML using
|
|
5
|
+
[ast-grep](https://ast-grep.github.io/).
|
|
6
|
+
|
|
7
|
+
Run the rules from the FAST Element package root with:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm exec sg scan --config migration/fast-html/sgconfig.yml path/to/source
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The generated markup is a migration aid, not a semantic guarantee. Move the
|
|
14
|
+
resulting template into an `.html` file, use `$e` and `$c` for event/context
|
|
15
|
+
arguments, and verify it with the declarative Playwright suite.
|
|
@@ -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($e)}
|
|
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($e)}'
|
|
@@ -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'
|