From 248fcd5d7f69c6a30f498edd627fcf5ae1b0a921 Mon Sep 17 00:00:00 2001 From: Teffen Ellis Date: Mon, 19 May 2025 00:37:49 +0200 Subject: [PATCH] web: Check JS files. Add types. --- web/scripts/build-locales.mjs | 39 +++++++++++++++++++++++----------- web/scripts/eslint.mjs | 5 +++++ web/scripts/pseudolocalize.mjs | 33 ++++++++++++++++++++++------ web/tsconfig.json | 3 +++ 4 files changed, 61 insertions(+), 19 deletions(-) diff --git a/web/scripts/build-locales.mjs b/web/scripts/build-locales.mjs index 991ac8306d..3392e9d6dd 100644 --- a/web/scripts/build-locales.mjs +++ b/web/scripts/build-locales.mjs @@ -1,17 +1,32 @@ -import { spawnSync } from "child_process"; -import fs from "fs"; -import path from "path"; -import process from "process"; +/** + * @file Lit Localize build script. + * + * @remarks + * Determines if all the Xliff translation source files are present and if the Typescript source files generated from those sources are up-to-date. + * + * If they are not, it runs the locale building script, + * intercepting the long spew of "this string is not translated" and replacing it with a + * summary of how many strings are missing with respect to the source locale. + * + * @import { ConfigFile } from "@lit/localize-tools/lib/types/config" + */ +import { PackageRoot } from "@goauthentik/web/paths"; +import { spawnSync } from "node:child_process"; +import { readFileSync, statSync } from "node:fs"; +import path from "node:path"; /** - * Determines if all the Xliff translation source files are present and if the Typescript source - * files generated from those sources are up-to-date. If they are not, it runs the locale building - * script, intercepting the long spew of "this string is not translated" and replacing it with a - * summary of how many strings are missing with respect to the source locale. + * @type {ConfigFile} */ +const localizeRules = JSON.parse( + readFileSync(path.join(PackageRoot, "lit-localize.json"), "utf-8"), +); -const localizeRules = JSON.parse(fs.readFileSync("./lit-localize.json", "utf-8")); - +/** + * + * @param {string} loc + * @returns {boolean} + */ function generatedFileIsUpToDateWithXliffSource(loc) { const xliff = path.join("./xliff", `${loc}.xlf`); const gened = path.join("./src/locales", `${loc}.ts`); @@ -22,7 +37,7 @@ function generatedFileIsUpToDateWithXliffSource(loc) { // generates a unique error message and halts the build. try { - var xlfStat = fs.statSync(xliff); + var xlfStat = statSync(xliff); } catch (_error) { console.error(`lit-localize expected '${loc}.xlf', but XLF file is not present`); process.exit(1); @@ -30,7 +45,7 @@ function generatedFileIsUpToDateWithXliffSource(loc) { // If the generated file doesn't exist, of course it's not up to date. try { - var genedStat = fs.statSync(gened); + var genedStat = statSync(gened); } catch (_error) { return false; } diff --git a/web/scripts/eslint.mjs b/web/scripts/eslint.mjs index 63ba74eebd..3b38f544d1 100644 --- a/web/scripts/eslint.mjs +++ b/web/scripts/eslint.mjs @@ -35,6 +35,11 @@ const __dirname = fileURLToPath(new URL(".", import.meta.url)); const projectRoot = path.join(__dirname, ".."); process.chdir(projectRoot); +/** + * + * @param {string[]} flags + * @returns + */ const hasFlag = (flags) => process.argv.length > 1 && flags.includes(process.argv[2]); const [configFile, files] = hasFlag(["-n", "--nightmare"]) diff --git a/web/scripts/pseudolocalize.mjs b/web/scripts/pseudolocalize.mjs index d0495f15c8..396b4012ee 100644 --- a/web/scripts/pseudolocalize.mjs +++ b/web/scripts/pseudolocalize.mjs @@ -1,22 +1,36 @@ -import { readFileSync } from "fs"; -import path from "path"; +/** + * @file Pseudo-localization script. + * + * @import { ConfigFile } from "@lit/localize-tools/lib/types/config.js" + * @import { Config } from '@lit/localize-tools/lib/types/config.js'; + * @import { ProgramMessage } from "@lit/localize-tools/src/messages.js" + * @import { Locale } from "@lit/localize-tools/src/types/locale.js" + */ +import { PackageRoot } from "@goauthentik/web/paths"; +import { readFileSync } from "node:fs"; +import path from "node:path"; import pseudolocale from "pseudolocale"; -import { fileURLToPath } from "url"; import { makeFormatter } from "@lit/localize-tools/lib/formatters/index.js"; import { sortProgramMessages } from "@lit/localize-tools/lib/messages.js"; import { TransformLitLocalizer } from "@lit/localize-tools/lib/modes/transform.js"; -const __dirname = fileURLToPath(new URL(".", import.meta.url)); -const pseudoLocale = "pseudo-LOCALE"; +const pseudoLocale = /** @type {Locale} */ ("pseudo-LOCALE"); const targetLocales = [pseudoLocale]; -const baseConfig = JSON.parse(readFileSync(path.join(__dirname, "../lit-localize.json"), "utf-8")); + +/** + * @type {ConfigFile} + */ +const baseConfig = JSON.parse(readFileSync(path.join(PackageRoot, "lit-localize.json"), "utf-8")); // Need to make some internal specifications to satisfy the transformer. It doesn't actually matter // which Localizer we use (transformer or runtime), because all of the functionality we care about // is in their common parent class, but I had to pick one. Everything else here is just pure // exploitation of the lit/localize-tools internals. +/** + * @satisfies {Config} + */ const config = { ...baseConfig, baseDir: path.join(__dirname, ".."), @@ -28,6 +42,11 @@ const config = { resolve: (path) => path, }; +/** + * + * @param {ProgramMessage} message + * @returns + */ const pseudoMessagify = (message) => ({ name: message.name, contents: message.contents.map((content) => @@ -36,7 +55,7 @@ const pseudoMessagify = (message) => ({ }); const localizer = new TransformLitLocalizer(config); -const messages = localizer.extractSourceMessages().messages; +const { messages } = localizer.extractSourceMessages(); const translations = messages.map(pseudoMessagify); const sorted = sortProgramMessages([...messages]); const formatter = makeFormatter(config); diff --git a/web/tsconfig.json b/web/tsconfig.json index bc496a7c77..1f71fb71aa 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -2,6 +2,9 @@ { "extends": "@goauthentik/tsconfig", "compilerOptions": { + "checkJs": true, + "allowJs": true, + "resolveJsonModule": true, "allowSyntheticDefaultImports": true, "emitDeclarationOnly": true, "experimentalDecorators": true,