zmod-ember 0.1.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/README.md +139 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/package.json +63 -0
- package/src/index.ts +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# zmod-ember
|
|
2
|
+
|
|
3
|
+
This repo provides an adapter for [zmod](https://github.com/NaamuKim/zmod) for ember's gjs and gts files via [ember-estree](https://github.com/NullVoxPopuli/ember-estree) as zmod's default parser is [oxc](https://github.com/oxc-project/oxc)-parser, which is ESTree-compatible.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add zmod-ember zmod
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### With `z.withParser()`
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { z } from "zmod";
|
|
17
|
+
import { emberParser } from "zmod-ember";
|
|
18
|
+
|
|
19
|
+
const j = z.withParser(emberParser);
|
|
20
|
+
|
|
21
|
+
const source = `import Component from '@glimmer/component';
|
|
22
|
+
|
|
23
|
+
export default class OldComponent extends Component {
|
|
24
|
+
<template>
|
|
25
|
+
<h1>Hello {{@name}}</h1>
|
|
26
|
+
</template>
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
const root = j(source, { filePath: "my-component.gjs" });
|
|
31
|
+
|
|
32
|
+
root.find(j.Identifier, { name: "OldComponent" }).replaceWith("NewComponent");
|
|
33
|
+
|
|
34
|
+
console.log(root.toSource());
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### As a transform module
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import type { Transform } from "zmod";
|
|
41
|
+
import { emberParser } from "zmod-ember";
|
|
42
|
+
|
|
43
|
+
// Export the parser so zmod's `run()` uses it for all files
|
|
44
|
+
export const parser = emberParser;
|
|
45
|
+
|
|
46
|
+
const transform: Transform = ({ source, path }, { z }) => {
|
|
47
|
+
const root = z(source, { filePath: path });
|
|
48
|
+
|
|
49
|
+
root.find(z.Identifier, { name: "OldName" }).replaceWith("NewName");
|
|
50
|
+
|
|
51
|
+
return root.toSource();
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export default transform;
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Operating on Glimmer nodes
|
|
58
|
+
|
|
59
|
+
Glimmer template nodes are exposed as `Glimmer*`-prefixed types and can be found using string-based type queries:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { z } from "zmod";
|
|
63
|
+
import { emberParser } from "zmod-ember";
|
|
64
|
+
|
|
65
|
+
const j = z.withParser(emberParser);
|
|
66
|
+
|
|
67
|
+
const source = `<template>
|
|
68
|
+
<OldComponent @oldArg={{this.value}}>
|
|
69
|
+
<:header>Header</:header>
|
|
70
|
+
</OldComponent>
|
|
71
|
+
</template>
|
|
72
|
+
`;
|
|
73
|
+
|
|
74
|
+
const root = j(source, { filePath: "component.gjs" });
|
|
75
|
+
|
|
76
|
+
// Rename a component
|
|
77
|
+
root.find("GlimmerElementNode", { tag: "OldComponent" }).forEach((path) => {
|
|
78
|
+
path.node.tag = "NewComponent";
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Rename an argument
|
|
82
|
+
root.find("GlimmerAttrNode", { name: "@oldArg" }).replaceWith("@newArg={{this.value}}");
|
|
83
|
+
|
|
84
|
+
// Rename a named block
|
|
85
|
+
root.find("GlimmerElementNode", { tag: ":header" }).replaceWith("<:title>Header</:title>");
|
|
86
|
+
|
|
87
|
+
console.log(root.toSource());
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Other Glimmer node types you can query include `GlimmerMustacheStatement`, `GlimmerBlockStatement`, `GlimmerPathExpression`, `GlimmerTextNode`, `GlimmerElementModifierStatement`, `GlimmerSubExpression`, `GlimmerHashPair`, `GlimmerStringLiteral`, `GlimmerNumberLiteral`, and `GlimmerBlockParam`.
|
|
91
|
+
|
|
92
|
+
### Running transforms
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { run } from "zmod";
|
|
96
|
+
import transform from "./my-transform.js";
|
|
97
|
+
|
|
98
|
+
const result = await run(transform, {
|
|
99
|
+
include: ["src/**/*.gjs", "src/**/*.gts"],
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
console.log(result.files);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## How it works
|
|
106
|
+
|
|
107
|
+
The adapter wraps [ember-estree](https://github.com/NullVoxPopuli/ember-estree)'s `toTree()` to implement zmod's [`Parser` interface](https://github.com/NaamuKim/zmod/blob/main/packages/zmod/src/parser.ts):
|
|
108
|
+
|
|
109
|
+
- **`parse(source, options)`** — Calls `toTree` and returns an ESTree-compatible AST with embedded Glimmer template nodes. All nodes are guaranteed to have `start`/`end` byte-offset properties required by zmod's span-based patching. Handles both top-level and class body `<template>` tags.
|
|
110
|
+
- **`print(node)`** — Serializes AST nodes back to source code. Handles standard ESTree nodes and Glimmer template nodes (e.g., `GlimmerElementNode`, `GlimmerMustacheStatement`).
|
|
111
|
+
|
|
112
|
+
Pass `{ filePath: 'name.gjs' }` or `{ filePath: 'name.gts' }` in the parse options to control the file type.
|
|
113
|
+
|
|
114
|
+
> **Note:** Use zmod's default parser for plain `.js` and `.ts` files — `zmod-ember` is only needed for `.gjs` and `.gts` files that contain `<template>` tags. For codemods that target both standard JS/TS and Ember template files, use `zmod-ember` only for the `.gjs`/`.gts` files:
|
|
115
|
+
>
|
|
116
|
+
> ```ts
|
|
117
|
+
> import { z, run } from "zmod";
|
|
118
|
+
> import { emberParser } from "zmod-ember";
|
|
119
|
+
>
|
|
120
|
+
> // For .gjs/.gts files, use the ember parser
|
|
121
|
+
> const gjsTransform = ({ source, path }, { z }) => {
|
|
122
|
+
> return z(source, { filePath: path })
|
|
123
|
+
> .find(z.Identifier, { name: "OldName" })
|
|
124
|
+
> .replaceWith("NewName")
|
|
125
|
+
> .toSource();
|
|
126
|
+
> };
|
|
127
|
+
> gjsTransform.parser = emberParser;
|
|
128
|
+
>
|
|
129
|
+
> // For .js/.ts files, use zmod's default parser (no parser export needed)
|
|
130
|
+
> const jsTransform = ({ source }, { z }) => {
|
|
131
|
+
> return z(source).find(z.Identifier, { name: "OldName" }).replaceWith("NewName").toSource();
|
|
132
|
+
> };
|
|
133
|
+
> ```
|
|
134
|
+
|
|
135
|
+
## Peer dependencies
|
|
136
|
+
|
|
137
|
+
| Package | Required | Notes |
|
|
138
|
+
| ------- | -------- | -------------------- |
|
|
139
|
+
| `zmod` | Yes | Core codemod toolkit |
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Parser } from "zmod";
|
|
2
|
+
/**
|
|
3
|
+
* A zmod `Parser` adapter for Ember's `.gjs` and `.gts` files.
|
|
4
|
+
*
|
|
5
|
+
* Uses `ember-estree` to parse files containing `<template>` tags
|
|
6
|
+
* into an ESTree-compatible AST with embedded Glimmer template nodes.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { z } from 'zmod';
|
|
11
|
+
* import { emberParser } from 'zmod-ember';
|
|
12
|
+
*
|
|
13
|
+
* const j = z.withParser(emberParser);
|
|
14
|
+
* const root = j(gjsSource, { filePath: 'my-component.gjs' });
|
|
15
|
+
*
|
|
16
|
+
* root.find(j.Identifier, { name: 'OldName' })
|
|
17
|
+
* .replaceWith('NewName');
|
|
18
|
+
*
|
|
19
|
+
* console.log(root.toSource());
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* // As a transform module export
|
|
25
|
+
* import type { Transform } from 'zmod';
|
|
26
|
+
* import { emberParser } from 'zmod-ember';
|
|
27
|
+
*
|
|
28
|
+
* export const parser = emberParser;
|
|
29
|
+
*
|
|
30
|
+
* const transform: Transform = ({ source }, { z }) => {
|
|
31
|
+
* const root = z(source);
|
|
32
|
+
* // ... transform logic
|
|
33
|
+
* return root.toSource();
|
|
34
|
+
* };
|
|
35
|
+
*
|
|
36
|
+
* export default transform;
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare const emberParser: Parser;
|
|
40
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAgB,MAAM,MAAM,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,WAAW,EAAE,MAOzB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { toTree, print as emberPrint } from "ember-estree";
|
|
2
|
+
/**
|
|
3
|
+
* A zmod `Parser` adapter for Ember's `.gjs` and `.gts` files.
|
|
4
|
+
*
|
|
5
|
+
* Uses `ember-estree` to parse files containing `<template>` tags
|
|
6
|
+
* into an ESTree-compatible AST with embedded Glimmer template nodes.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { z } from 'zmod';
|
|
11
|
+
* import { emberParser } from 'zmod-ember';
|
|
12
|
+
*
|
|
13
|
+
* const j = z.withParser(emberParser);
|
|
14
|
+
* const root = j(gjsSource, { filePath: 'my-component.gjs' });
|
|
15
|
+
*
|
|
16
|
+
* root.find(j.Identifier, { name: 'OldName' })
|
|
17
|
+
* .replaceWith('NewName');
|
|
18
|
+
*
|
|
19
|
+
* console.log(root.toSource());
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* // As a transform module export
|
|
25
|
+
* import type { Transform } from 'zmod';
|
|
26
|
+
* import { emberParser } from 'zmod-ember';
|
|
27
|
+
*
|
|
28
|
+
* export const parser = emberParser;
|
|
29
|
+
*
|
|
30
|
+
* const transform: Transform = ({ source }, { z }) => {
|
|
31
|
+
* const root = z(source);
|
|
32
|
+
* // ... transform logic
|
|
33
|
+
* return root.toSource();
|
|
34
|
+
* };
|
|
35
|
+
*
|
|
36
|
+
* export default transform;
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export const emberParser = {
|
|
40
|
+
parse(source, options) {
|
|
41
|
+
return toTree(source, options);
|
|
42
|
+
},
|
|
43
|
+
print(node) {
|
|
44
|
+
return emberPrint(node);
|
|
45
|
+
},
|
|
46
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zmod-ember",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "zmod parser adapter for Ember's .gjs and .gts files via ember-estree",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"codemod",
|
|
7
|
+
"ember",
|
|
8
|
+
"gjs",
|
|
9
|
+
"glimmer",
|
|
10
|
+
"gts",
|
|
11
|
+
"parser",
|
|
12
|
+
"zmod"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/NullVoxPopuli/zmod-ember.git"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"src"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "dist/index.js",
|
|
25
|
+
"types": "dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"import": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"default": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"ember-estree": "^0.2.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^25.5.0",
|
|
39
|
+
"oxfmt": "^0.40.0",
|
|
40
|
+
"oxlint": "^1.55.0",
|
|
41
|
+
"release-plan": "^0.17.4",
|
|
42
|
+
"typescript": "^5.3.3",
|
|
43
|
+
"vitest": "^3.2.1",
|
|
44
|
+
"zmod": "^0.3.1"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"zmod": "^0.3.1"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=20.19.0"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"registry": "https://registry.npmjs.org",
|
|
54
|
+
"access": "public"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"format": "oxfmt",
|
|
58
|
+
"format:check": "oxfmt --check",
|
|
59
|
+
"lint": "oxlint && pnpm format:check",
|
|
60
|
+
"lint:fix": "oxlint --fix && oxfmt",
|
|
61
|
+
"test": "vitest run"
|
|
62
|
+
}
|
|
63
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { toTree, print as emberPrint } from "ember-estree";
|
|
2
|
+
import type { Parser, ParseOptions } from "zmod";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A zmod `Parser` adapter for Ember's `.gjs` and `.gts` files.
|
|
6
|
+
*
|
|
7
|
+
* Uses `ember-estree` to parse files containing `<template>` tags
|
|
8
|
+
* into an ESTree-compatible AST with embedded Glimmer template nodes.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { z } from 'zmod';
|
|
13
|
+
* import { emberParser } from 'zmod-ember';
|
|
14
|
+
*
|
|
15
|
+
* const j = z.withParser(emberParser);
|
|
16
|
+
* const root = j(gjsSource, { filePath: 'my-component.gjs' });
|
|
17
|
+
*
|
|
18
|
+
* root.find(j.Identifier, { name: 'OldName' })
|
|
19
|
+
* .replaceWith('NewName');
|
|
20
|
+
*
|
|
21
|
+
* console.log(root.toSource());
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* // As a transform module export
|
|
27
|
+
* import type { Transform } from 'zmod';
|
|
28
|
+
* import { emberParser } from 'zmod-ember';
|
|
29
|
+
*
|
|
30
|
+
* export const parser = emberParser;
|
|
31
|
+
*
|
|
32
|
+
* const transform: Transform = ({ source }, { z }) => {
|
|
33
|
+
* const root = z(source);
|
|
34
|
+
* // ... transform logic
|
|
35
|
+
* return root.toSource();
|
|
36
|
+
* };
|
|
37
|
+
*
|
|
38
|
+
* export default transform;
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export const emberParser: Parser = {
|
|
42
|
+
parse(source: string, options?: ParseOptions): any {
|
|
43
|
+
return toTree(source, options as any);
|
|
44
|
+
},
|
|
45
|
+
print(node: any): string {
|
|
46
|
+
return emberPrint(node);
|
|
47
|
+
},
|
|
48
|
+
};
|