Skip to content

Commit

Permalink
fix: parser return convention
Browse files Browse the repository at this point in the history
  • Loading branch information
ceopaludetto committed May 24, 2024
1 parent 8b40e4e commit cd925c3
Show file tree
Hide file tree
Showing 22 changed files with 59 additions and 49 deletions.
Binary file modified bun.lockb
Binary file not shown.
3 changes: 2 additions & 1 deletion examples/vite-react/src/application.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useTranslation } from "@diacritic/react";

export function Application() {
const { t, language, setLanguage } = useTranslation(["common"]);
const { t, language, setLanguage } = useTranslation(["common", "withHyphen"]);

return (
<div>
<h1>{t.common.hello()}</h1>
<p>{t.withHyphen.someKey()}</p>
<p>{t.common.interpolation(10)}</p>
<button onClick={() => setLanguage(language === "en" ? "pt" : "en")}>
{t.common.actions.switch()}
Expand Down
3 changes: 3 additions & 0 deletions examples/vite-react/src/locales/en/with-hyphen.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"some-key": "value"
}
3 changes: 3 additions & 0 deletions examples/vite-react/src/locales/pt/with-hyphen.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"some-key": "valor"
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"docs:preview": "vitepress preview documentation",
"lint:fix": "turbo lint --cache-dir=.turbo -- --fix && manypkg fix",
"lint": "turbo lint --cache-dir=.turbo && manypkg check",
"release": "bun run build && bun run docs:build && bun changesets publish",
"release": "bun run build && bun run docs:build && bun changeset publish",
"test:update": "turbo test --cache-dir=.turbo -- --update-snapshots",
"test": "turbo test --cache-dir=.turbo"
},
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"test": "bun test"
},
"dependencies": {
"@diacritic/utilities": "workspace:",
"dset": "^3.1.3",
"glob": "^10.3.15",
"tiny-invariant": "^1.3.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export const diacritic = createUnplugin<DiacriticOptions>(({
invariant(files.length > 0, `There's no language resource available [${resource}]`);

const entries = files.flatMap(item => parser.convertFile(item));
const functions = entries.map(item => createFunctionFromEntry(parser.interpolation, item));
const functions = entries.map(item => createFunctionFromEntry(item));

return { code: functions.join(EOL) };
}
Expand Down
9 changes: 3 additions & 6 deletions packages/core/src/utilities/generator/modules.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import type { Entry, Parser } from "../types";
import type { Entry } from "../types";

import { EOL } from "node:os";

import { prefixes } from "../loader";

export function createFunctionFromEntry(interpolation: Parser["interpolation"], entry: Entry) {
const interpolators = interpolation.map(side => side.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
const regex = new RegExp(`${interpolators[0]}\\s*(\\w+)\\s*\\|\\s*[\\w\\s]*\\s*${interpolators[1]}`, "g");

export function createFunctionFromEntry(entry: Entry) {
return [
`export function ${entry.name}(${entry.args.map(item => item.name + ": " + item.type)}) {`,
`\treturn \`${entry.return.replace(regex, (_, content) => `\${${content}}`)}\`;`,
`\treturn \`${entry.return}\`;`,
`}`,
].join(EOL);
}
Expand Down
6 changes: 2 additions & 4 deletions packages/core/src/utilities/generator/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,9 @@ export function generateTypes({
);

for (const [namespace, files] of Object.entries(entries)) {
const contents = files
.map(file => readFileSync(file, "utf-8"))
.flatMap(content => parser.convertFile(content));

const contents = files.map(file => readFileSync(file, "utf-8")).flatMap(parser.convertFile);
const structure = {};

for (const entry of contents) dset(structure, entry.path, functionFromEntry(entry));

declarations.push(
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/utilities/resource.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { resolve } from "node:path";

import { toCamelCase } from "@diacritic/utilities";
import { globSync } from "glob";

export class ResourceGraph {
Expand All @@ -13,7 +14,7 @@ export class ResourceGraph {

const regex = new RegExp(pattern.replace("*", "(.*)"));
for (const file of files) {
const namespace = file.match(regex)?.[1] ?? "default";
const namespace = toCamelCase(file.match(regex)![1]!);

if (!this.graph[language]) this.graph[language] = {};
if (!this.graph[language]![namespace]) this.graph[language]![namespace] = [];
Expand Down Expand Up @@ -66,7 +67,7 @@ export class ResourceGraph {
const regex = new RegExp(resource.replaceAll("*", "(.*)").replace("{{language}}", "(.*)"));
const match = file.match(regex);

if (match) return { language: match[1]!, namespace: match[2]! };
if (match) return { language: match[1]!, namespace: toCamelCase(match[2]!) };
}

throw new Error(`Could not determine language and namespace from file: ${file}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`createFunctionFromEntry should create a function from an entry correctly 1`] = `
"export function hello(name: string) {
return \`Hello, { name : string }!\`;
return \`Hello, ${name}!\`;
}"
`;
Expand Down
5 changes: 3 additions & 2 deletions packages/core/test/utilities/generator/modules.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-template-curly-in-string */
import type { Entry } from "~/utilities/types";

import { describe, expect, it } from "bun:test";
Expand All @@ -10,10 +11,10 @@ describe("createFunctionFromEntry", () => {
name: "hello",
path: "hello",
args: [{ name: "name", type: "string" }],
return: "Hello, { name : string }!",
return: "Hello, ${name}!",
};

expect(createFunctionFromEntry(["{", "}"], entry)).toMatchSnapshot();
expect(createFunctionFromEntry(entry)).toMatchSnapshot();
});
});

Expand Down
1 change: 0 additions & 1 deletion packages/detector/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
"tiny-invariant": "^1.3.3"
},
"devDependencies": {
"@diacritic/utilities": "workspace:",
"@types/accept-language-parser": "^1.5.6"
}
}
5 changes: 2 additions & 3 deletions packages/parser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@
"test": "bun test"
},
"dependencies": {
"@diacritic/core": "workspace:",
"@diacritic/utilities": "workspace:",
"tiny-invariant": "^1.3.3"
},
"devDependencies": {
"@diacritic/utilities": "workspace:"
}
}
20 changes: 14 additions & 6 deletions packages/parser/src/json.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import type { Entry, Parser } from "@diacritic/core";

import { toCamelCase } from "@diacritic/utilities";

import { extractArgumentsFromString, functionName } from "./utilities/parser";

function parseContent(content: Record<string, any>, parent: string[] = []): Entry[] {
return Object.entries(content)
.reduce<Entry[]>((acc, [key, value]) => {
if (typeof value !== "string" && (typeof value !== "object" || Array.isArray(value))) return acc;
if (typeof value === "object") return [...acc, ...parseContent(value, [...parent, key])];
if (typeof value === "object" && !Array.isArray(value))
return [...acc, ...parseContent(value, [...parent, toCamelCase(key)])];

if (typeof value === "string") {
const name = functionName(parent, key);
const args = extractArgumentsFromString(value);

const str = value.replace(/\{\s*(\w+)\s*:\s*(\w+)\s*\}/g, (_, name) => `\${${name}}`);

const name = functionName(parent, key);
const args = extractArgumentsFromString(value);
const fn = { name, path: [...parent, toCamelCase(key)].join("."), args, return: str };

const fn = { name, path: [...parent, key].join("."), args, return: value };
return [...acc, fn];
}

return [...acc, fn];
return acc;
}, []);
}

Expand Down
6 changes: 3 additions & 3 deletions packages/parser/src/utilities/parser.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { Entry } from "@diacritic/core";

import { capitalizeFirst } from "@diacritic/utilities";
import { capitalizeFirst, toCamelCase } from "@diacritic/utilities";
import invariant from "tiny-invariant";

export function functionName(parent: string[], key: string) {
return [...parent, key].reduce((acc, item, index) => {
if (index === 0) return acc + item;
return acc + capitalizeFirst(item);
if (index === 0) return acc + toCamelCase(item);
return acc + capitalizeFirst(toCamelCase(item));
}, "");
}

Expand Down
5 changes: 3 additions & 2 deletions packages/parser/test/json.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-template-curly-in-string */
import { describe, expect, it } from "bun:test";

import parserJson from "~/json";
Expand Down Expand Up @@ -26,8 +27,8 @@ describe("parseJson", () => {
expect(parser.convertFile(json)).toStrictEqual([
{ name: "hello", path: "hello", args: [], return: "world" },
{ name: "someDeepNest", path: "some.deep.nest", args: [], return: "content" },
{ name: "someDeepInterpolated", path: "some.deep.interpolated", args: [{ name: "a", type: "number" }], return: "{ a : number }" },
{ name: "interpolator", path: "interpolator", args: [{ name: "value", type: "string" }], return: "some { value : string }" },
{ name: "someDeepInterpolated", path: "some.deep.interpolated", args: [{ name: "a", type: "number" }], return: "${a}" },
{ name: "interpolator", path: "interpolator", args: [{ name: "value", type: "string" }], return: "some ${value}" },
]);
});
});
1 change: 0 additions & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"tiny-invariant": "^1.3.3"
},
"devDependencies": {
"@diacritic/utilities": "workspace:",
"@types/react": "^18.3.2",
"react": "^18.3.1"
}
Expand Down
4 changes: 1 addition & 3 deletions packages/runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@
"test": "bun test"
},
"dependencies": {
"@diacritic/utilities": "workspace:",
"proxy-deep": "^4.0.1",
"tiny-invariant": "^1.3.3"
},
"devDependencies": {
"@diacritic/utilities": "workspace:"
}
}
11 changes: 0 additions & 11 deletions packages/utilities/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,7 @@
"lint": "eslint src",
"test": "bun test"
},
"peerDependencies": {
"@diacritic/core": "workspace:"
},
"peerDependenciesMeta": {
"@diacritic/core": {
"optional": false
}
},
"dependencies": {
"tiny-invariant": "^1.3.3"
},
"devDependencies": {
"@diacritic/core": "workspace:"
}
}
4 changes: 4 additions & 0 deletions packages/utilities/src/string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ export function capitalizeFirst(str: string) {
if (!str[0]) return str;
return str[0].toUpperCase() + str.slice(1);
}

export function toCamelCase(str: string) {
return str.replace(/[-_](.)/g, (_, c) => c.toUpperCase());
}
10 changes: 9 additions & 1 deletion packages/utilities/test/string.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { describe, expect, it } from "bun:test";

import { capitalizeFirst } from "~/string";
import { capitalizeFirst, toCamelCase } from "~/string";

describe("capitalizeFirst", () => {
it("should correctly capitalize the first letter", () => {
expect(capitalizeFirst("carlos")).toBe("Carlos");
});
});

describe("toCamelCase", () => {
it("should correctly convert a string to camel case", () => {
expect(toCamelCase("carlos-eduardo")).toBe("carlosEduardo");
expect(toCamelCase("carlos_eduardo")).toBe("carlosEduardo");
expect(toCamelCase("carlosEduardo")).toBe("carlosEduardo");
});
});

0 comments on commit cd925c3

Please sign in to comment.