Merge branch 'main' into i18n_extraLanguages_and_perThemeVariantTranslations

This commit is contained in:
Joseph Garrone 2024-09-22 18:15:25 +02:00
commit 08f03b3118
14 changed files with 43 additions and 79 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "keycloakify", "name": "keycloakify",
"version": "10.1.0", "version": "10.1.4",
"description": "Create Keycloak themes using React", "description": "Create Keycloak themes using React",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -1,59 +1,8 @@
import * as child_process from "child_process"; import * as child_process from "child_process";
import { transformCodebase } from "../src/bin/tools/transformCodebase";
import { join as pathJoin, sep as pathSep } from "path";
import { assert } from "tsafe/assert";
run("yarn build"); run("yarn build");
run("npx build-storybook"); run("npx build-storybook");
const storybookStaticDirPath = "storybook-static";
{
let hasPatched = false;
transformCodebase({
srcDirPath: storybookStaticDirPath,
destDirPath: storybookStaticDirPath,
transformSourceCode: ({ fileRelativePath, sourceCode }) => {
replace_dot_keycloakify: {
if (fileRelativePath.includes(pathSep)) {
break replace_dot_keycloakify;
}
if (!fileRelativePath.endsWith(".js")) {
break replace_dot_keycloakify;
}
const search = `DOT_KEYCLOAKIFY:".keycloakify"`;
if (!sourceCode.includes(search)) {
break replace_dot_keycloakify;
}
hasPatched = true;
return {
modifiedSourceCode: Buffer.from(
sourceCode
.toString("utf8")
.replace(search, `DOT_KEYCLOAKIFY:"dot_keycloakify"`),
"utf8"
)
};
}
return { modifiedSourceCode: sourceCode };
}
});
assert(hasPatched);
}
transformCodebase({
srcDirPath: pathJoin(storybookStaticDirPath, ".keycloakify"),
destDirPath: pathJoin(storybookStaticDirPath, "dot_keycloakify")
});
function run(command: string, options?: { env?: NodeJS.ProcessEnv }) { function run(command: string, options?: { env?: NodeJS.ProcessEnv }) {
console.log(`$ ${command}`); console.log(`$ ${command}`);

View File

@ -7,7 +7,7 @@ import { WELL_KNOWN_DIRECTORY_BASE_NAME } from "../../src/bin/shared/constants";
import { assert, type Equals } from "tsafe/assert"; import { assert, type Equals } from "tsafe/assert";
import * as fsPr from "fs/promises"; import * as fsPr from "fs/promises";
export async function createPublicDotKeycloakifyDir() { export async function createPublicKeycloakifyDevResourcesDir() {
await Promise.all( await Promise.all(
(["login", "account"] as const).map(async themeType => { (["login", "account"] as const).map(async themeType => {
const { extractedDirPath } = await downloadKeycloakDefaultTheme({ const { extractedDirPath } = await downloadKeycloakDefaultTheme({
@ -27,7 +27,7 @@ export async function createPublicDotKeycloakifyDir() {
"dist", "dist",
"res", "res",
"public", "public",
WELL_KNOWN_DIRECTORY_BASE_NAME.DOT_KEYCLOAKIFY, WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES,
themeType themeType
); );

View File

@ -3,7 +3,7 @@ import * as fs from "fs";
import { join } from "path"; import { join } from "path";
import { assert } from "tsafe/assert"; import { assert } from "tsafe/assert";
import { transformCodebase } from "../../src/bin/tools/transformCodebase"; import { transformCodebase } from "../../src/bin/tools/transformCodebase";
import { createPublicDotKeycloakifyDir } from "./createPublicDotKeycloakifyDir"; import { createPublicKeycloakifyDevResourcesDir } from "./createPublicKeycloakifyDevResourcesDir";
import { createAccountV1Dir } from "./createAccountV1Dir"; import { createAccountV1Dir } from "./createAccountV1Dir";
import chalk from "chalk"; import chalk from "chalk";
@ -144,7 +144,7 @@ import chalk from "chalk";
fs.cpSync(dirBasename, destDirPath, { recursive: true }); fs.cpSync(dirBasename, destDirPath, { recursive: true });
} }
await createPublicDotKeycloakifyDir(); await createPublicKeycloakifyDevResourcesDir();
await createAccountV1Dir(); await createAccountV1Dir();
transformCodebase({ transformCodebase({

View File

@ -6,7 +6,7 @@ import { BASE_URL } from "keycloakify/lib/BASE_URL";
import { assert, type Equals } from "tsafe/assert"; import { assert, type Equals } from "tsafe/assert";
import type { LanguageTag } from "keycloakify/account/i18n/messages_defaultSet/types"; import type { LanguageTag } from "keycloakify/account/i18n/messages_defaultSet/types";
const resourcesPath = `${BASE_URL}${WELL_KNOWN_DIRECTORY_BASE_NAME.DOT_KEYCLOAKIFY}/account`; const resourcesPath = `${BASE_URL}${WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES}/account`;
export const kcContextCommonMock: KcContext.Common = { export const kcContextCommonMock: KcContext.Common = {
themeVersion: "0.0.0", themeVersion: "0.0.0",

View File

@ -85,6 +85,19 @@ attributes_to_attributesByName: {
}); });
} }
window.kcContext = kcContext; window.kcContext = kcContext;
<#if xKeycloakify.themeType == "login" >
const script = document.createElement("script");
script.type = "importmap";
script.textContent = JSON.stringify({
imports: {
"rfc4648": kcContext.url.resourcesCommonPath + "/node_modules/rfc4648/lib/rfc4648.js"
}
}, null, 2);
document.head.appendChild(script);
</#if>
function decodeHtmlEntities(htmlStr){ function decodeHtmlEntities(htmlStr){
var element = decodeHtmlEntities.element; var element = decodeHtmlEntities.element;
if (!element) { if (!element) {

View File

@ -112,7 +112,7 @@ export async function generateResourcesForMainTheme(params: {
{ {
const dirPath = pathJoin( const dirPath = pathJoin(
buildContext.projectBuildDirPath, buildContext.projectBuildDirPath,
WELL_KNOWN_DIRECTORY_BASE_NAME.DOT_KEYCLOAKIFY WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES
); );
if (fs.existsSync(dirPath)) { if (fs.existsSync(dirPath)) {
@ -120,7 +120,7 @@ export async function generateResourcesForMainTheme(params: {
throw new Error( throw new Error(
[ [
`Keycloakify build error: The ${WELL_KNOWN_DIRECTORY_BASE_NAME.DOT_KEYCLOAKIFY} directory shouldn't exist in your build directory.`, `Keycloakify build error: The ${WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES} directory shouldn't exist in your build directory.`,
`(${pathRelative(process.cwd(), dirPath)}).\n`, `(${pathRelative(process.cwd(), dirPath)}).\n`,
`Theses assets are only required for local development with Storybook.", `Theses assets are only required for local development with Storybook.",
"Please remove this directory as an additional step of your command.\n`, "Please remove this directory as an additional step of your command.\n`,
@ -266,7 +266,7 @@ export async function generateResourcesForMainTheme(params: {
getThisCodebaseRootDirPath(), getThisCodebaseRootDirPath(),
"res", "res",
"public", "public",
WELL_KNOWN_DIRECTORY_BASE_NAME.DOT_KEYCLOAKIFY, WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES,
themeType themeType
), ),
destDirPath: pathJoin(themeTypeDirPath, "resources") destDirPath: pathJoin(themeTypeDirPath, "resources")

View File

@ -1,5 +1,5 @@
export const WELL_KNOWN_DIRECTORY_BASE_NAME = { export const WELL_KNOWN_DIRECTORY_BASE_NAME = {
DOT_KEYCLOAKIFY: ".keycloakify", KEYCLOAKIFY_DEV_RESOURCES: "keycloakify-dev-resources",
RESOURCES_COMMON: "resources-common", RESOURCES_COMMON: "resources-common",
DIST: "dist" DIST: "dist"
} as const; } as const;

View File

@ -21,7 +21,7 @@ export function copyKeycloakResourcesToPublic(params: {
const destDirPath = pathJoin( const destDirPath = pathJoin(
buildContext.publicDirPath, buildContext.publicDirPath,
WELL_KNOWN_DIRECTORY_BASE_NAME.DOT_KEYCLOAKIFY WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES
); );
const keycloakifyBuildinfoFilePath = pathJoin(destDirPath, "keycloakify.buildinfo"); const keycloakifyBuildinfoFilePath = pathJoin(destDirPath, "keycloakify.buildinfo");
@ -57,6 +57,10 @@ export function copyKeycloakResourcesToPublic(params: {
force: true, force: true,
recursive: true recursive: true
}); });
rmSync(pathJoin(pathDirname(destDirPath), ".keycloakify"), {
force: true,
recursive: true
});
fs.mkdirSync(destDirPath, { recursive: true }); fs.mkdirSync(destDirPath, { recursive: true });
@ -67,7 +71,7 @@ export function copyKeycloakResourcesToPublic(params: {
getThisCodebaseRootDirPath(), getThisCodebaseRootDirPath(),
"res", "res",
"public", "public",
WELL_KNOWN_DIRECTORY_BASE_NAME.DOT_KEYCLOAKIFY WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES
), ),
destDirPath destDirPath
}); });

View File

@ -37,15 +37,17 @@ export type CliCommandOptions = CliCommandOptions_common & {
export async function command(params: { cliCommandOptions: CliCommandOptions }) { export async function command(params: { cliCommandOptions: CliCommandOptions }) {
exit_if_docker_not_installed: { exit_if_docker_not_installed: {
let commandOutput: Buffer | undefined = undefined; let commandOutput: string | undefined = undefined;
try { try {
commandOutput = child_process.execSync("docker --version", { commandOutput = child_process
.execSync("docker --version", {
stdio: ["ignore", "pipe", "ignore"] stdio: ["ignore", "pipe", "ignore"]
}); })
?.toString("utf8");
} catch {} } catch {}
if (commandOutput?.toString("utf8").includes("Docker")) { if (commandOutput?.includes("Docker") || commandOutput?.includes("podman")) {
break exit_if_docker_not_installed; break exit_if_docker_not_installed;
} }

View File

@ -76,7 +76,7 @@ const attributesByName = Object.fromEntries(
]).map(attribute => [attribute.name, attribute]) ]).map(attribute => [attribute.name, attribute])
); );
const resourcesPath = `${BASE_URL}${WELL_KNOWN_DIRECTORY_BASE_NAME.DOT_KEYCLOAKIFY}/login`; const resourcesPath = `${BASE_URL}${WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES}/login`;
export const kcContextCommonMock: KcContext.Common = { export const kcContextCommonMock: KcContext.Common = {
themeVersion: "0.0.0", themeVersion: "0.0.0",

View File

@ -40,14 +40,7 @@ export function useInitialize(params: {
const { insertScriptTags } = useInsertScriptTags({ const { insertScriptTags } = useInsertScriptTags({
componentOrHookName: "Template", componentOrHookName: "Template",
scriptTags: [ scriptTags: [
{ // NOTE: The importmap is added in by the FTL script because it's too late to add it here.
type: "importmap",
textContent: JSON.stringify({
imports: {
rfc4648: `${url.resourcesCommonPath}/node_modules/rfc4648/lib/rfc4648.js`
}
})
},
{ {
type: "module", type: "module",
src: `${url.resourcesPath}/js/menu-button-links.js` src: `${url.resourcesPath}/js/menu-button-links.js`

View File

@ -6,7 +6,7 @@ export type ScriptTag = ScriptTag.TextContent | ScriptTag.Src;
export namespace ScriptTag { export namespace ScriptTag {
type Common = { type Common = {
type: "text/javascript" | "module" | "importmap"; type: "text/javascript" | "module";
}; };
export type TextContent = Common & { export type TextContent = Common & {

View File

@ -201,7 +201,10 @@ export function keycloakify(params: keycloakify.Params) {
assert(buildDirPath !== undefined); assert(buildDirPath !== undefined);
await rm( await rm(
pathJoin(buildDirPath, WELL_KNOWN_DIRECTORY_BASE_NAME.DOT_KEYCLOAKIFY), pathJoin(
buildDirPath,
WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES
),
{ {
recursive: true, recursive: true,
force: true force: true