diff --git a/package.json b/package.json index e98d08fa..a30299f8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "keycloakify", - "version": "0.3.6", + "version": "0.3.7", "description": "Keycloak theme generator for Reacts app", "repository": { "type": "git", diff --git a/src/bin/build-keycloak-theme/generateFtl/index.ts b/src/bin/build-keycloak-theme/generateFtl/index.ts index 45543d73..b1a8c894 100644 --- a/src/bin/build-keycloak-theme/generateFtl/index.ts +++ b/src/bin/build-keycloak-theme/generateFtl/index.ts @@ -29,16 +29,25 @@ function loadFtlFile(ftlFileBasename: PageId | "template.ftl") { } } +export type Mode = { + type: "standalone"; + urlPathname: string; +} | { + type: "static fetched from app"; + urlPathname: string; + urlOrigin: string; +} + export function generateFtlFilesCodeFactory( params: { ftlValuesGlobalName: string; cssGlobalsToDefine: Record; indexHtmlCode: string; - urlPathname: string; + mode: Mode; } ) { - const { ftlValuesGlobalName, cssGlobalsToDefine, indexHtmlCode, urlPathname } = params; + const { ftlValuesGlobalName, cssGlobalsToDefine, indexHtmlCode, mode } = params; const $ = cheerio.load(indexHtmlCode); @@ -46,7 +55,8 @@ export function generateFtlFilesCodeFactory( const { fixedJsCode } = replaceImportFromStaticInJsCode({ ftlValuesGlobalName, - "jsCode": $(element).html()! + "jsCode": $(element).html()!, + mode }); $(element).text(fixedJsCode); @@ -65,13 +75,24 @@ export function generateFtlFilesCodeFactory( return; } - $(element).attr( - attrName, - href.replace( - new RegExp(`^${urlPathname.replace(/\//g, "\\/")}`), - "${url.resourcesPath}/build/" - ) - ); + switch (mode.type) { + case "static fetched from app": + $(element).attr( + attrName, + href.replace(/^\//, `${mode.urlOrigin}/`) + ); + break; + case "standalone": + $(element).attr( + attrName, + href.replace( + new RegExp(`^${mode.urlPathname.replace(/\//g, "\\/")}`), + "${url.resourcesPath}/build/" + ) + ); + break; + } + }) ); @@ -96,9 +117,9 @@ export function generateFtlFilesCodeFactory( ...(Object.keys(cssGlobalsToDefine).length === 0 ? [] : [ '', '', '' diff --git a/src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts b/src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts index b270bc4f..dbf1872c 100644 --- a/src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts +++ b/src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts @@ -6,24 +6,25 @@ import { replaceImportFromStaticInCssCode, replaceImportFromStaticInJsCode } from "./replaceImportFromStatic"; -import { generateFtlFilesCodeFactory, pageIds } from "./generateFtl"; -import { builtinThemesUrl } from "../install-builtin-keycloak-themes"; -import { downloadAndUnzip } from "../tools/downloadAndUnzip"; +import { generateFtlFilesCodeFactory, pageIds, Mode } from "./generateFtl"; +import { builtinThemesUrl } from "../install-builtin-keycloak-themes"; +import { downloadAndUnzip } from "../tools/downloadAndUnzip"; import * as child_process from "child_process"; -import { ftlValuesGlobalName } from "./ftlValuesGlobalName"; -import { resourcesCommonPath, resourcesPath, subDirOfPublicDirBasename } from "../../lib/kcContextMocks/urlResourcesPath"; -import { isInside } from "../tools/isInside"; +import { ftlValuesGlobalName } from "./ftlValuesGlobalName"; +import { resourcesCommonPath, resourcesPath, subDirOfPublicDirBasename } from "../../lib/kcContextMocks/urlResourcesPath"; +import { isInside } from "../tools/isInside"; + export function generateKeycloakThemeResources( params: { - urlPathname: string; themeName: string; reactAppBuildDirPath: string; keycloakThemeBuildingDirPath: string; + mode: Mode; } ) { - const { themeName, reactAppBuildDirPath, keycloakThemeBuildingDirPath, urlPathname } = params; + const { themeName, reactAppBuildDirPath, keycloakThemeBuildingDirPath, mode } = params; const themeDirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", themeName, "login"); @@ -44,30 +45,34 @@ export function generateKeycloakThemeResources( return undefined; } + if (mode.type === "standalone") { - if (/\.css?$/i.test(filePath)) { + if (/\.css?$/i.test(filePath)) { - const { cssGlobalsToDefine, fixedCssCode } = replaceImportFromStaticInCssCode( - { "cssCode": sourceCode.toString("utf8") } - ); + const { cssGlobalsToDefine, fixedCssCode } = replaceImportFromStaticInCssCode( + { "cssCode": sourceCode.toString("utf8") } + ); - allCssGlobalsToDefine = { - ...allCssGlobalsToDefine, - ...cssGlobalsToDefine - }; + allCssGlobalsToDefine = { + ...allCssGlobalsToDefine, + ...cssGlobalsToDefine + }; - return { "modifiedSourceCode": Buffer.from(fixedCssCode, "utf8") }; + return { "modifiedSourceCode": Buffer.from(fixedCssCode, "utf8") }; - } + } - if (/\.js?$/i.test(filePath)) { + if (/\.js?$/i.test(filePath)) { - const { fixedJsCode } = replaceImportFromStaticInJsCode({ - "jsCode": sourceCode.toString("utf8"), - ftlValuesGlobalName - }); + const { fixedJsCode } = replaceImportFromStaticInJsCode({ + "jsCode": sourceCode.toString("utf8"), + ftlValuesGlobalName, + mode + }); - return { "modifiedSourceCode": Buffer.from(fixedJsCode, "utf8") }; + return { "modifiedSourceCode": Buffer.from(fixedJsCode, "utf8") }; + + } } @@ -82,7 +87,7 @@ export function generateKeycloakThemeResources( "indexHtmlCode": fs.readFileSync( pathJoin(reactAppBuildDirPath, "index.html") ).toString("utf8"), - urlPathname + mode }); pageIds.forEach(pageId => { diff --git a/src/bin/build-keycloak-theme/index.ts b/src/bin/build-keycloak-theme/index.ts index 390b567b..64a5c73e 100644 --- a/src/bin/build-keycloak-theme/index.ts +++ b/src/bin/build-keycloak-theme/index.ts @@ -6,11 +6,13 @@ import type { ParsedPackageJson } from "./generateJavaStackFiles"; import { join as pathJoin, relative as pathRelative, basename as pathBasename } from "path"; import * as child_process from "child_process"; import { generateDebugFiles, containerLaunchScriptBasename } from "./generateDebugFiles"; -import { URL } from "url"; +import { URL } from "url"; const reactProjectDirPath = process.cwd(); +const isStandalone = process.argv[2]?.toLowerCase() === "--standalone"; + const parsedPackageJson: ParsedPackageJson = require(pathJoin(reactProjectDirPath, "package.json")); export const keycloakThemeBuildingDirPath = pathJoin(reactProjectDirPath, "build_keycloak"); @@ -24,15 +26,50 @@ if (require.main === module) { keycloakThemeBuildingDirPath, "reactAppBuildDirPath": pathJoin(reactProjectDirPath, "build"), "themeName": parsedPackageJson.name, - "urlPathname": (()=>{ + "mode": (() => { - const { homepage } = parsedPackageJson; - return homepage === undefined ? - "/" : - new URL(homepage).pathname.replace(/([^/])$/, "$1/"); + const url = (() => { + + const { homepage } = parsedPackageJson; + + return homepage === undefined ? + undefined : + new URL(homepage); + + })(); + + const urlPathname = + url === undefined ? + "/" : + url.pathname.replace(/([^/])$/, "$1/"); + + + + return isStandalone ? + { + "type": "standalone", + urlPathname + } as const + : + { + "type": "static fetched from app", + urlPathname, + "urlOrigin": (() => { + + if (url === undefined) { + console.error("ERROR: You must specify 'homepage' in your package.json"); + process.exit(-1); + } + + return url.origin; + + })() + + } as const; })() + }); const { jarFilePath } = generateJavaStackFiles({ diff --git a/src/bin/build-keycloak-theme/replaceImportFromStatic.ts b/src/bin/build-keycloak-theme/replaceImportFromStatic.ts index b38194ae..f6488fbf 100644 --- a/src/bin/build-keycloak-theme/replaceImportFromStatic.ts +++ b/src/bin/build-keycloak-theme/replaceImportFromStatic.ts @@ -1,19 +1,39 @@ import * as crypto from "crypto"; +type Mode = { + type: "standalone"; +} | { + type: "static fetched from app"; + urlOrigin: string; + urlPathname: string; +} + export function replaceImportFromStaticInJsCode( params: { ftlValuesGlobalName: string; jsCode: string; + mode: Mode; } ): { fixedJsCode: string; } { - const { jsCode, ftlValuesGlobalName } = params; + const { jsCode, ftlValuesGlobalName, mode } = params; + + const fixedJsCode = (() => { + switch (mode.type) { + case "standalone": + return jsCode!.replace( + /[a-z]+\.[a-z]+\+"static\//g, + `window.${ftlValuesGlobalName}.url.resourcesPath + "/build/static/` + ); + case "static fetched from app": + return jsCode!.replace( + /[a-z]+\.[a-z]+\+"static\//g, + `"${mode.urlOrigin}${mode.urlPathname}static/` + ); + } + })(); - const fixedJsCode = jsCode!.replace( - /[a-z]+\.[a-z]+\+"static\//g, - `window.${ftlValuesGlobalName}.url.resourcesPath + "/build/static/` - ); return { fixedJsCode }; @@ -60,7 +80,7 @@ export function replaceImportFromStaticInCssCode( export function generateCssCodeToDefineGlobals( params: { cssGlobalsToDefine: Record; - urlPathname: string; + urlPathname: string; } ): { cssCodeToPrependInHead: string; @@ -75,7 +95,7 @@ export function generateCssCodeToDefineGlobals( .map(cssVariableName => [ `--${cssVariableName}:`, cssGlobalsToDefine[cssVariableName] - .replace(new RegExp(`url\\(${urlPathname.replace(/\//g,"\\/")}`, "g"),"url(${url.resourcesPath}/build/") + .replace(new RegExp(`url\\(${urlPathname.replace(/\//g, "\\/")}`, "g"), "url(${url.resourcesPath}/build/") ].join(" ")) .map(line => ` ${line};`), "}" diff --git a/src/test/generateKeycloakThemeResources.ts b/src/test/generateKeycloakThemeResources.ts index b2caed85..d7587b47 100644 --- a/src/test/generateKeycloakThemeResources.ts +++ b/src/test/generateKeycloakThemeResources.ts @@ -1,7 +1,7 @@ import { join as pathJoin } from "path"; import { generateKeycloakThemeResources } from "../bin/build-keycloak-theme/generateKeycloakThemeResources"; -import { +import { setupSampleReactProject, sampleReactProjectDirPath } from "./setupSampleReactProject"; @@ -12,6 +12,9 @@ generateKeycloakThemeResources({ "themeName": "keycloakify-demo-app", "reactAppBuildDirPath": pathJoin(sampleReactProjectDirPath, "build"), "keycloakThemeBuildingDirPath": pathJoin(sampleReactProjectDirPath, "build_keycloak_theme"), - "urlPathname": "/keycloakify-demo-app/" + "mode": { + "type": "standalone", + "urlPathname": "/keycloakify-demo-app/" + } }); diff --git a/src/test/replaceImportFromStatic.ts b/src/test/replaceImportFromStatic.ts index 396d75d1..5121b3ac 100644 --- a/src/test/replaceImportFromStatic.ts +++ b/src/test/replaceImportFromStatic.ts @@ -19,7 +19,8 @@ const { fixedJsCode } = replaceImportFromStaticInJsCode({ 3: "0664cdc0" }[e] + ".chunk.js" } - ` + `, + "mode": { "type": "standalone" } }); console.log({ fixedJsCode });