Load scripts after component rendered #470

This commit is contained in:
Joseph Garrone 2024-05-07 20:04:27 +02:00
parent b61f442a15
commit a887844a37
4 changed files with 44 additions and 34 deletions

View File

@ -4,7 +4,6 @@ import { generateCssCodeToDefineGlobals } from "../replacers/replaceImportsInCss
import { replaceImportsInInlineCssCode } from "../replacers/replaceImportsInInlineCssCode"; import { replaceImportsInInlineCssCode } from "../replacers/replaceImportsInInlineCssCode";
import * as fs from "fs"; import * as fs from "fs";
import { join as pathJoin } from "path"; import { join as pathJoin } from "path";
import { objectKeys } from "tsafe/objectKeys";
import type { BuildOptions } from "../buildOptions"; import type { BuildOptions } from "../buildOptions";
import { assert } from "tsafe/assert"; import { assert } from "tsafe/assert";
import { type ThemeType, nameOfTheGlobal, basenameOfTheKeycloakifyResourcesDir, resources_common } from "../../constants"; import { type ThemeType, nameOfTheGlobal, basenameOfTheKeycloakifyResourcesDir, resources_common } from "../../constants";
@ -96,35 +95,20 @@ export function generateFtlFilesCodeFactory(params: {
} }
//FTL is no valid html, we can't insert with cheerio, we put placeholder for injecting later. //FTL is no valid html, we can't insert with cheerio, we put placeholder for injecting later.
const replaceValueBySearchValue = { const ftlObjectToJsCodeDeclaringAnObject = fs
'{ "x": "vIdLqMeOed9sdLdIdOxdK0d" }': fs .readFileSync(pathJoin(__dirname, "ftl_object_to_js_code_declaring_an_object.ftl"))
.readFileSync(pathJoin(__dirname, "ftl_object_to_js_code_declaring_an_object.ftl")) .toString("utf8")
.toString("utf8") .match(/^<script>const _=((?:.|\n)+)<\/script>[\n]?$/)![1]
.match(/^<script>const _=((?:.|\n)+)<\/script>[\n]?$/)![1] .replace("FIELD_NAMES_eKsIY4ZsZ4xeM", fieldNames.map(name => `"${name}"`).join(", "))
.replace("FIELD_NAMES_eKsIY4ZsZ4xeM", fieldNames.map(name => `"${name}"`).join(", ")) .replace("KEYCLOAKIFY_VERSION_xEdKd3xEdr", keycloakifyVersion)
.replace("KEYCLOAKIFY_VERSION_xEdKd3xEdr", keycloakifyVersion) .replace("KEYCLOAKIFY_THEME_VERSION_sIgKd3xEdr3dx", buildOptions.themeVersion)
.replace("KEYCLOAKIFY_THEME_VERSION_sIgKd3xEdr3dx", buildOptions.themeVersion) .replace("KEYCLOAKIFY_THEME_TYPE_dExKd3xEdr", themeType)
.replace("KEYCLOAKIFY_THEME_TYPE_dExKd3xEdr", themeType) .replace("KEYCLOAKIFY_THEME_NAME_cXxKd3xEer", themeName)
.replace("KEYCLOAKIFY_THEME_NAME_cXxKd3xEer", themeName) .replace("RESOURCES_COMMON_cLsLsMrtDkpVv", resources_common);
.replace("RESOURCES_COMMON_cLsLsMrtDkpVv", resources_common),
"<!-- xIdLqMeOedErIdLsPdNdI9dSlxI -->": [
"<#if scripts??>",
" <#list scripts as script>",
' <script src="${script}" type="text/javascript"></script>',
" </#list>",
"</#if>"
].join("\n")
};
$("head").prepend( const ftlObjectToJsCodeDeclaringAnObjectPlaceholder = '{ "x": "vIdLqMeOed9sdLdIdOxdK0d" }';
[
"<script>", $("head").prepend(["<script>", ` window.${nameOfTheGlobal}= ${ftlObjectToJsCodeDeclaringAnObjectPlaceholder};`, "</script>"].join("\n"));
` window.${nameOfTheGlobal}= ${objectKeys(replaceValueBySearchValue)[0]};`,
"</script>",
"",
objectKeys(replaceValueBySearchValue)[1]
].join("\n")
);
// Remove part of the document marked as ignored. // Remove part of the document marked as ignored.
{ {
@ -159,7 +143,7 @@ export function generateFtlFilesCodeFactory(params: {
let ftlCode = $.html(); let ftlCode = $.html();
Object.entries({ Object.entries({
...replaceValueBySearchValue, [ftlObjectToJsCodeDeclaringAnObjectPlaceholder]: ftlObjectToJsCodeDeclaringAnObject,
"PAGE_ID_xIgLsPgGId9D8e": pageId "PAGE_ID_xIgLsPgGId9D8e": pageId
}).map(([searchValue, replaceValue]) => (ftlCode = ftlCode.replace(searchValue, replaceValue))); }).map(([searchValue, replaceValue]) => (ftlCode = ftlCode.replace(searchValue, replaceValue)));

View File

@ -70,6 +70,21 @@ export function usePrepareTemplate(params: {
setReady(); setReady();
})(); })();
return () => {
isUnmounted = true;
removeArray.forEach(remove => remove());
};
}, []);
useEffect(() => {
if (!isReady) {
return;
}
let isUnmounted = false;
const removeArray: (() => void)[] = [];
scripts.forEach(script => { scripts.forEach(script => {
const { remove } = headInsert({ const { remove } = headInsert({
"type": "javascript", "type": "javascript",
@ -83,7 +98,7 @@ export function usePrepareTemplate(params: {
isUnmounted = true; isUnmounted = true;
removeArray.forEach(remove => remove()); removeArray.forEach(remove => remove());
}; };
}, []); }, [isReady]);
useSetClassName({ useSetClassName({
"target": "html", "target": "html",

View File

@ -26,7 +26,7 @@ export default function Template(props: TemplateProps<KcContext, I18n>) {
const { msg, msgStr, changeLocale, labelBySupportedLanguageTag, currentLanguageTag } = i18n; const { msg, msgStr, changeLocale, labelBySupportedLanguageTag, currentLanguageTag } = i18n;
const { realm, locale, auth, url, message, isAppInitiatedAction, authenticationSession } = kcContext; const { realm, locale, auth, url, message, isAppInitiatedAction, authenticationSession, scripts } = kcContext;
const { isReady } = usePrepareTemplate({ const { isReady } = usePrepareTemplate({
"styles": !doUseDefaultCss "styles": !doUseDefaultCss
@ -64,7 +64,17 @@ export default function Template(props: TemplateProps<KcContext, I18n>) {
].join("\n") ].join("\n")
} }
} }
]) ]),
...scripts.map(
script =>
({
"isModule": false,
"source": {
"type": "url",
"src": script
}
} as const)
)
], ],
"htmlClassName": getClassName("kcHtmlClass"), "htmlClassName": getClassName("kcHtmlClass"),
"bodyClassName": getClassName("kcBodyClass"), "bodyClassName": getClassName("kcBodyClass"),

View File

@ -421,7 +421,8 @@ export const kcContextMocks = [
"context": "REGISTRATION_PROFILE" as const, "context": "REGISTRATION_PROFILE" as const,
attributes, attributes,
attributesByName attributesByName
} },
"scripts": [...registerCommon.scripts, "https://www.google.com/recaptcha/api.js"]
}) })
]; ];
})(), })(),