Skip to content

Commit b39ca2c

Browse files
authored
Separated concerns in @codemod-utils/ast-template-tag (#189)
* breaking: Separated preprocess() into findTemplateTags() and toEcma() * chore: Updated tests * breaking: Generalized replaceTemplate() * chore: Updated tests * chore: Updated documentation * chore: Added changeset
1 parent d232b31 commit b39ca2c

38 files changed

Lines changed: 815 additions & 447 deletions

.changeset/sharp-dodos-fall.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@codemod-utils/ast-template-tag": minor
3+
---
4+
5+
Separated preprocess() into findTemplateTags() and toEcma()

.changeset/wide-spoons-warn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@codemod-utils/ast-template-tag": minor
3+
---
4+
5+
Generalized replaceTemplate()

packages/ast/template-tag/README.md

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,67 +33,81 @@ const newFile = updateTemplates(oldFile, transform);
3333

3434
## API
3535

36-
### preprocess
36+
### findTemplateTags
3737

38-
Processes a file with `<template>` tags into things that work with existing methods or libraries.
39-
40-
⚠️ Likely, you won't need this method but [`updateJavaScript`](#updatejavascript) instead.
38+
Finds `<template>` tags in a file.
4139

4240
<details>
4341

4442
<summary>Example</summary>
4543

46-
Analyze the JavaScript part of the file.
44+
Count the number of lines of code (LOC) in `<template>` tags.
4745

4846
```ts
49-
const { javascript } = preprocess(file);
47+
function getLOC(code: string): number {
48+
const matches = file.match(/\r?\n/g);
5049

51-
// Some method that checks `*.{js,ts}` files
52-
analyze(javascript);
50+
return (matches ?? []).length;
51+
}
52+
53+
const templateTags = findTemplateTags(file);
54+
55+
let loc = 0;
56+
57+
templateTags.forEach(({ contents }) => {
58+
loc += getLOC(contents.trim());
59+
});
5360
```
5461

5562
</details>
5663

64+
65+
### replaceTemplateTag
66+
67+
Replaces a particular `<template>` tag.
68+
69+
⚠️ Likely, you won't need this method but [`updateTemplates`](#updatetemplates) instead.
70+
5771
<details>
5872

5973
<summary>Example</summary>
6074

61-
Count the number of lines inside `<template>` tags.
75+
Update all template tags in a file.
6276

6377
```ts
64-
const { templateTags } = preprocess(file);
78+
const templateTags = findTemplateTags(file);
6579

66-
let numOfLines = 0;
80+
templateTags.reverse().forEach(({ contents, range }) => {
81+
// Some method that can update `*.hbs` files
82+
const template = transform(contents);
6783

68-
templateTags.forEach(({ contents }) => {
69-
numOfLines += contents.trim().split('\n').length;
84+
file = replaceTemplateTag(file, {
85+
code: `<template>${template}</template>`,
86+
range,
87+
});
7088
});
7189
```
7290

7391
</details>
7492

7593

76-
### replaceTemplate
94+
### toEcma
7795

78-
Replaces the template of a particular `<template>` tag.
96+
Converts a file with `<template>` tags to standard JavaScript.
7997

80-
⚠️ Likely, you won't need this method but [`updateTemplates`](#updatetemplates) instead.
98+
⚠️ Likely, you won't need this method but [`updateJavaScript`](#updatejavascript) instead.
8199

82100
<details>
83101

84102
<summary>Example</summary>
85103

86-
Update the template in each tag.
104+
Analyze the JavaScript part of the file.
87105

88106
```ts
89-
const { templateTags } = preprocess(file);
107+
const ecma = toEcma(file);
90108

91-
templateTags.reverse().forEach(({ contents, range }) => {
92-
// Some method that can update `*.hbs` files
93-
const template = transform(contents);
94-
95-
file = replaceTemplate(file, { range, template });
96-
});
109+
// Some method that checks `*.{js,ts}` files
110+
analyze(ecma);
97111
```
98112

99113
</details>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { type Parsed as TemplateTag, Preprocessor } from 'content-tag';
2+
3+
const preprocessor = new Preprocessor();
4+
5+
/**
6+
* Finds `<template>` tags in a file.
7+
*
8+
* @param file
9+
*
10+
* A `*.{gjs,gts}` file.
11+
*
12+
* @return
13+
*
14+
* A sorted array that tracks tag contents and locations.
15+
*
16+
* @example
17+
*
18+
* Count the number of lines of code (LOC) in `<template>` tags.
19+
*
20+
* ```ts
21+
* function getLOC(code: string): number {
22+
* const matches = file.match(/\r?\n/g);
23+
*
24+
* return (matches ?? []).length;
25+
* }
26+
*
27+
* const templateTags = findTemplateTags(file);
28+
*
29+
* let loc = 0;
30+
*
31+
* templateTags.forEach(({ contents }) => {
32+
* loc += getLOC(contents.trim());
33+
* });
34+
* ```
35+
*/
36+
export function findTemplateTags(file: string): TemplateTag[] {
37+
const templateTags = preprocessor.parse(file);
38+
39+
return templateTags;
40+
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
export * from './preprocess.js';
2-
export * from './replace-template.js';
1+
export * from './find-template-tags.js';
2+
export * from './replace-template-tag.js';
3+
export * from './to-ecma.js';
34
export * from './update-javascript.js';
45
export * from './update-templates.js';

packages/ast/template-tag/src/preprocess.ts

Lines changed: 0 additions & 54 deletions
This file was deleted.

packages/ast/template-tag/src/replace-template.ts renamed to packages/ast/template-tag/src/replace-template-tag.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ function sliceByteRange(
2424
}
2525

2626
/**
27-
* Replaces the template of a particular `<template>` tag.
27+
* Replaces a particular `<template>` tag.
2828
*
2929
* @param file
3030
*
3131
* A `*.{gjs,gts}` file.
3232
*
3333
* @param data
3434
*
35-
* An object with `range` (tag location) and `template` (what to
35+
* An object with `range` (tag location) and `code` (what to
3636
* replace with).
3737
*
3838
* @return
@@ -41,33 +41,34 @@ function sliceByteRange(
4141
*
4242
* @example
4343
*
44-
* Update the template in each tag.
44+
* Update all template tags in a file.
4545
*
4646
* ```ts
47-
* const { templateTags } = preprocess(file);
47+
* const templateTags = findTemplateTags(file);
4848
*
4949
* templateTags.reverse().forEach(({ contents, range }) => {
5050
* // Some method that can update `*.hbs` files
5151
* const template = transform(contents);
5252
*
53-
* file = replaceTemplate(file, { range, template });
53+
* file = replaceTemplateTag(file, {
54+
* code: `<template>${template}</template>`,
55+
* range,
56+
* });
5457
* });
5558
* ```
5659
*/
57-
export function replaceTemplate(
60+
export function replaceTemplateTag(
5861
file: string,
5962
data: {
63+
code: string;
6064
range: Range;
61-
template: string;
6265
},
6366
): string {
64-
const { range, template } = data;
67+
const { code, range } = data;
6568

6669
return [
6770
sliceByteRange(file, 0, range.startByte),
68-
'<template>',
69-
template,
70-
'</template>',
71+
code,
7172
sliceByteRange(file, range.endByte, undefined),
7273
].join('');
7374
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Preprocessor } from 'content-tag';
2+
3+
const preprocessor = new Preprocessor();
4+
5+
/**
6+
* Converts a file with `<template>` tags to standard JavaScript.
7+
*
8+
* @param file
9+
*
10+
* A `*.{gjs,gts}` file.
11+
*
12+
* @return
13+
*
14+
* File in standard JavaScript.
15+
*
16+
* @example
17+
*
18+
* Analyze the JavaScript part of the file.
19+
*
20+
* ```ts
21+
* const ecma = toEcma(file);
22+
*
23+
* // Some method that checks `*.{js,ts}` files
24+
* analyze(ecma);
25+
* ```
26+
*/
27+
export function toEcma(file: string): string {
28+
const { code } = preprocessor.process(file);
29+
30+
return code;
31+
}

packages/ast/template-tag/src/update-templates.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { preprocess } from './preprocess.js';
2-
import { replaceTemplate } from './replace-template.js';
1+
import { findTemplateTags } from './find-template-tags.js';
2+
import { replaceTemplateTag } from './replace-template-tag.js';
33

44
/**
55
* Updates the `<template>` tags in a file. Leaves the JavaScript
@@ -55,12 +55,15 @@ export function updateTemplates(
5555
file: string,
5656
update: (code: string) => string,
5757
): string {
58-
const { templateTags } = preprocess(file);
58+
const templateTags = findTemplateTags(file);
5959

6060
templateTags.reverse().forEach(({ contents, range }) => {
6161
const template = update(contents);
6262

63-
file = replaceTemplate(file, { range, template });
63+
file = replaceTemplateTag(file, {
64+
code: `<template>${template}</template>`,
65+
range,
66+
});
6467
});
6568

6669
return file;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { assert, test } from '@codemod-utils/tests';
2+
3+
import { findTemplateTags } from '../../src/index.js';
4+
5+
test('find-template-tags > base case', function () {
6+
const oldFile = '';
7+
8+
const templateTags = findTemplateTags(oldFile);
9+
10+
assert.deepStrictEqual(templateTags, []);
11+
});

0 commit comments

Comments
 (0)