Skip to content

Commit

Permalink
Merge pull request #2 from bertdeblock/ensure-unique-identifiers
Browse files Browse the repository at this point in the history
Ensure unique identifiers
  • Loading branch information
bertdeblock authored Feb 27, 2024
2 parents b277ec2 + acf48a3 commit dc5de8a
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 33 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"dependencies": {
"chalk": "^5.3.0",
"change-case": "^5.4.3",
"execa": "^8.0.1",
"fast-glob": "^3.3.2",
"fs-extra": "^11.2.0"
},
Expand Down
20 changes: 3 additions & 17 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 47 additions & 7 deletions src/generate-template-registry.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import chalk from "chalk";
import { camelCase, pascalCase } from "change-case";
import { execa } from "execa";
import glob from "fast-glob";
import { pathExists, readJson } from "fs-extra/esm";
import { writeFile } from "node:fs/promises";
Expand Down Expand Up @@ -29,11 +30,15 @@ export async function generateTemplateRegistry(cwd = processCwd()) {
const helpers = await getEntries(join(cwd, srcDir, "helpers"));
const modifiers = await getEntries(join(cwd, srcDir, "modifiers"));

const identifiers = new Identifiers();

let templateRegistryContent = "";

if (components.length > 0) {
const componentImports = components.map((name) => {
return `import type ${pascalCase(name)}Component from "${importRoot}/components/${name}";`;
const identifier = identifiers.generate(name, pascalCase, "Component");

return `import type ${identifier} from "${importRoot}/components/${name}";`;
});

templateRegistryContent += "// Components:\n";
Expand All @@ -42,7 +47,9 @@ export async function generateTemplateRegistry(cwd = processCwd()) {

if (helpers.length > 0) {
const helperImports = helpers.map((name) => {
return `import type ${camelCase(name)}Helper from "${importRoot}/helpers/${name}";`;
const identifier = identifiers.generate(name, camelCase, "Helper");

return `import type ${identifier} from "${importRoot}/helpers/${name}";`;
});

templateRegistryContent += "// Helpers:\n";
Expand All @@ -51,7 +58,9 @@ export async function generateTemplateRegistry(cwd = processCwd()) {

if (modifiers.length > 0) {
const modifierImports = modifiers.map((name) => {
return `import type ${camelCase(name)}Modifier from "${importRoot}/modifiers/${name}";`;
const identifier = identifiers.generate(name, camelCase, "Modifier");

return `import type ${identifier} from "${importRoot}/modifiers/${name}";`;
});

templateRegistryContent += "// Modifiers:\n";
Expand All @@ -66,8 +75,8 @@ export async function generateTemplateRegistry(cwd = processCwd()) {
let componentsContent = " // Components:\n";

components.forEach((name) => {
componentsContent += ` ${angleBracketNotation(name)}: typeof ${pascalCase(name)}Component;\n`;
componentsContent += ` "${name}": typeof ${pascalCase(name)}Component;\n`;
componentsContent += ` ${angleBracketNotation(name)}: typeof ${identifiers.for(name)};\n`;
componentsContent += ` "${name}": typeof ${identifiers.for(name)};\n`;
});

entriesContent.push(componentsContent);
Expand All @@ -77,7 +86,7 @@ export async function generateTemplateRegistry(cwd = processCwd()) {
let helpersContent = " // Helpers:\n";

helpers.forEach((name) => {
helpersContent += ` "${name}": typeof ${camelCase(name)}Helper;\n`;
helpersContent += ` "${name}": typeof ${identifiers.for(name)};\n`;
});

entriesContent.push(helpersContent);
Expand All @@ -87,7 +96,7 @@ export async function generateTemplateRegistry(cwd = processCwd()) {
let modifiersContent = " // Modifiers:\n";

modifiers.forEach((name) => {
modifiersContent += ` "${name}": typeof ${camelCase(name)}Modifier;\n`;
modifiersContent += ` "${name}": typeof ${identifiers.for(name)};\n`;
});

entriesContent.push(modifiersContent);
Expand All @@ -99,6 +108,12 @@ export async function generateTemplateRegistry(cwd = processCwd()) {

await writeFile(templateRegistryPath, templateRegistryContent);

try {
await execa("npx", ["prettier", "--write", templateRegistryPath]);
} catch {
// Move on.
}

console.log(
chalk.green(`Template registry generated at ${templateRegistryPath}`),
);
Expand Down Expand Up @@ -150,3 +165,28 @@ function angleBracketNotation(name: string) {

return result;
}

class Identifiers {
map: Record<string, string> = {};
seen: Record<string, number> = {};

for(name: string) {
return this.map[name];
}

generate(
name: string,
transform: typeof camelCase | typeof pascalCase,
suffix: string,
) {
let identifier = `${transform(name)}${suffix}`;

this.seen[identifier] = (this.seen[identifier] || 0) + 1;

identifier += this.seen[identifier] > 1 ? this.seen[identifier] : "";

this.map[name] = identifier;

return identifier;
}
}
27 changes: 18 additions & 9 deletions test/__snapshots__/generate-template-registry.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,62 @@
exports[`generates a template registry for a v1 addon 1`] = `
"// Components:
import type BarComponent from "v1-addon/components/bar";
import type FooBarComponent from "v1-addon/components/foo-bar";
import type FooComponent from "v1-addon/components/foo";
import type FooBarComponent from "v1-addon/components/foo/bar";
import type FooBarComponent2 from "v1-addon/components/foo/bar";
export default interface Registry {
// Components:
Bar: typeof BarComponent;
"bar": typeof BarComponent;
FooBar: typeof FooBarComponent;
"foo-bar": typeof FooBarComponent;
Foo: typeof FooComponent;
"foo": typeof FooComponent;
"Foo::Bar": typeof FooBarComponent;
"foo/bar": typeof FooBarComponent;
"Foo::Bar": typeof FooBarComponent2;
"foo/bar": typeof FooBarComponent2;
}
"
`;

exports[`generates a template registry for a v2 addon 1`] = `
"// Components:
import type BarComponent from "./components/bar";
import type FooBarComponent from "./components/foo-bar";
import type FooComponent from "./components/foo";
import type FooBarComponent from "./components/foo/bar";
import type FooBarComponent2 from "./components/foo/bar";
export default interface Registry {
// Components:
Bar: typeof BarComponent;
"bar": typeof BarComponent;
FooBar: typeof FooBarComponent;
"foo-bar": typeof FooBarComponent;
Foo: typeof FooComponent;
"foo": typeof FooComponent;
"Foo::Bar": typeof FooBarComponent;
"foo/bar": typeof FooBarComponent;
"Foo::Bar": typeof FooBarComponent2;
"foo/bar": typeof FooBarComponent2;
}
"
`;

exports[`generates a template registry for an app 1`] = `
"// Components:
import type BarComponent from "app/components/bar";
import type FooBarComponent from "app/components/foo-bar";
import type FooComponent from "app/components/foo";
import type FooBarComponent from "app/components/foo/bar";
import type FooBarComponent2 from "app/components/foo/bar";
export default interface Registry {
// Components:
Bar: typeof BarComponent;
"bar": typeof BarComponent;
FooBar: typeof FooBarComponent;
"foo-bar": typeof FooBarComponent;
Foo: typeof FooComponent;
"foo": typeof FooComponent;
"Foo::Bar": typeof FooBarComponent;
"foo/bar": typeof FooBarComponent;
"Foo::Bar": typeof FooBarComponent2;
"foo/bar": typeof FooBarComponent2;
}
"
`;
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.

0 comments on commit dc5de8a

Please sign in to comment.