69 lines
1.8 KiB
TypeScript
69 lines
1.8 KiB
TypeScript
|
|
import { readFileSync, readdirSync, writeFileSync } from "node:fs";
|
||
|
|
import { join, resolve } from "node:path";
|
||
|
|
import { normalizePath } from "vite";
|
||
|
|
import type { Plugin, ResolvedConfig } from "vite";
|
||
|
|
|
||
|
|
interface Options {
|
||
|
|
sourceDir: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
type JsonValue = string | number | boolean | null | JsonObject | JsonValue[];
|
||
|
|
type JsonObject = { [key: string]: JsonValue };
|
||
|
|
|
||
|
|
function deepSortKeys(obj: JsonObject): JsonObject {
|
||
|
|
const sorted: JsonObject = {};
|
||
|
|
for (const key of Object.keys(obj).sort()) {
|
||
|
|
const value = obj[key];
|
||
|
|
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
||
|
|
sorted[key] = deepSortKeys(value as JsonObject);
|
||
|
|
} else {
|
||
|
|
sorted[key] = value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return sorted;
|
||
|
|
}
|
||
|
|
|
||
|
|
function sortFile(filePath: string): void {
|
||
|
|
const raw = readFileSync(filePath, "utf-8");
|
||
|
|
const parsed = JSON.parse(raw) as JsonObject;
|
||
|
|
const sorted = deepSortKeys(parsed);
|
||
|
|
const output = JSON.stringify(sorted, null, "\t") + "\n";
|
||
|
|
|
||
|
|
if (raw !== output) {
|
||
|
|
writeFileSync(filePath, output, "utf-8");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function sortAllFiles(sourceDir: string): void {
|
||
|
|
const files = readdirSync(sourceDir).filter((f) => f.endsWith(".json"));
|
||
|
|
for (const file of files) {
|
||
|
|
sortFile(join(sourceDir, file));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export function i18nextSortPlugin(options: Options): Plugin {
|
||
|
|
let resolvedSourceDir: string;
|
||
|
|
|
||
|
|
return {
|
||
|
|
name: "i18next-sort",
|
||
|
|
|
||
|
|
configResolved(config: ResolvedConfig) {
|
||
|
|
resolvedSourceDir = normalizePath(resolve(config.root, options.sourceDir));
|
||
|
|
},
|
||
|
|
|
||
|
|
buildStart() {
|
||
|
|
sortAllFiles(resolvedSourceDir);
|
||
|
|
},
|
||
|
|
|
||
|
|
configureServer(server) {
|
||
|
|
server.watcher.add(resolvedSourceDir);
|
||
|
|
|
||
|
|
server.watcher.on("change", (file: string) => {
|
||
|
|
if (file.startsWith(resolvedSourceDir) && file.endsWith(".json")) {
|
||
|
|
sortFile(file);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
},
|
||
|
|
};
|
||
|
|
}
|