Compare commits

..

13 Commits

16 changed files with 402 additions and 53 deletions

View File

@ -1,3 +1,16 @@
### **0.0.19** (2021-02-27)
- update
- update
### **0.0.18** (2021-02-23)
- Bump version number
- Moving on with implementation of the lib
- Update readme
- Readme eddit
- Fixing video link
### **0.0.16** (2021-02-23) ### **0.0.16** (2021-02-23)
- Bump version - Bump version

View File

@ -18,7 +18,7 @@ The problem:
![keycloak_before](https://user-images.githubusercontent.com/6702424/108838381-dbbbcf80-75d3-11eb-8ae8-db41563ef9db.gif) ![keycloak_before](https://user-images.githubusercontent.com/6702424/108838381-dbbbcf80-75d3-11eb-8ae8-db41563ef9db.gif)
When we redirected to Keycloak the user suffers from a harsh context switch. When we redirected to Keycloak the user suffers from a harsh context switch.
The language is set back to default and the theme is different. On je login/register pages the language is set back to default and the theme is different that the one on the app.
Keycloak does offer a way to customize theses pages but it requires a lot of raw HTML/CSS hacking Keycloak does offer a way to customize theses pages but it requires a lot of raw HTML/CSS hacking
to reproduce the look and feel of a specific app. Not mentioning the maintenance cost of such an endeavour. to reproduce the look and feel of a specific app. Not mentioning the maintenance cost of such an endeavour.
@ -28,9 +28,7 @@ still letting Keycloak handle the heavy lifting of actually authenticating the u
Here is `yarn add keycloak-react-theming` for you 🍸 Here is `yarn add keycloak-react-theming` for you 🍸
![image](https://user-images.githubusercontent.com/6702424/108833938-c9d72e00-75cd-11eb-8263-4334ca79275c.png) TODO: Insert video after.
![image](https://user-images.githubusercontent.com/6702424/108834054-f68b4580-75cd-11eb-9661-b1a43836c4b0.png)
![image](https://user-images.githubusercontent.com/6702424/108834220-32bea600-75ce-11eb-9e11-7661188beb7c.png)
# How to use # How to use
@ -44,18 +42,18 @@ Typically you will get:
`package.json`: `package.json`:
```json ```json
"devDependencies": { "devDependencies": {
"keycloak-react-theming": "^0.0.10", "keycloak-react-theming": "^0.0.10"
[...]
}, },
"scripts": { "scripts": {
"build": "react-scripts build && build-keycloak-theme", "build": "react-scripts build && build-keycloak-theme"
[...]
}, },
``` ```
Then build your app with `yarn run build` or `npm run build`, you will be provided with instructions Then build your app with `yarn run build` or `npm run build`, you will be provided with instructions
about how to load the theme into Keycloak. about how to load the theme into Keycloak.
[![kickstart_video](https://user-images.githubusercontent.com/6702424/108877866-f146ee80-75ff-11eb-8120-003b3c5f6dd8.png)](https://youtu.be/xTz0Rj7i2v8)
## Developing your login and register pages in your React app ## Developing your login and register pages in your React app
TODO TODO

View File

@ -1 +0,0 @@
{"version":3,"file":"generateFtl.js","sourceRoot":"","sources":["../../src/bin/build-keycloak-theme/generateFtl.ts"],"names":[],"mappings":"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"}

View File

@ -0,0 +1,113 @@
<script>const _=
{
"url": {
"loginAction": "${url.loginAction}",
"resourcesPath": "${url.resourcesPath}",
"resourcesCommonPath": "${url.resourcesCommonPath}",
"loginRestartFlowUrl": "${url.loginRestartFlowUrl}"
},
"realm": {
"displayName": "${realm.displayName!''}" || undefined,
"displayNameHtml": "${realm.displayNameHtml!''}" || undefined,
"internationalizationEnabled": ${realm.internationalizationEnabled?c}
},
"locale": (function (){
<#if realm.internationalizationEnabled>
return {
"supported": (function(){
<#if realm.internationalizationEnabled>
var out= [];
<#list locale.supported as lng>
out.push({
"url": "${lng.url}",
"label": "${lng.label}",
"languageTag": "${lng.languageTag}"
});
</#list>
return out;
</#if>
return undefined;
})(),
"current": "${locale.current}"
};
</#if>
return undefined;
})(),
"auth": (function (){
<#if auth?has_content>
var out= {
"showUsername": ${auth.showUsername()?c},
"showResetCredentials": ${auth.showResetCredentials()?c},
"showTryAnotherWayLink": ${auth.showTryAnotherWayLink()?c}
};
<#if auth.showUsername() && !auth.showResetCredentials()>
Object.assign(
out,
{
"attemptedUsername": "${auth.attemptedUsername}"
}
);
</#if>
return out;
</#if>
return undefined;
})(),
"scripts": (function(){
var out = [];
<#if scripts??>
<#list scripts as script>
out.push("${script}");
</#list>
</#if>
return out;
})(),
"message": (function (){
<#if message?has_content>
return { 
"type": "${message.type}",
"summary": "${kcSanitize(message.summary)?no_esc}"
};
</#if>
return undefined;
})(),
"isAppInitiatedAction": (function (){
<#if isAppInitiatedAction??>
return true;
</#if>
return false;
})()
}
</script>

View File

@ -25,7 +25,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.generateFtlFilesCodeFactory = void 0; exports.generateFtlFilesCodeFactory = void 0;
var cheerio_1 = __importDefault(require("cheerio")); var cheerio_1 = __importDefault(require("cheerio"));
var replaceImportFromStatic_1 = require("./replaceImportFromStatic"); var replaceImportFromStatic_1 = require("../replaceImportFromStatic");
var fs_1 = __importDefault(require("fs"));
var path_1 = require("path");
var objectKeys_1 = require("evt/tools/typeSafety/objectKeys");
function generateFtlFilesCodeFactory(params) { function generateFtlFilesCodeFactory(params) {
var ftlValuesGlobalName = params.ftlValuesGlobalName, cssGlobalsToDefine = params.cssGlobalsToDefine, indexHtmlCode = params.indexHtmlCode; var ftlValuesGlobalName = params.ftlValuesGlobalName, cssGlobalsToDefine = params.cssGlobalsToDefine, indexHtmlCode = params.indexHtmlCode;
var $ = cheerio_1.default.load(indexHtmlCode); var $ = cheerio_1.default.load(indexHtmlCode);
@ -59,6 +62,19 @@ function generateFtlFilesCodeFactory(params) {
$(element).attr(attrName, "${url.resourcesPath}" + href); $(element).attr(attrName, "${url.resourcesPath}" + href);
}); });
}); });
//FTL is no valid html, we can't insert with cheerio, we put placeholder for injecting later.
var ftlPlaceholders = {
'{ "x": "xIdLqMeOed9sdLdIdOxdK0d" }': fs_1.default.readFileSync(path_1.join(__dirname, "ftl2js.ftl"))
.toString("utf8")
.match(/^<script>const _=((?:.|\n)+)<\/script>[\n]?$/)[1],
'<!-- xIdLqMeOedErIdLsPdNdI9dSlxI -->': [
'<#if scripts??>',
' <#list scripts as script>',
' <script src="${script}" type="text/javascript"></script>',
' </#list>',
'</#if>',
].join("\n")
};
$("head").prepend(__spread((Object.keys(cssGlobalsToDefine).length === 0 ? [] : [ $("head").prepend(__spread((Object.keys(cssGlobalsToDefine).length === 0 ? [] : [
'', '',
'<style>', '<style>',
@ -69,14 +85,11 @@ function generateFtlFilesCodeFactory(params) {
'<script>', '<script>',
' Object.assign(', ' Object.assign(',
" window." + ftlValuesGlobalName + ",", " window." + ftlValuesGlobalName + ",",
' {', " " + objectKeys_1.objectKeys(ftlPlaceholders)[0],
' "url": {',
' "loginAction": "${url.loginAction}",',
' "resourcesPath": "${url.resourcesPath}"',
' }',
' }',
' );', ' );',
'</script>', '</script>',
'',
objectKeys_1.objectKeys(ftlPlaceholders)[1],
'' ''
]).join("\n")); ]).join("\n"));
var partiallyFixedIndexHtmlCode = $.html(); var partiallyFixedIndexHtmlCode = $.html();
@ -90,9 +103,12 @@ function generateFtlFilesCodeFactory(params) {
'</script>', '</script>',
'' ''
].join("\n")); ].join("\n"));
return { "ftlCode": $.html() }; var ftlCode = $.html();
objectKeys_1.objectKeys(ftlPlaceholders)
.forEach(function (id) { return ftlCode = ftlCode.replace(id, ftlPlaceholders[id]); });
return { ftlCode: ftlCode };
} }
return { generateFtlFilesCode: generateFtlFilesCode }; return { generateFtlFilesCode: generateFtlFilesCode };
} }
exports.generateFtlFilesCodeFactory = generateFtlFilesCodeFactory; exports.generateFtlFilesCodeFactory = generateFtlFilesCodeFactory;
//# sourceMappingURL=generateFtl.js.map //# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/bin/build-keycloak-theme/generateFtl/index.ts"],"names":[],"mappings":"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"}

View File

@ -1,9 +1,38 @@
import type { generateFtlFilesCodeFactory } from "../bin/build-keycloak-theme/generateFtl"; import type { generateFtlFilesCodeFactory } from "../bin/build-keycloak-theme/generateFtl";
export declare type LanguageLabel = "Deutsch" | "Norsk" | "Русский" | "Svenska" | "Português (Brasil)" | "Lietuvių" | "English" | "Italiano" | "Français" | "中文简体" | "Español" | "Čeština" | "日本語" | "Slovenčina" | "Polish" | "Català" | "Nederlands" | "tr";
export declare type LanguageTag = "de" | "no" | "ru" | "sv" | "pt-BR" | "lt" | "en" | "it" | "fr" | "zh-CN" | "es" | "cs" | "ja" | "sk" | "pl" | "ca" | "nl" | "tr";
export declare type KeycloakFtlValues = { export declare type KeycloakFtlValues = {
pageBasename: Parameters<ReturnType<typeof generateFtlFilesCodeFactory>["generateFtlFilesCode"]>[0]["pageBasename"]; pageBasename: Parameters<ReturnType<typeof generateFtlFilesCodeFactory>["generateFtlFilesCode"]>[0]["pageBasename"];
url: { url: {
loginAction: string; loginAction: string;
resourcesPath: string; resourcesPath: string;
resourcesCommonPath: string;
loginRestartFlowUrl: string;
}; };
realm: {
displayName?: string;
displayNameHtml?: string;
internationalizationEnabled: boolean;
};
locale?: {
supported: {
url: string;
label: LanguageLabel;
languageTag: LanguageTag;
};
current: LanguageLabel;
};
auth?: {
showUsername: boolean;
showResetCredentials: boolean;
showTryAnotherWayLink: boolean;
attemptedUsername?: boolean;
};
scripts: string[];
message?: {
type: "success" | "warning" | "error" | "info";
summary: string;
};
isAppInitiatedAction: boolean;
}; };
export declare const keycloakPagesContext: KeycloakFtlValues | undefined; export declare const keycloakPagesContext: KeycloakFtlValues | undefined;

View File

@ -1 +1 @@
{"version":3,"file":"keycloakFtlValues.js","sourceRoot":"","sources":["../src/lib/keycloakFtlValues.ts"],"names":[],"mappings":";;;;AAGA,6GAAiG;AAEjG,8CAA6C;AAW9B,QAAA,oBAAoB,aAC7B,GAAC,oDAAmB,IAAG,OAAE,CAAiC,MAAc,CAAC,oDAAmB,CAAC,CAAC,2BAAG;AACvG,CAAC"} {"version":3,"file":"keycloakFtlValues.js","sourceRoot":"","sources":["../src/lib/keycloakFtlValues.ts"],"names":[],"mappings":";;;;AAGA,6GAAiG;AAEjG,8CAA6C;AA+C9B,QAAA,oBAAoB,aAC7B,GAAC,oDAAmB,IAAG,OAAE,CAAiC,MAAc,CAAC,oDAAmB,CAAC,CAAC,2BAAG;AACvG,CAAC"}

4
package-lock.json generated
View File

@ -1,11 +1,11 @@
{ {
"name": "keycloak-react-theming", "name": "keycloak-react-theming",
"version": "0.0.16", "version": "0.0.19",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"version": "0.0.16", "version": "0.0.19",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"cheerio": "^1.0.0-rc.5", "cheerio": "^1.0.0-rc.5",

View File

@ -1,6 +1,6 @@
{ {
"name": "keycloak-react-theming", "name": "keycloak-react-theming",
"version": "0.0.16", "version": "0.0.19",
"description": "Keycloak theme generator for Reacts app", "description": "Keycloak theme generator for Reacts app",
"repository": { "repository": {
"type": "git", "type": "git",
@ -17,7 +17,8 @@
"files": [ "files": [
"src/bin/build-keycloak-theme/generateDebugFiles/index.ts", "src/bin/build-keycloak-theme/generateDebugFiles/index.ts",
"src/bin/build-keycloak-theme/generateDebugFiles/standalone-ha.xml", "src/bin/build-keycloak-theme/generateDebugFiles/standalone-ha.xml",
"src/bin/build-keycloak-theme/generateFtl.ts", "src/bin/build-keycloak-theme/generateFtl/ftl2js.ftl",
"src/bin/build-keycloak-theme/generateFtl/index.ts",
"src/bin/build-keycloak-theme/generateJavaStackFiles.ts", "src/bin/build-keycloak-theme/generateJavaStackFiles.ts",
"src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts", "src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts",
"src/bin/build-keycloak-theme/index.ts", "src/bin/build-keycloak-theme/index.ts",
@ -31,9 +32,10 @@
"bin/build-keycloak-theme/generateDebugFiles/index.js", "bin/build-keycloak-theme/generateDebugFiles/index.js",
"bin/build-keycloak-theme/generateDebugFiles/index.js.map", "bin/build-keycloak-theme/generateDebugFiles/index.js.map",
"bin/build-keycloak-theme/generateDebugFiles/standalone-ha.xml", "bin/build-keycloak-theme/generateDebugFiles/standalone-ha.xml",
"bin/build-keycloak-theme/generateFtl.d.ts", "bin/build-keycloak-theme/generateFtl/ftl2js.ftl",
"bin/build-keycloak-theme/generateFtl.js", "bin/build-keycloak-theme/generateFtl/index.d.ts",
"bin/build-keycloak-theme/generateFtl.js.map", "bin/build-keycloak-theme/generateFtl/index.js",
"bin/build-keycloak-theme/generateFtl/index.js.map",
"bin/build-keycloak-theme/generateJavaStackFiles.d.ts", "bin/build-keycloak-theme/generateJavaStackFiles.d.ts",
"bin/build-keycloak-theme/generateJavaStackFiles.js", "bin/build-keycloak-theme/generateJavaStackFiles.js",
"bin/build-keycloak-theme/generateJavaStackFiles.js.map", "bin/build-keycloak-theme/generateJavaStackFiles.js.map",
@ -60,7 +62,8 @@
"tools/crawl.js.map", "tools/crawl.js.map",
"tools/transformCodebase.d.ts", "tools/transformCodebase.d.ts",
"tools/transformCodebase.js", "tools/transformCodebase.js",
"tools/transformCodebase.js.map" "tools/transformCodebase.js.map",
"res/test.txt"
], ],
"keywords": [ "keywords": [
"keycloak", "keycloak",
@ -71,7 +74,7 @@
"devDependencies": { "devDependencies": {
"@types/node": "^10.0.0", "@types/node": "^10.0.0",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",
"denoify": "^0.6.4", "denoify": "^0.6.5",
"scripting-tools": "^0.19.13", "scripting-tools": "^0.19.13",
"typescript": "^4.1.5" "typescript": "^4.1.5"
}, },

0
res/test.txt Normal file
View File

View File

@ -0,0 +1,113 @@
<script>const _=
{
"url": {
"loginAction": "${url.loginAction}",
"resourcesPath": "${url.resourcesPath}",
"resourcesCommonPath": "${url.resourcesCommonPath}",
"loginRestartFlowUrl": "${url.loginRestartFlowUrl}"
},
"realm": {
"displayName": "${realm.displayName!''}" || undefined,
"displayNameHtml": "${realm.displayNameHtml!''}" || undefined,
"internationalizationEnabled": ${realm.internationalizationEnabled?c}
},
"locale": (function (){
<#if realm.internationalizationEnabled>
return {
"supported": (function(){
<#if realm.internationalizationEnabled>
var out= [];
<#list locale.supported as lng>
out.push({
"url": "${lng.url}",
"label": "${lng.label}",
"languageTag": "${lng.languageTag}"
});
</#list>
return out;
</#if>
return undefined;
})(),
"current": "${locale.current}"
};
</#if>
return undefined;
})(),
"auth": (function (){
<#if auth?has_content>
var out= {
"showUsername": ${auth.showUsername()?c},
"showResetCredentials": ${auth.showResetCredentials()?c},
"showTryAnotherWayLink": ${auth.showTryAnotherWayLink()?c}
};
<#if auth.showUsername() && !auth.showResetCredentials()>
Object.assign(
out,
{
"attemptedUsername": "${auth.attemptedUsername}"
}
);
</#if>
return out;
</#if>
return undefined;
})(),
"scripts": (function(){
var out = [];
<#if scripts??>
<#list scripts as script>
out.push("${script}");
</#list>
</#if>
return out;
})(),
"message": (function (){
<#if message?has_content>
return { 
"type": "${message.type}",
"summary": "${kcSanitize(message.summary)?no_esc}"
};
</#if>
return undefined;
})(),
"isAppInitiatedAction": (function (){
<#if isAppInitiatedAction??>
return true;
</#if>
return false;
})()
}
</script>

View File

@ -4,7 +4,10 @@ import cheerio from "cheerio";
import { import {
replaceImportFromStaticInJsCode, replaceImportFromStaticInJsCode,
generateCssCodeToDefineGlobals generateCssCodeToDefineGlobals
} from "./replaceImportFromStatic"; } from "../replaceImportFromStatic";
import fs from "fs";
import { join as pathJoin } from "path";
import { objectKeys } from "evt/tools/typeSafety/objectKeys";
export function generateFtlFilesCodeFactory( export function generateFtlFilesCodeFactory(
params: { params: {
@ -47,6 +50,22 @@ export function generateFtlFilesCodeFactory(
}) })
); );
//FTL is no valid html, we can't insert with cheerio, we put placeholder for injecting later.
const ftlPlaceholders = {
'{ "x": "xIdLqMeOed9sdLdIdOxdK0d" }':
fs.readFileSync(pathJoin(__dirname, "ftl2js.ftl"))
.toString("utf8")
.match(/^<script>const _=((?:.|\n)+)<\/script>[\n]?$/)![1],
'<!-- xIdLqMeOedErIdLsPdNdI9dSlxI -->':
[
'<#if scripts??>',
' <#list scripts as script>',
' <script src="${script}" type="text/javascript"></script>',
' </#list>',
'</#if>',
].join("\n")
};
$("head").prepend( $("head").prepend(
[ [
...(Object.keys(cssGlobalsToDefine).length === 0 ? [] : [ ...(Object.keys(cssGlobalsToDefine).length === 0 ? [] : [
@ -58,18 +77,14 @@ export function generateFtlFilesCodeFactory(
'</style>', '</style>',
'' ''
]), ]),
'<script>', '<script>',
' Object.assign(', ' Object.assign(',
` window.${ftlValuesGlobalName},`, ` window.${ftlValuesGlobalName},`,
' {', ` ${objectKeys(ftlPlaceholders)[0]}`,
' "url": {',
' "loginAction": "${url.loginAction}",',
' "resourcesPath": "${url.resourcesPath}"',
' }',
' }',
' );', ' );',
'</script>', '</script>',
'',
objectKeys(ftlPlaceholders)[1],
'' ''
].join("\n"), ].join("\n"),
); );
@ -94,11 +109,15 @@ export function generateFtlFilesCodeFactory(
` window.${ftlValuesGlobalName} = { "pageBasename": "${pageBasename}" };`, ` window.${ftlValuesGlobalName} = { "pageBasename": "${pageBasename}" };`,
'</script>', '</script>',
'' ''
].join("\n"), ].join("\n")
); );
return { "ftlCode": $.html() }; let ftlCode = $.html();
objectKeys(ftlPlaceholders)
.forEach(id => ftlCode = ftlCode.replace(id, ftlPlaceholders[id]));
return { ftlCode };
} }

View File

@ -3,17 +3,53 @@
import { ftlValuesGlobalName } from "../bin/build-keycloak-theme/generateKeycloakThemeResources"; import { ftlValuesGlobalName } from "../bin/build-keycloak-theme/generateKeycloakThemeResources";
import type { generateFtlFilesCodeFactory } from "../bin/build-keycloak-theme/generateFtl"; import type { generateFtlFilesCodeFactory } from "../bin/build-keycloak-theme/generateFtl";
import { id } from "evt/tools/typeSafety/id"; import { id } from "evt/tools/typeSafety/id";
export type LanguageLabel =
/* spell-checker: disable */
"Deutsch" | "Norsk" | "Русский" | "Svenska" | "Português (Brasil)" | "Lietuvių" |
"English" | "Italiano" | "Français" | "中文简体" | "Español" | "Čeština" | "日本語" |
"Slovenčina" | "Polish" | "Català" | "Nederlands" | "tr";
/* spell-checker: enable */
export type LanguageTag = "de" | "no" | "ru" | "sv" | "pt-BR" | "lt" | "en" | "it" | "fr" | "zh-CN" | "es" | "cs" | "ja" | "sk" | "pl" | "ca" | "nl" | "tr";
export type KeycloakFtlValues = { export type KeycloakFtlValues = {
pageBasename: Parameters<ReturnType<typeof generateFtlFilesCodeFactory>["generateFtlFilesCode"]>[0]["pageBasename"]; pageBasename: Parameters<ReturnType<typeof generateFtlFilesCodeFactory>["generateFtlFilesCode"]>[0]["pageBasename"];
url: { url: {
loginAction: string, loginAction: string;
resourcesPath: string resourcesPath: string;
} resourcesCommonPath: string;
loginRestartFlowUrl: string;
},
realm: {
displayName?: string;
displayNameHtml?: string;
internationalizationEnabled: boolean;
},
//NOTE: Undefined if !realm.internationalizationEnabled
locale?: {
supported: {
url: string;
label: LanguageLabel;
languageTag: LanguageTag;
},
current: LanguageLabel;
},
auth?: {
showUsername: boolean;
showResetCredentials: boolean;
showTryAnotherWayLink: boolean;
attemptedUsername?: boolean;
},
scripts: string[];
message?: {
type: "success" | "warning" | "error" | "info";
summary: string;
},
isAppInitiatedAction: boolean;
}; };
export const { keycloakPagesContext } = export const { keycloakPagesContext } =
{ [ftlValuesGlobalName]: id<KeycloakFtlValues | undefined>((window as any)[ftlValuesGlobalName]) }; { [ftlValuesGlobalName]: id<KeycloakFtlValues | undefined>((window as any)[ftlValuesGlobalName]) };
; ;

View File

@ -241,8 +241,13 @@
"signature": "c3a2f14af88ebca3c9e0445aa8c14d1cf6fcebfdadf54a46e26c46959e368119", "signature": "c3a2f14af88ebca3c9e0445aa8c14d1cf6fcebfdadf54a46e26c46959e368119",
"affectsGlobalScope": false "affectsGlobalScope": false
}, },
"../src/bin/build-keycloak-theme/generateFtl.ts": { "../node_modules/evt/tools/typeSafety/objectKeys.d.ts": {
"version": "9b6401a245a32e2968648cf5e48595a0a4e1d12237bf8aadf2da6336304ad8c8", "version": "4da2684f4596bd222840b428282b011560505fd93efb2de24709418ec33ad614",
"signature": "4da2684f4596bd222840b428282b011560505fd93efb2de24709418ec33ad614",
"affectsGlobalScope": false
},
"../src/bin/build-keycloak-theme/generateFtl/index.ts": {
"version": "0f236ff99727073587d85a380fc1e46f3176124d458ad699560507de2180c794",
"signature": "3a11af9abe294b90f19598d16e9d081f5452cdb668939e63abdd6a4d90955279", "signature": "3a11af9abe294b90f19598d16e9d081f5452cdb668939e63abdd6a4d90955279",
"affectsGlobalScope": false "affectsGlobalScope": false
}, },
@ -277,8 +282,8 @@
"affectsGlobalScope": false "affectsGlobalScope": false
}, },
"../src/lib/keycloakFtlValues.ts": { "../src/lib/keycloakFtlValues.ts": {
"version": "8855aa745f2916ae3bc7161b4ef9784c21f595070e177e2a201a5d8ffc672a64", "version": "1cad1ed4d26f828a7cdeef4ea5eb9bd6db3026ef9464eec29d1b6c0d00d78954",
"signature": "47f69685f9207ddeb9e876a0b9545efbd8a73a6b3b123c9b685165bde9d408df", "signature": "a4b2d36ae0aadc02ecd11b0e7da14a0b66f9498a2528e5d019023355787fed27",
"affectsGlobalScope": false "affectsGlobalScope": false
}, },
"../src/lib/index.ts": { "../src/lib/index.ts": {
@ -774,8 +779,11 @@
"../node_modules/@types/node/fs.d.ts", "../node_modules/@types/node/fs.d.ts",
"../node_modules/@types/node/path.d.ts" "../node_modules/@types/node/path.d.ts"
], ],
"../src/bin/build-keycloak-theme/generateFtl.ts": [ "../src/bin/build-keycloak-theme/generateFtl/index.ts": [
"../node_modules/@types/node/fs.d.ts",
"../node_modules/@types/node/path.d.ts",
"../node_modules/cheerio/types/index.d.ts", "../node_modules/cheerio/types/index.d.ts",
"../node_modules/evt/tools/typeSafety/objectKeys.d.ts",
"../src/bin/build-keycloak-theme/replaceImportFromStatic.ts" "../src/bin/build-keycloak-theme/replaceImportFromStatic.ts"
], ],
"../src/bin/build-keycloak-theme/generateJavaStackFiles.ts": [ "../src/bin/build-keycloak-theme/generateJavaStackFiles.ts": [
@ -786,7 +794,7 @@
"../src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts": [ "../src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts": [
"../node_modules/@types/node/fs.d.ts", "../node_modules/@types/node/fs.d.ts",
"../node_modules/@types/node/path.d.ts", "../node_modules/@types/node/path.d.ts",
"../src/bin/build-keycloak-theme/generateFtl.ts", "../src/bin/build-keycloak-theme/generateFtl/index.ts",
"../src/bin/build-keycloak-theme/replaceImportFromStatic.ts", "../src/bin/build-keycloak-theme/replaceImportFromStatic.ts",
"../src/tools/transformCodebase.ts" "../src/tools/transformCodebase.ts"
], ],
@ -811,7 +819,7 @@
], ],
"../src/lib/keycloakFtlValues.ts": [ "../src/lib/keycloakFtlValues.ts": [
"../node_modules/evt/tools/typeSafety/id.d.ts", "../node_modules/evt/tools/typeSafety/id.d.ts",
"../src/bin/build-keycloak-theme/generateFtl.ts", "../src/bin/build-keycloak-theme/generateFtl/index.ts",
"../src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts" "../src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts"
], ],
"../src/test/build-keycloak-theme.ts": [ "../src/test/build-keycloak-theme.ts": [
@ -1057,7 +1065,7 @@
"../src/lib/keycloakFtlValues.ts" "../src/lib/keycloakFtlValues.ts"
], ],
"../src/lib/keycloakFtlValues.ts": [ "../src/lib/keycloakFtlValues.ts": [
"../src/bin/build-keycloak-theme/generateFtl.ts" "../src/bin/build-keycloak-theme/generateFtl/index.ts"
] ]
}, },
"semanticDiagnosticsPerFile": [ "semanticDiagnosticsPerFile": [
@ -1119,6 +1127,7 @@
"../node_modules/domutils/lib/tagtypes.d.ts", "../node_modules/domutils/lib/tagtypes.d.ts",
"../node_modules/domutils/lib/traversal.d.ts", "../node_modules/domutils/lib/traversal.d.ts",
"../node_modules/evt/tools/typeSafety/id.d.ts", "../node_modules/evt/tools/typeSafety/id.d.ts",
"../node_modules/evt/tools/typeSafety/objectKeys.d.ts",
"../node_modules/htmlparser2/lib/FeedHandler.d.ts", "../node_modules/htmlparser2/lib/FeedHandler.d.ts",
"../node_modules/htmlparser2/lib/Parser.d.ts", "../node_modules/htmlparser2/lib/Parser.d.ts",
"../node_modules/htmlparser2/lib/Tokenizer.d.ts", "../node_modules/htmlparser2/lib/Tokenizer.d.ts",
@ -1154,7 +1163,7 @@
"../node_modules/typescript/lib/lib.es5.d.ts", "../node_modules/typescript/lib/lib.es5.d.ts",
"../node_modules/typescript/lib/lib.esnext.intl.d.ts", "../node_modules/typescript/lib/lib.esnext.intl.d.ts",
"../src/bin/build-keycloak-theme/generateDebugFiles/index.ts", "../src/bin/build-keycloak-theme/generateDebugFiles/index.ts",
"../src/bin/build-keycloak-theme/generateFtl.ts", "../src/bin/build-keycloak-theme/generateFtl/index.ts",
"../src/bin/build-keycloak-theme/generateJavaStackFiles.ts", "../src/bin/build-keycloak-theme/generateJavaStackFiles.ts",
"../src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts", "../src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts",
"../src/bin/build-keycloak-theme/index.ts", "../src/bin/build-keycloak-theme/index.ts",