Skip to content

Commit c33dc64

Browse files
committed
feat: improve name handling to avoid duplicates
1 parent 9c9e5fc commit c33dc64

File tree

5 files changed

+66
-14
lines changed

5 files changed

+66
-14
lines changed

src/naming.ts

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,51 @@
1-
export function formatName(name: string) {
2-
return name.toLowerCase().replace(" ", "_")
1+
import { Instance } from "./roblox";
2+
3+
// TODO: allow other cases instead of lower case
4+
export enum Casing {
5+
LowerCase,
6+
}
7+
8+
function formatName(name: string, casing: Casing = Casing.LowerCase) {
9+
switch (casing) {
10+
case Casing.LowerCase:
11+
return name.toLowerCase().replace(" ", "_")
12+
}
13+
}
14+
15+
interface FixNamesOptions {
16+
includeSelf?: boolean;
17+
descendants?: boolean;
18+
casing?: Casing;
19+
}
20+
21+
export function fixNames(instance: Instance, options?: FixNamesOptions) {
22+
let namesCount: Record<string, number> = {}
23+
24+
instance.name = formatName(instance.name, options?.casing)
25+
26+
if (options?.includeSelf)
27+
namesCount[instance.name] = 1
28+
29+
function processChild(child: Instance) {
30+
const name = formatName(child.name, options?.casing)
31+
32+
if (namesCount[name])
33+
namesCount[name]++
34+
else
35+
namesCount[name] = 1
36+
37+
const suffix = namesCount[name] > 1 ? `_${namesCount[name]}` : ""
38+
child.name = name + suffix
39+
}
40+
41+
function processChildren(_instance: Instance) {
42+
_instance.children.forEach(processChild)
43+
44+
if (!options?.descendants)
45+
namesCount = {}
46+
47+
_instance.children.forEach(processChildren)
48+
}
49+
50+
processChildren(instance)
351
}

src/roblox.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ export interface Properties {
77
}
88

99
export interface Instance {
10+
name: string;
1011
readonly className: string;
11-
readonly name: string;
1212
readonly properties: Properties;
1313
readonly children: Instance[];
1414
}

src/translators/jsx.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { formatName } from "../naming";
1+
import { fixNames } from "../naming";
22
import { Instance } from "../roblox";
33
import { TypeScriptSerializer } from "../seralizers/typescript";
44
import { Snippet } from "../snippet";
@@ -9,7 +9,7 @@ function translate(instance: Instance, indent: number = 0): string {
99

1010
snippet.writeLine(`<${instance.className.toLowerCase()}`)
1111
snippet.indent++
12-
snippet.writeLine(`Key="${formatName(instance.name)}"`)
12+
snippet.writeLine(`Key="${instance.name}"`)
1313

1414
Object.entries(instance.properties).forEach(([property, value]) => {
1515
const serialized = serializer.ser(value)
@@ -37,5 +37,7 @@ function translate(instance: Instance, indent: number = 0): string {
3737
}
3838

3939
export function TranslateJsx(instance: Instance): CodegenResult {
40+
fixNames(instance)
41+
4042
return { title: "TypeScript", code: translate(instance), language: "TYPESCRIPT" }
4143
}

src/translators/react.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { formatName } from "../naming";
1+
import { fixNames } from "../naming";
22
import { Instance } from "../roblox";
33
import { LuauSerializer } from "../seralizers/luau";
44
import { Snippet } from "../snippet";
@@ -22,7 +22,7 @@ function translate(instance: Instance, indent: number = 0): string {
2222
snippet.indent++
2323

2424
instance.children.forEach((child) => {
25-
snippet.writeLine(`${formatName(child.name)} = ${translate(child, snippet.indent)},`)
25+
snippet.writeLine(`${child.name} = ${translate(child, snippet.indent)},`)
2626
})
2727

2828
snippet.indent--
@@ -35,5 +35,7 @@ function translate(instance: Instance, indent: number = 0): string {
3535
}
3636

3737
export function TranslateReact(instance: Instance): CodegenResult {
38+
fixNames(instance)
39+
3840
return { title: "Luau", code: translate(instance), language: "PYTHON" }
3941
}

src/translators/vanilla.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { formatName } from "../naming";
1+
import { fixNames } from "../naming";
22
import { Instance } from "../roblox";
33
import { LuauSerializer } from "../seralizers/luau";
44
import { Snippet } from "../snippet";
@@ -7,21 +7,19 @@ function translate(instance: Instance, indent: number = 0, parent?: Instance): s
77
const serializer = new LuauSerializer();
88
const snippet = new Snippet(indent);
99

10-
const name = formatName(instance.name)
11-
const properties = Object.entries(instance.properties)
12-
13-
snippet.writeLine(`local ${name} = Instance.new("${instance.className}")`)
10+
snippet.writeLine(`local ${instance.name} = Instance.new("${instance.className}")`)
1411

12+
const properties = Object.entries(instance.properties)
1513
properties.forEach(([property, value], index) => {
16-
snippet.write(`${name}.${property} = ${serializer.ser(value)}`)
14+
snippet.write(`${instance.name}.${property} = ${serializer.ser(value)}`)
1715

1816
if (index != properties.length - 1)
1917
snippet.newLine()
2018
})
2119

2220
if (parent) {
2321
snippet.newLine()
24-
snippet.write(`${name}.Parent = ${formatName(parent.name)}`)
22+
snippet.write(`${instance.name}.Parent = ${parent.name}`)
2523
}
2624

2725
if (instance.children.length > 0) {
@@ -42,5 +40,7 @@ function translate(instance: Instance, indent: number = 0, parent?: Instance): s
4240
}
4341

4442
export function TranslateVanilla(instance: Instance): CodegenResult {
43+
fixNames(instance, { includeSelf: true, descendants: true })
44+
4545
return { title: "Luau", code: translate(instance), language: "PYTHON" }
4646
}

0 commit comments

Comments
 (0)