diff --git a/scripts/build/createAccountV1Dir.ts b/scripts/build/createAccountV1Dir.ts index e00333c9..2865e251 100644 --- a/scripts/build/createAccountV1Dir.ts +++ b/scripts/build/createAccountV1Dir.ts @@ -1,6 +1,5 @@ import * as fs from "fs"; import { join as pathJoin } from "path"; -import { KEYCLOAK_VERSION } from "../shared/constants"; import { transformCodebase } from "../../src/bin/tools/transformCodebase"; import { downloadKeycloakDefaultTheme } from "../shared/downloadKeycloakDefaultTheme"; import { WELL_KNOWN_DIRECTORY_BASE_NAME } from "../../src/bin/shared/constants"; @@ -10,7 +9,7 @@ import * as fsPr from "fs/promises"; export async function createAccountV1Dir() { const { extractedDirPath } = await downloadKeycloakDefaultTheme({ - keycloakVersion: KEYCLOAK_VERSION.FOR_ACCOUNT_MULTI_PAGE + keycloakVersionId: "FOR_ACCOUNT_MULTI_PAGE" }); const destDirPath = pathJoin( diff --git a/scripts/build/createPublicDotKeycloakifyDir.ts b/scripts/build/createPublicDotKeycloakifyDir.ts index 13044a96..667124ea 100644 --- a/scripts/build/createPublicDotKeycloakifyDir.ts +++ b/scripts/build/createPublicDotKeycloakifyDir.ts @@ -1,6 +1,5 @@ import { join as pathJoin } from "path"; import { downloadKeycloakDefaultTheme } from "../shared/downloadKeycloakDefaultTheme"; -import { KEYCLOAK_VERSION } from "../shared/constants"; import { transformCodebase } from "../../src/bin/tools/transformCodebase"; import { existsAsync } from "../../src/bin/tools/fs.existsAsync"; import { getThisCodebaseRootDirPath } from "../../src/bin/tools/getThisCodebaseRootDirPath"; @@ -11,18 +10,16 @@ import * as fsPr from "fs/promises"; export async function createPublicDotKeycloakifyDir() { await Promise.all( (["login", "account"] as const).map(async themeType => { - const keycloakVersion = (() => { - switch (themeType) { - case "login": - return KEYCLOAK_VERSION.FOR_LOGIN_THEME; - case "account": - return KEYCLOAK_VERSION.FOR_ACCOUNT_MULTI_PAGE; - } - assert>(); - })(); - const { extractedDirPath } = await downloadKeycloakDefaultTheme({ - keycloakVersion + keycloakVersionId: (() => { + switch (themeType) { + case "login": + return "FOR_LOGIN_THEME"; + case "account": + return "FOR_ACCOUNT_MULTI_PAGE"; + } + assert>(); + })() }); const destDirPath = pathJoin( diff --git a/scripts/generate-i18n-messages.ts b/scripts/generate-i18n-messages.ts index 39beaba7..a31c993d 100644 --- a/scripts/generate-i18n-messages.ts +++ b/scripts/generate-i18n-messages.ts @@ -6,14 +6,13 @@ import { dirname as pathDirname, sep as pathSep } from "path"; -import { assert } from "tsafe/assert"; +import { assert, type Equals } from "tsafe/assert"; import { same } from "evt/tools/inDepth"; import { crawl } from "../src/bin/tools/crawl"; import { downloadKeycloakDefaultTheme } from "./shared/downloadKeycloakDefaultTheme"; import { getThisCodebaseRootDirPath } from "../src/bin/tools/getThisCodebaseRootDirPath"; import { deepAssign } from "../src/tools/deepAssign"; import { THEME_TYPES } from "../src/bin/shared/constants"; -import { KEYCLOAK_VERSION } from "./shared/constants"; const propertiesParser: any = require("properties-parser"); if (require.main === module) { @@ -29,13 +28,14 @@ async function generateI18nMessages() { for (const themeType of THEME_TYPES) { const { extractedDirPath } = await downloadKeycloakDefaultTheme({ - keycloakVersion: (() => { + keycloakVersionId: (() => { switch (themeType) { case "login": - return KEYCLOAK_VERSION.FOR_LOGIN_THEME; + return "FOR_LOGIN_THEME"; case "account": - return KEYCLOAK_VERSION.FOR_ACCOUNT_MULTI_PAGE; + return "FOR_ACCOUNT_MULTI_PAGE"; } + assert>(); })() }); diff --git a/scripts/shared/constants.ts b/scripts/shared/constants.ts deleted file mode 100644 index fffddb47..00000000 --- a/scripts/shared/constants.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const KEYCLOAK_VERSION = { - FOR_LOGIN_THEME: "25.0.4", - FOR_ACCOUNT_MULTI_PAGE: "21.1.2" -}; diff --git a/scripts/shared/downloadKeycloakDefaultTheme.ts b/scripts/shared/downloadKeycloakDefaultTheme.ts index 953cac66..3681ccd4 100644 --- a/scripts/shared/downloadKeycloakDefaultTheme.ts +++ b/scripts/shared/downloadKeycloakDefaultTheme.ts @@ -3,9 +3,22 @@ import { downloadAndExtractArchive } from "../../src/bin/tools/downloadAndExtrac import { getProxyFetchOptions } from "../../src/bin/tools/fetchProxyOptions"; import { join as pathJoin } from "path"; import { getThisCodebaseRootDirPath } from "../../src/bin/tools/getThisCodebaseRootDirPath"; +import { assert, type Equals } from "tsafe/assert"; -export async function downloadKeycloakDefaultTheme(params: { keycloakVersion: string }) { - const { keycloakVersion } = params; +const KEYCLOAK_VERSION = { + FOR_LOGIN_THEME: "25.0.4", + FOR_ACCOUNT_MULTI_PAGE: "21.1.2" +} as const; + +export async function downloadKeycloakDefaultTheme(params: { + keycloakVersionId: keyof typeof KEYCLOAK_VERSION; +}) { + const { keycloakVersionId } = params; + + const keycloakVersion = KEYCLOAK_VERSION[keycloakVersionId]; + + let kcNodeModulesKeepFilePaths: Set | undefined = undefined; + let kcNodeModulesKeepFilePaths_lastAccountV1: Set | undefined = undefined; const { extractedDirPath } = await downloadAndExtractArchive({ url: `https://repo1.maven.org/maven2/org/keycloak/keycloak-themes/${keycloakVersion}/keycloak-themes-${keycloakVersion}.jar`, @@ -19,14 +32,299 @@ export async function downloadKeycloakDefaultTheme(params: { keycloakVersion: st npmConfigGetCwd: getThisCodebaseRootDirPath() }), uniqueIdOfOnArchiveFile: "extractOnlyRequiredFiles", - onArchiveFile: async ({ fileRelativePath, writeFile }) => { - const fileRelativePath_target = pathRelative("theme", fileRelativePath); + onArchiveFile: async params => { + const fileRelativePath = pathRelative("theme", params.fileRelativePath); - if (fileRelativePath_target.startsWith("..")) { + if (fileRelativePath.startsWith("..")) { return; } - await writeFile({ fileRelativePath: fileRelativePath_target }); + const { readFile, writeFile } = params; + + if ( + !fileRelativePath.startsWith("base") && + !fileRelativePath.startsWith("keycloak") + ) { + return; + } + + switch (keycloakVersion) { + case KEYCLOAK_VERSION.FOR_LOGIN_THEME: + if ( + !fileRelativePath.startsWith(pathJoin("base", "login")) && + !fileRelativePath.startsWith(pathJoin("keycloak", "login")) && + !fileRelativePath.startsWith(pathJoin("keycloak", "common")) + ) { + return; + } + + if (fileRelativePath.endsWith(".ftl")) { + return; + } + + break; + case KEYCLOAK_VERSION.FOR_ACCOUNT_MULTI_PAGE: + if ( + !fileRelativePath.startsWith(pathJoin("base", "account")) && + !fileRelativePath.startsWith(pathJoin("keycloak", "account")) && + !fileRelativePath.startsWith(pathJoin("keycloak", "common")) + ) { + return; + } + + break; + default: + assert>(false); + } + + last_account_v1_transformations: { + if (keycloakVersion !== KEYCLOAK_VERSION.FOR_ACCOUNT_MULTI_PAGE) { + break last_account_v1_transformations; + } + + skip_web_modules: { + if ( + !fileRelativePath.startsWith( + pathJoin("keycloak", "common", "resources", "web_modules") + ) + ) { + break skip_web_modules; + } + + return; + } + + skip_lib: { + if ( + !fileRelativePath.startsWith( + pathJoin("keycloak", "common", "resources", "lib") + ) + ) { + break skip_lib; + } + + return; + } + + skip_node_modules: { + const nodeModulesRelativeDirPath = pathJoin( + "keycloak", + "common", + "resources", + "node_modules" + ); + + if (!fileRelativePath.startsWith(nodeModulesRelativeDirPath)) { + break skip_node_modules; + } + + if (kcNodeModulesKeepFilePaths_lastAccountV1 === undefined) { + kcNodeModulesKeepFilePaths_lastAccountV1 = new Set([ + pathJoin("patternfly", "dist", "css", "patternfly.min.css"), + pathJoin( + "patternfly", + "dist", + "css", + "patternfly-additions.min.css" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "OpenSans-Regular-webfont.woff2" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "OpenSans-Bold-webfont.woff2" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "OpenSans-Light-webfont.woff2" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "OpenSans-Semibold-webfont.woff2" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "PatternFlyIcons-webfont.ttf" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "PatternFlyIcons-webfont.woff" + ) + ]); + } + + const fileRelativeToNodeModulesPath = fileRelativePath.substring( + nodeModulesRelativeDirPath.length + 1 + ); + + if ( + kcNodeModulesKeepFilePaths_lastAccountV1.has( + fileRelativeToNodeModulesPath + ) + ) { + break skip_node_modules; + } + + return; + } + + patch_account_css: { + if ( + fileRelativePath !== + pathJoin("keycloak", "account", "resources", "css", "account.css") + ) { + break patch_account_css; + } + + await writeFile({ + fileRelativePath, + modifiedData: Buffer.from( + (await readFile()) + .toString("utf8") + .replace("top: -34px;", "top: -34px !important;"), + "utf8" + ) + }); + + return; + } + } + + skip_unused_resources: { + if (keycloakVersion !== KEYCLOAK_VERSION.FOR_LOGIN_THEME) { + break skip_unused_resources; + } + + skip_node_modules: { + const nodeModulesRelativeDirPath = pathJoin( + "keycloak", + "common", + "resources", + "node_modules" + ); + + if (!fileRelativePath.startsWith(nodeModulesRelativeDirPath)) { + break skip_node_modules; + } + + if (kcNodeModulesKeepFilePaths === undefined) { + kcNodeModulesKeepFilePaths = new Set([ + pathJoin("@patternfly", "patternfly", "patternfly.min.css"), + pathJoin("patternfly", "dist", "css", "patternfly.min.css"), + pathJoin( + "patternfly", + "dist", + "css", + "patternfly-additions.min.css" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "OpenSans-Regular-webfont.woff2" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "OpenSans-Light-webfont.woff2" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "OpenSans-Bold-webfont.woff2" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "OpenSans-Bold-webfont.woff" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "OpenSans-Bold-webfont.ttf" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "fontawesome-webfont.woff2" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "PatternFlyIcons-webfont.ttf" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "PatternFlyIcons-webfont.woff" + ), + pathJoin( + "patternfly", + "dist", + "fonts", + "OpenSans-Semibold-webfont.woff2" + ), + pathJoin("patternfly", "dist", "img", "bg-login.jpg"), + pathJoin("jquery", "dist", "jquery.min.js") + ]); + } + + const fileRelativeToNodeModulesPath = fileRelativePath.substring( + nodeModulesRelativeDirPath.length + 1 + ); + + if (kcNodeModulesKeepFilePaths.has(fileRelativeToNodeModulesPath)) { + break skip_node_modules; + } + + return; + } + + skip_vendor: { + if ( + !fileRelativePath.startsWith( + pathJoin("keycloak", "common", "resources", "vendor") + ) + ) { + break skip_vendor; + } + + return; + } + + skip_rollup_config: { + if ( + fileRelativePath !== + pathJoin("keycloak", "common", "resources", "rollup.config.js") + ) { + break skip_rollup_config; + } + + return; + } + } + + await writeFile({ fileRelativePath }); } });