185 lines
5.6 KiB
TypeScript
Raw Normal View History

import cheerio from "cheerio";
2024-01-30 07:10:53 +01:00
import { replaceImportsInJsCode } from "../replacers/replaceImportsInJsCode";
import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode";
import * as fs from "fs";
import { join as pathJoin } from "path";
2024-06-09 09:15:16 +02:00
import type { BuildContext } from "../../shared/buildContext";
2022-08-16 14:41:06 +07:00
import { assert } from "tsafe/assert";
2024-05-20 15:48:51 +02:00
import {
type ThemeType,
basenameOfTheKeycloakifyResourcesDir,
2024-05-27 17:18:06 +02:00
resources_common,
nameOfTheLocalizationRealmOverridesUserProfileProperty
2024-05-20 15:48:51 +02:00
} from "../../shared/constants";
2024-05-19 04:21:35 +02:00
import { getThisCodebaseRootDirPath } from "../../tools/getThisCodebaseRootDirPath";
2024-06-09 09:15:16 +02:00
export type BuildContextLike = {
2024-01-30 07:10:53 +01:00
bundler: "vite" | "webpack";
2023-08-21 05:54:17 +02:00
themeVersion: string;
urlPathname: string | undefined;
projectBuildDirPath: string;
2024-01-30 07:10:53 +01:00
assetsDirPath: string;
2024-06-06 01:31:00 +02:00
kcContextExclusionsFtlCode: string | undefined;
2023-08-21 05:54:17 +02:00
};
2022-08-16 14:41:06 +07:00
2024-06-09 09:15:16 +02:00
assert<BuildContext extends BuildContextLike ? true : false>();
2022-08-16 14:41:06 +07:00
export function generateFtlFilesCodeFactory(params: {
themeName: string;
indexHtmlCode: string;
2024-06-09 09:15:16 +02:00
buildContext: BuildContextLike;
keycloakifyVersion: string;
2023-04-27 11:52:02 +02:00
themeType: ThemeType;
fieldNames: string[];
}) {
2024-05-20 15:48:51 +02:00
const {
themeName,
indexHtmlCode,
2024-06-09 09:15:16 +02:00
buildContext,
2024-05-20 15:48:51 +02:00
keycloakifyVersion,
themeType,
fieldNames
} = params;
const $ = cheerio.load(indexHtmlCode);
2022-08-16 14:41:06 +07:00
fix_imports_statements: {
$("script:not([src])").each((...[, element]) => {
2023-08-21 05:54:17 +02:00
const jsCode = $(element).html();
assert(jsCode !== null);
2024-05-20 15:48:51 +02:00
const { fixedJsCode } = replaceImportsInJsCode({
jsCode,
2024-06-09 09:15:16 +02:00
buildContext
2024-05-20 15:48:51 +02:00
});
2022-08-16 14:41:06 +07:00
$(element).text(fixedJsCode);
});
2022-08-16 14:41:06 +07:00
$("style").each((...[, element]) => {
2023-08-21 05:54:17 +02:00
const cssCode = $(element).html();
assert(cssCode !== null);
const { fixedCssCode } = replaceImportsInCssCode({
2023-08-21 05:54:17 +02:00
cssCode,
fileRelativeDirPath: ".",
2024-06-09 09:15:16 +02:00
buildContext
2022-08-16 14:41:06 +07:00
});
2022-08-16 14:41:06 +07:00
$(element).text(fixedCssCode);
});
(
[
["link", "href"],
["script", "src"]
2022-08-16 14:41:06 +07:00
] as const
).forEach(([selector, attrName]) =>
$(selector).each((...[, element]) => {
const href = $(element).attr(attrName);
if (href === undefined) {
return;
}
$(element).attr(
attrName,
2024-01-30 00:06:17 +01:00
href.replace(
2024-05-20 15:48:51 +02:00
new RegExp(
2024-06-09 09:15:16 +02:00
`^${(buildContext.urlPathname ?? "/").replace(/\//g, "\\/")}`
2024-05-20 15:48:51 +02:00
),
2024-01-30 00:06:17 +01:00
`\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/`
)
2022-08-16 14:41:06 +07:00
);
})
2022-08-16 14:41:06 +07:00
);
}
//FTL is no valid html, we can't insert with cheerio, we put placeholder for injecting later.
const kcContextDeclarationTemplateFtl = fs
2024-05-19 04:21:35 +02:00
.readFileSync(
2024-05-20 15:48:51 +02:00
pathJoin(
getThisCodebaseRootDirPath(),
"src",
"bin",
"keycloakify",
"generateFtl",
"kcContextDeclarationTemplate.ftl"
2024-05-20 15:48:51 +02:00
)
2024-05-19 04:21:35 +02:00
)
.toString("utf8")
2024-05-20 15:48:51 +02:00
.replace(
"FIELD_NAMES_eKsIY4ZsZ4xeM",
fieldNames.map(name => `"${name}"`).join(", ")
)
.replace("KEYCLOAKIFY_VERSION_xEdKd3xEdr", keycloakifyVersion)
2024-06-09 09:15:16 +02:00
.replace("KEYCLOAKIFY_THEME_VERSION_sIgKd3xEdr3dx", buildContext.themeVersion)
.replace("KEYCLOAKIFY_THEME_TYPE_dExKd3xEdr", themeType)
.replace("KEYCLOAKIFY_THEME_NAME_cXxKd3xEer", themeName)
2024-05-27 17:18:06 +02:00
.replace("RESOURCES_COMMON_cLsLsMrtDkpVv", resources_common)
.replace(
"lOCALIZATION_REALM_OVERRIDES_USER_PROFILE_PROPERTY_KEY_aaGLsPgGIdeeX",
nameOfTheLocalizationRealmOverridesUserProfileProperty
2024-06-06 01:31:00 +02:00
)
.replace(
"USER_DEFINED_EXCLUSIONS_eKsaY4ZsZ4eMr2",
2024-06-09 09:15:16 +02:00
buildContext.kcContextExclusionsFtlCode ?? ""
2024-05-27 17:18:06 +02:00
);
2024-05-20 15:48:51 +02:00
const ftlObjectToJsCodeDeclaringAnObjectPlaceholder =
'{ "x": "vIdLqMeOed9sdLdIdOxdK0d" }';
2024-05-20 15:48:51 +02:00
$("head").prepend(
`<script>\n${ftlObjectToJsCodeDeclaringAnObjectPlaceholder}\n</script>`
2024-05-20 15:48:51 +02:00
);
2023-11-19 03:27:40 +01:00
// Remove part of the document marked as ignored.
{
const startTags = $('meta[name="keycloakify-ignore-start"]');
startTags.each((...[, startTag]) => {
const $startTag = $(startTag);
2024-05-20 15:48:51 +02:00
const $endTag = $startTag
.nextAll('meta[name="keycloakify-ignore-end"]')
.first();
2023-11-19 03:27:40 +01:00
if ($endTag.length) {
let currentNode = $startTag.next();
while (currentNode.length && !currentNode.is($endTag)) {
currentNode.remove();
currentNode = $startTag.next();
}
$startTag.remove();
$endTag.remove();
}
});
}
const partiallyFixedIndexHtmlCode = $.html();
function generateFtlFilesCode(params: { pageId: string }): {
ftlCode: string;
} {
const { pageId } = params;
const $ = cheerio.load(partiallyFixedIndexHtmlCode);
let ftlCode = $.html();
Object.entries({
2024-05-20 15:48:51 +02:00
[ftlObjectToJsCodeDeclaringAnObjectPlaceholder]:
kcContextDeclarationTemplateFtl,
2024-05-20 15:48:51 +02:00
PAGE_ID_xIgLsPgGId9D8e: pageId
}).map(
([searchValue, replaceValue]) =>
(ftlCode = ftlCode.replace(searchValue, replaceValue))
);
return { ftlCode };
}
return { generateFtlFilesCode };
}