Compare commits
38 Commits
Author | SHA1 | Date | |
---|---|---|---|
b0819314a1 | |||
0099442543 | |||
66a0b07228 | |||
85f9544754 | |||
2f16a09ab8 | |||
183ae98c30 | |||
ba15e63879 | |||
654277feda | |||
81279a5cc5 | |||
59f0a843b0 | |||
c094f70171 | |||
0858fe6319 | |||
5012ec0ccc | |||
990a24fab2 | |||
036b6bf82a | |||
8272a02b52 | |||
e346b1d9d2 | |||
2309bd21c6 | |||
7d6476c1b5 | |||
e892a0e7e6 | |||
ca5b41e730 | |||
9b18234112 | |||
5274368f47 | |||
1415c24028 | |||
4a084f5859 | |||
a30c9eb0cd | |||
85d3b40b8e | |||
335afec230 | |||
69fa49848a | |||
7a09051127 | |||
07ee0ecb8b | |||
6f133428f8 | |||
4f733736db | |||
d96ff13a67 | |||
2c1351ce47 | |||
96cd56ec77 | |||
e5b2096d65 | |||
3aa140335f |
40
CHANGELOG.md
40
CHANGELOG.md
@ -1,3 +1,43 @@
|
|||||||
|
### **0.3.20** (2021-04-01)
|
||||||
|
|
||||||
|
- Always catch freemarker errors
|
||||||
|
|
||||||
|
### **0.3.19** (2021-04-01)
|
||||||
|
|
||||||
|
- Fix previous release
|
||||||
|
|
||||||
|
### **0.3.18** (2021-04-01)
|
||||||
|
|
||||||
|
- Fix error.ftt, Adopt best effort strategy to convert ftl values into JS
|
||||||
|
|
||||||
|
### **0.3.17** (2021-03-29)
|
||||||
|
|
||||||
|
- Use push instead of replace in keycloak-js adapter to enable going back
|
||||||
|
|
||||||
|
### **0.3.15** (2021-03-28)
|
||||||
|
|
||||||
|
- Remove all reference to --external-assets, broken feature
|
||||||
|
|
||||||
|
### **0.3.14** (2021-03-28)
|
||||||
|
|
||||||
|
- Fix standalone mode: imports from js
|
||||||
|
|
||||||
|
### **0.3.13** (2021-03-26)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### **0.3.12** (2021-03-26)
|
||||||
|
|
||||||
|
- Fix mocksContext
|
||||||
|
|
||||||
|
### **0.3.11** (2021-03-26)
|
||||||
|
|
||||||
|
- Fix previous build, improve README
|
||||||
|
|
||||||
|
### **0.3.10** (2021-03-26)
|
||||||
|
|
||||||
|
- Handle <style> tag, improve documentation
|
||||||
|
|
||||||
### **0.3.9** (2021-03-25)
|
### **0.3.9** (2021-03-25)
|
||||||
|
|
||||||
- Update readme
|
- Update readme
|
||||||
|
71
README.md
71
README.md
@ -41,7 +41,6 @@ Here is `yarn add keycloakify` for you 🍸
|
|||||||
- [Motivations](#motivations)
|
- [Motivations](#motivations)
|
||||||
- [How to use](#how-to-use)
|
- [How to use](#how-to-use)
|
||||||
- [Setting up the build tool](#setting-up-the-build-tool)
|
- [Setting up the build tool](#setting-up-the-build-tool)
|
||||||
- [Specify from where the resources should be downloaded.](#specify-from-where-the-resources-should-be-downloaded)
|
|
||||||
- [Developing your login and register pages in your React app](#developing-your-login-and-register-pages-in-your-react-app)
|
- [Developing your login and register pages in your React app](#developing-your-login-and-register-pages-in-your-react-app)
|
||||||
- [Just changing the look](#just-changing-the-look)
|
- [Just changing the look](#just-changing-the-look)
|
||||||
- [Changing the look **and** feel](#changing-the-look-and-feel)
|
- [Changing the look **and** feel](#changing-the-look-and-feel)
|
||||||
@ -49,9 +48,13 @@ Here is `yarn add keycloakify` for you 🍸
|
|||||||
- [GitHub Actions](#github-actions)
|
- [GitHub Actions](#github-actions)
|
||||||
- [Requirements](#requirements)
|
- [Requirements](#requirements)
|
||||||
- [Limitations](#limitations)
|
- [Limitations](#limitations)
|
||||||
|
- [`process.env.PUBLIC_URL` not supported.](#processenvpublic_url-not-supported)
|
||||||
|
- [`@font-face` importing fonts from the `src/` dir](#font-face-importing-fonts-from-thesrc-dir)
|
||||||
|
- [Example of setup that **won't** work](#example-of-setup-that-wont-work)
|
||||||
|
- [Workarounds](#workarounds)
|
||||||
|
- [Implement context persistence (optional)](#implement-context-persistence-optional)
|
||||||
- [API Reference](#api-reference)
|
- [API Reference](#api-reference)
|
||||||
- [The build tool](#the-build-tool)
|
- [The build tool](#the-build-tool)
|
||||||
- [Implement context persistence (optional)](#implement-context-persistence-optional)
|
|
||||||
|
|
||||||
# How to use
|
# How to use
|
||||||
## Setting up the build tool
|
## Setting up the build tool
|
||||||
@ -66,6 +69,8 @@ Here is `yarn add keycloakify` for you 🍸
|
|||||||
"keycloak": "yarn build && build-keycloak-theme",
|
"keycloak": "yarn build && build-keycloak-theme",
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
`"homepage"` must be specified only if the url path is not `/`
|
||||||
|
(Onl `/YOUR-APP` matters `URL.OF` don't have to be the actual domain)
|
||||||
|
|
||||||
It is mandatory that you specify the url where your app will be available
|
It is mandatory that you specify the url where your app will be available
|
||||||
using the `homepage` field.
|
using the `homepage` field.
|
||||||
@ -77,33 +82,6 @@ dependency with `yarn install` and build the keycloak theme with
|
|||||||
Once the build is complete instructions about how to load
|
Once the build is complete instructions about how to load
|
||||||
the theme into Keycloak are printed in the console.
|
the theme into Keycloak are printed in the console.
|
||||||
|
|
||||||
### Specify from where the resources should be downloaded.
|
|
||||||
|
|
||||||
When you run `npx build-keycloak-theme` without arguments, Keycloakify will build
|
|
||||||
a standalone version of the Keycloak theme. That is to say even if your app, the
|
|
||||||
one hosted at the url specified as `homepage` in your package.json, is down the
|
|
||||||
Keycloak theme will still work.
|
|
||||||
In this mode (the default) every asset are served by the keycloak server. It is
|
|
||||||
convergent for debugging but it production you probably want the assets to be
|
|
||||||
fetched from your app.
|
|
||||||
Indeed in the default mode your users have to download again the whole app just
|
|
||||||
to access the login page. You probably have [long-term asset caching](https://create-react-app.dev/docs/production-build/#static-file-caching)
|
|
||||||
enabled in the server that host your app ([example](https://github.com/garronej/keycloakify-demo-app/blob/224c43383548635a463fa68e8909c147ac189f0e/nginx.conf#L14))
|
|
||||||
so it's better if only the html is served by the Keycloak server and everything
|
|
||||||
else, your JS bundles, your CSS ect point to your app.
|
|
||||||
|
|
||||||
To enable this behavior you car run:
|
|
||||||
```bash
|
|
||||||
npx build-keycloak-theme --external-assets
|
|
||||||
```
|
|
||||||
(instead of `npx build-keycloak-theme`)
|
|
||||||
|
|
||||||
This is something you probably want to do in your CI pipeline. [Example](https://github.com/garronej/keycloakify-demo-app/blob/224c43383548635a463fa68e8909c147ac189f0e/.github/workflows/ci.yaml#L112)
|
|
||||||
|
|
||||||
Also note that there is [a same-origin policy exception for fonts](https://en.wikipedia.org/wiki/Same-origin_policy#cite_note-3) so you must enabled
|
|
||||||
CORS for fonts on the server hosting your app. Concretely this mean that your server should add a `Access-Control-Allow-Origin: *` response header to
|
|
||||||
GET request on *.woff2?. [Example with Nginx](https://github.com/garronej/keycloakify-demo-app/blob/224c43383548635a463fa68e8909c147ac189f0e/nginx.conf#L18-L20)
|
|
||||||
|
|
||||||
## Developing your login and register pages in your React app
|
## Developing your login and register pages in your React app
|
||||||
|
|
||||||
### Just changing the look
|
### Just changing the look
|
||||||
@ -214,19 +192,25 @@ NOTE: This build tool has only be tested on MacOS.
|
|||||||
|
|
||||||
# Limitations
|
# Limitations
|
||||||
|
|
||||||
In the standalone mode (when you run `npx build-keycloak-theme` without `--external-assets`) the fonts won't work if you are self
|
## `process.env.PUBLIC_URL` not supported.
|
||||||
hosting them. This, for example, won’t work: [`src: url("/assets/worksans-bold-webfont.woff2") format("woff2")`](https://github.com/InseeFrLab/onyxia-ui/blob/b24df3a9b34b505ce00619bb8ec0174223ecfaca/src/app/theme/fonts.scss#L5-L6)
|
|
||||||
you will have to [host them externally](https://github.com/InseeFrLab/onyxia-ui/blob/43bf4a508419072a4ae202698e59d20b69feb9c0/src/app/theme/fonts.scss#L8-L9)
|
|
||||||
on a server that has CORS enabled.
|
|
||||||
Again this apply ony if you are not building your theme with `--external-assets` which is advised against in production.
|
|
||||||
# API Reference
|
|
||||||
|
|
||||||
## The build tool
|
You won't be able to [import things from your public directory in your JavaScript code](https://create-react-app.dev/docs/using-the-public-folder/#adding-assets-outside-of-the-module-system). (This isn't recommended anyway).
|
||||||
|
|
||||||
Part of the lib that runs with node, at build time.
|
## `@font-face` importing fonts from the `src/` dir
|
||||||
|
### Example of setup that **won't** work
|
||||||
|
|
||||||
- `npx build-keycloak-theme [--external-assets]`: Builds the theme, the CWD is assumed to be the root of your react project.
|
- We have a `fonts/` directory in `src/`
|
||||||
- `npx download-sample-keycloak-themes`: Downloads the keycloak default themes (for development purposes)
|
- We import the font like this [`src: url("/fonts/my-font.woff2") format("woff2");`(https://github.com/garronej/keycloakify-demo-app/blob/07d54a3012ef354ee12b1374c6f7ad1cb125d56b/src/fonts.scss#L4) in a `.scss` a file.
|
||||||
|
|
||||||
|
### Workarounds
|
||||||
|
|
||||||
|
If it is possible, use Google Fonts or any other font provider.
|
||||||
|
|
||||||
|
If you want to host your font recommended approach is to move your fonts into the `public`
|
||||||
|
directory and to place your `@font-face` statements in the `public/index.html`.
|
||||||
|
Example [here]().
|
||||||
|
|
||||||
|
You can also [use your explicit url](https://github.com/garronej/keycloakify-demo-app/blob/2de8a9eb6f5de9c94f9cd3991faad0377e63268c/src/fonts.scss#L16) but don't forget [`Access-Control-Allow-Origin`](https://github.com/garronej/keycloakify-demo-app/blob/2de8a9eb6f5de9c94f9cd3991faad0377e63268c/nginx.conf#L17-L19).
|
||||||
|
|
||||||
# Implement context persistence (optional)
|
# Implement context persistence (optional)
|
||||||
|
|
||||||
@ -286,3 +270,12 @@ keycloakInstance.init({
|
|||||||
If you really want to go the extra miles and avoid having the white
|
If you really want to go the extra miles and avoid having the white
|
||||||
flash of the blank html before the js bundle have been evaluated
|
flash of the blank html before the js bundle have been evaluated
|
||||||
[here is a snippet](https://github.com/InseeFrLab/onyxia-ui/blob/a77eb502870cfe6878edd0d956c646d28746d053/public/index.html#L5-L54) that you can place in your `public/index.html` if you are using `powerhooks/useGlobalState`.
|
[here is a snippet](https://github.com/InseeFrLab/onyxia-ui/blob/a77eb502870cfe6878edd0d956c646d28746d053/public/index.html#L5-L54) that you can place in your `public/index.html` if you are using `powerhooks/useGlobalState`.
|
||||||
|
|
||||||
|
# API Reference
|
||||||
|
|
||||||
|
## The build tool
|
||||||
|
|
||||||
|
Part of the lib that runs with node, at build time.
|
||||||
|
|
||||||
|
- `npx build-keycloak-theme`: Builds the theme, the CWD is assumed to be the root of your react project.
|
||||||
|
- `npx download-sample-keycloak-themes`: Downloads the keycloak default themes (for development purposes)
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "keycloakify",
|
"name": "keycloakify",
|
||||||
"version": "0.3.9",
|
"version": "0.3.20",
|
||||||
"description": "Keycloak theme generator for Reacts app",
|
"description": "Keycloak theme generator for Reacts app",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -14,8 +14,7 @@
|
|||||||
"grant-exec-perms": "node dist/bin/tools/grant-exec-perms.js",
|
"grant-exec-perms": "node dist/bin/tools/grant-exec-perms.js",
|
||||||
"test": "node dist/test",
|
"test": "node dist/test",
|
||||||
"copy-files": "copyfiles -u 1 src/**/*.ftl src/**/*.xml src/**/*.js dist/",
|
"copy-files": "copyfiles -u 1 src/**/*.ftl src/**/*.xml src/**/*.js dist/",
|
||||||
"generate-messages": "node dist/bin/generate-i18n-messages.js",
|
"generate-messages": "node dist/bin/generate-i18n-messages.js"
|
||||||
"watch": "tsc -w"
|
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"build-keycloak-theme": "dist/bin/build-keycloak-theme/index.js",
|
"build-keycloak-theme": "dist/bin/build-keycloak-theme/index.js",
|
||||||
@ -54,8 +53,8 @@
|
|||||||
"evt": "2.0.0-beta.15",
|
"evt": "2.0.0-beta.15",
|
||||||
"minimal-polyfills": "^2.1.6",
|
"minimal-polyfills": "^2.1.6",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"powerhooks": "^0.0.27",
|
"powerhooks": "^0.0.32",
|
||||||
"scripting-tools": "^0.19.13",
|
"scripting-tools": "^0.19.13",
|
||||||
"tss-react": "^0.0.11"
|
"tss-react": "^0.0.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
263
src/bin/build-keycloak-theme/generateFtl/common.ftl
Normal file
263
src/bin/build-keycloak-theme/generateFtl/common.ftl
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
<script>const _=
|
||||||
|
{
|
||||||
|
"url": {
|
||||||
|
"loginAction": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${url.loginAction?no_esc}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"resourcesPath": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${url.resourcesPath?no_esc}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"resourcesCommonPath": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${url.resourcesCommonPath?no_esc}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"loginRestartFlowUrl": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${url.loginRestartFlowUrl?no_esc}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"loginUrl": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${url.loginUrl?no_esc}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
|
},
|
||||||
|
"realm": {
|
||||||
|
"displayName": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${realm.displayName!''}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"displayNameHtml": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${realm.displayNameHtml!''}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"internationalizationEnabled": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return ${realm.internationalizationEnabled?c};
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"registrationEmailAsUsername": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return ${realm.registrationEmailAsUsername?c};
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
|
},
|
||||||
|
"locale": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
<#if realm.internationalizationEnabled>
|
||||||
|
|
||||||
|
return {
|
||||||
|
"supported": (function(){
|
||||||
|
|
||||||
|
var out= [];
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
<#list locale.supported as lng>
|
||||||
|
out.push({
|
||||||
|
"url": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${lng.url?no_esc}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"label": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${lng.label}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"languageTag": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${lng.languageTag}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
|
});
|
||||||
|
</#list>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
return out;
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"current": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${locale.current}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
|
};
|
||||||
|
|
||||||
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"auth": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
<#if auth?has_content>
|
||||||
|
|
||||||
|
var out= {
|
||||||
|
"showUsername": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return ${auth.showUsername()?c};
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"showResetCredentials": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return ${auth.showResetCredentials()?c};
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"showTryAnotherWayLink": (function(){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return ${auth.showTryAnotherWayLink()?c};
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
|
};
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
<#if auth.showUsername() && !auth.showResetCredentials()>
|
||||||
|
Object.assign(
|
||||||
|
out,
|
||||||
|
{
|
||||||
|
"attemptedUsername": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return "${auth.attemptedUsername}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
return out;
|
||||||
|
|
||||||
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"scripts": (function(){
|
||||||
|
|
||||||
|
var out = [];
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
<#if scripts??>
|
||||||
|
<#attempt>
|
||||||
|
<#list scripts as script>
|
||||||
|
out.push((function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${script}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})());
|
||||||
|
</#list>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
return out;
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"message": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
<#if message?has_content>
|
||||||
|
|
||||||
|
return {
|
||||||
|
"type": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${message.type}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"summary": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return String.htmlUnescape("${message.summary}");
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
|
};
|
||||||
|
|
||||||
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"isAppInitiatedAction": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
<#if isAppInitiatedAction??>
|
||||||
|
return true;
|
||||||
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
})()
|
||||||
|
}
|
||||||
|
</script>
|
@ -2,13 +2,21 @@
|
|||||||
{
|
{
|
||||||
"client": (function (){
|
"client": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
<#if client??>
|
<#if client??>
|
||||||
return {
|
return {
|
||||||
"baseUrl": "${(client.baseUrl!'')?no_esc}" || undefined
|
"baseUrl": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${(client.baseUrl!'')?no_esc}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
};
|
};
|
||||||
</#if>
|
</#if>
|
||||||
|
<#recover>
|
||||||
return undefined;
|
</#attempt>
|
||||||
|
|
||||||
})()
|
})()
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
import cheerio from "cheerio";
|
import cheerio from "cheerio";
|
||||||
import {
|
import {
|
||||||
replaceImportFromStaticInJsCode,
|
replaceImportsFromStaticInJsCode,
|
||||||
|
replaceImportsInInlineCssCode,
|
||||||
generateCssCodeToDefineGlobals
|
generateCssCodeToDefineGlobals
|
||||||
} from "../replaceImportFromStatic";
|
} from "../replaceImportFromStatic";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
@ -18,7 +19,7 @@ function loadAdjacentFile(fileBasename: string) {
|
|||||||
.toString("utf8");
|
.toString("utf8");
|
||||||
};
|
};
|
||||||
|
|
||||||
function loadFtlFile(ftlFileBasename: PageId | "template.ftl") {
|
function loadFtlFile(ftlFileBasename: PageId | "common.ftl") {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
return loadAdjacentFile(ftlFileBasename)
|
return loadAdjacentFile(ftlFileBasename)
|
||||||
@ -29,40 +30,42 @@ function loadFtlFile(ftlFileBasename: PageId | "template.ftl") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Mode = {
|
|
||||||
type: "standalone";
|
|
||||||
urlPathname: string;
|
|
||||||
} | {
|
|
||||||
type: "external assets";
|
|
||||||
urlPathname: string;
|
|
||||||
urlOrigin: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateFtlFilesCodeFactory(
|
export function generateFtlFilesCodeFactory(
|
||||||
params: {
|
params: {
|
||||||
ftlValuesGlobalName: string;
|
ftlValuesGlobalName: string;
|
||||||
cssGlobalsToDefine: Record<string, string>;
|
cssGlobalsToDefine: Record<string, string>;
|
||||||
indexHtmlCode: string;
|
indexHtmlCode: string;
|
||||||
mode: Mode;
|
urlPathname: string;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
|
||||||
const { ftlValuesGlobalName, cssGlobalsToDefine, indexHtmlCode, mode } = params;
|
const { ftlValuesGlobalName, cssGlobalsToDefine, indexHtmlCode, urlPathname } = params;
|
||||||
|
|
||||||
const $ = cheerio.load(indexHtmlCode);
|
const $ = cheerio.load(indexHtmlCode);
|
||||||
|
|
||||||
$("script:not([src])").each((...[, element]) => {
|
$("script:not([src])").each((...[, element]) => {
|
||||||
|
|
||||||
const { fixedJsCode } = replaceImportFromStaticInJsCode({
|
const { fixedJsCode } = replaceImportsFromStaticInJsCode({
|
||||||
ftlValuesGlobalName,
|
ftlValuesGlobalName,
|
||||||
"jsCode": $(element).html()!,
|
"jsCode": $(element).html()!
|
||||||
mode
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$(element).text(fixedJsCode);
|
$(element).text(fixedJsCode);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("style").each((...[, element]) => {
|
||||||
|
|
||||||
|
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
||||||
|
"cssCode": $(element).html()!,
|
||||||
|
"urlPathname": params.urlPathname
|
||||||
|
});
|
||||||
|
|
||||||
|
$(element).text(fixedCssCode);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
([
|
([
|
||||||
["link", "href"],
|
["link", "href"],
|
||||||
["script", "src"],
|
["script", "src"],
|
||||||
@ -75,31 +78,20 @@ export function generateFtlFilesCodeFactory(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mode.type) {
|
|
||||||
case "external assets":
|
|
||||||
$(element).attr(
|
|
||||||
attrName,
|
|
||||||
href.replace(/^\//, `${mode.urlOrigin}/`)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "standalone":
|
|
||||||
$(element).attr(
|
$(element).attr(
|
||||||
attrName,
|
attrName,
|
||||||
href.replace(
|
href.replace(
|
||||||
new RegExp(`^${mode.urlPathname.replace(/\//g, "\\/")}`),
|
new RegExp(`^${urlPathname.replace(/\//g, "\\/")}`),
|
||||||
"${url.resourcesPath}/build/"
|
"${url.resourcesPath}/build/"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
//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 ftlCommonPlaceholders = {
|
const ftlCommonPlaceholders = {
|
||||||
'{ "x": "vIdLqMeOed9sdLdIdOxdK0d" }': loadFtlFile("template.ftl"),
|
'{ "x": "vIdLqMeOed9sdLdIdOxdK0d" }': loadFtlFile("common.ftl"),
|
||||||
'<!-- xIdLqMeOedErIdLsPdNdI9dSlxI -->':
|
'<!-- xIdLqMeOedErIdLsPdNdI9dSlxI -->':
|
||||||
[
|
[
|
||||||
'<#if scripts??>',
|
'<#if scripts??>',
|
||||||
@ -119,7 +111,7 @@ export function generateFtlFilesCodeFactory(
|
|||||||
'<style>',
|
'<style>',
|
||||||
generateCssCodeToDefineGlobals({
|
generateCssCodeToDefineGlobals({
|
||||||
cssGlobalsToDefine,
|
cssGlobalsToDefine,
|
||||||
"urlPathname": mode.urlPathname
|
urlPathname
|
||||||
}).cssCodeToPrependInHead,
|
}).cssCodeToPrependInHead,
|
||||||
'</style>',
|
'</style>',
|
||||||
''
|
''
|
||||||
|
@ -1,37 +1,82 @@
|
|||||||
<script>const _=
|
<script>const _=
|
||||||
{
|
{
|
||||||
"messageHeader": "${messageHeader!''}" || undefined,
|
"messageHeader": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${messageHeader!''}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
"requiredActions": (function (){
|
"requiredActions": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
<#if requiredActions??>
|
<#if requiredActions??>
|
||||||
|
|
||||||
var out =[];
|
var out =[];
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
<#list requiredActions>
|
<#list requiredActions>
|
||||||
|
<#attempt>
|
||||||
<#items as reqActionItem>
|
<#items as reqActionItem>
|
||||||
out.push("${reqActionItem}");
|
out.push((function (){
|
||||||
</#items></b>
|
|
||||||
|
<#attempt>
|
||||||
|
return "${reqActionItem}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})());
|
||||||
|
</#items>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
</#list>
|
</#list>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
<#else>
|
</#if>
|
||||||
|
<#recover>
|
||||||
return undefined;
|
</#attempt>
|
||||||
|
|
||||||
})(),
|
})(),
|
||||||
"skipLink": (function (){
|
"skipLink": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
<#if skipLink??>
|
<#if skipLink??>
|
||||||
return true;
|
return true;
|
||||||
</#if>
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
})(),
|
})(),
|
||||||
"pageRedirectUri": "${(pageRedirectUri!'')?no_esc}" || undefined,
|
"pageRedirectUri": (function (){
|
||||||
"actionUri": "${(actionUri!'')?no_esc}" || undefined,
|
|
||||||
|
<#attempt>
|
||||||
|
return "${(pageRedirectUri!'')?no_esc}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"actionUri": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${(actionUri!'')?no_esc}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
"client": {
|
"client": {
|
||||||
"baseUrl": "${(client.baseUrl!'')?no_esc}" || undefined
|
"baseUrl": (function(){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${(client.baseUrl!'')?no_esc}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -1,7 +1,14 @@
|
|||||||
<script>const _=
|
<script>const _=
|
||||||
{
|
{
|
||||||
"realm": {
|
"realm": {
|
||||||
"loginWithEmailAllowed": ${realm.loginWithEmailAllowed?c}
|
"loginWithEmailAllowed": (function (){
|
||||||
},
|
|
||||||
|
<#attempt>
|
||||||
|
return ${realm.loginWithEmailAllowed?c};
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -1,83 +1,160 @@
|
|||||||
<script>const _=
|
<script>const _=
|
||||||
{
|
{
|
||||||
"url": {
|
"url": {
|
||||||
"loginResetCredentialsUrl": "${url.loginResetCredentialsUrl?no_esc}",
|
"loginResetCredentialsUrl": (function (){
|
||||||
"registrationUrl": "${url.registrationUrl?no_esc}"
|
<#attempt>
|
||||||
|
return "${url.loginResetCredentialsUrl?no_esc}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})(),
|
||||||
|
"registrationUrl": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return "${url.registrationUrl?no_esc}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})()
|
||||||
},
|
},
|
||||||
"realm": {
|
"realm": {
|
||||||
"loginWithEmailAllowed": ${realm.loginWithEmailAllowed?c},
|
"loginWithEmailAllowed": (function(){
|
||||||
"rememberMe": ${realm.rememberMe?c},
|
<#attempt>
|
||||||
"password": ${realm.password?c},
|
return ${realm.loginWithEmailAllowed?c};
|
||||||
"resetPasswordAllowed": ${realm.resetPasswordAllowed?c},
|
<#recover>
|
||||||
"registrationAllowed": ${realm.registrationAllowed?c}
|
</#attempt>
|
||||||
|
})(),
|
||||||
|
"rememberMe": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return ${realm.rememberMe?c};
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})(),
|
||||||
|
"password": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return ${realm.password?c};
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})(),
|
||||||
|
"resetPasswordAllowed": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return ${realm.resetPasswordAllowed?c};
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})(),
|
||||||
|
"registrationAllowed": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return ${realm.registrationAllowed?c};
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})()
|
||||||
},
|
},
|
||||||
"auth": (function (){
|
"auth": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
<#if auth?has_content>
|
<#if auth?has_content>
|
||||||
|
|
||||||
var out= {
|
return {
|
||||||
"selectedCredential": "${auth.selectedCredential!''}" || undefined
|
"selectedCredential": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return "${auth.selectedCredential!''}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})()
|
||||||
};
|
};
|
||||||
|
|
||||||
return out;
|
|
||||||
|
|
||||||
</#if>
|
</#if>
|
||||||
|
<#recover>
|
||||||
return undefined;
|
</#attempt>
|
||||||
|
|
||||||
})(),
|
})(),
|
||||||
"social": {
|
"social": {
|
||||||
"displayInfo": ${social.displayInfo?c},
|
"displayInfo": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return ${social.displayInfo?c};
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})(),
|
||||||
"providers": (()=>{
|
"providers": (()=>{
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
<#if social.providers??>
|
<#if social.providers??>
|
||||||
|
|
||||||
var out= [];
|
var out= [];
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
<#list social.providers as p>
|
<#list social.providers as p>
|
||||||
out.push({
|
out.push({
|
||||||
"loginUrl": "${p.loginUrl?no_esc}",
|
"loginUrl": (function (){
|
||||||
"alias": "${p.alias}",
|
<#attempt>
|
||||||
"providerId": "${p.providerId}",
|
return "${p.loginUrl?no_esc}";
|
||||||
"displayName": "${p.displayName}"
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})(),
|
||||||
|
"alias": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return "${p.alias}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})(),
|
||||||
|
"providerId": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return "${p.providerId}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})(),
|
||||||
|
"displayName": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return "${p.displayName}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})()
|
||||||
});
|
});
|
||||||
</#list>
|
</#list>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
</#if>
|
</#if>
|
||||||
|
<#recover>
|
||||||
return undefined;
|
</#attempt>
|
||||||
|
|
||||||
})()
|
})()
|
||||||
},
|
},
|
||||||
"usernameEditDisabled": (function () {
|
"usernameEditDisabled": (function () {
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
<#if usernameEditDisabled??>
|
<#if usernameEditDisabled??>
|
||||||
return true;
|
return true;
|
||||||
</#if>
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
})(),
|
})(),
|
||||||
"login": {
|
"login": {
|
||||||
"username": "${login.username!''}" || undefined,
|
"username": (function (){
|
||||||
|
<#attempt>
|
||||||
|
return "${login.username!''}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
})(),
|
||||||
"rememberMe": (function (){
|
"rememberMe": (function (){
|
||||||
|
<#attempt>
|
||||||
<#if login.rememberMe??>
|
<#if login.rememberMe??>
|
||||||
return true;
|
return true;
|
||||||
</#if>
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
})()
|
})()
|
||||||
},
|
},
|
||||||
"registrationDisabled": (function (){
|
"registrationDisabled": (function (){
|
||||||
|
<#attempt>
|
||||||
<#if registrationDisabled??>
|
<#if registrationDisabled??>
|
||||||
return true;
|
return true;
|
||||||
</#if>
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
})()
|
})()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -1,46 +1,152 @@
|
|||||||
<script>const _=
|
<script>const _=
|
||||||
{
|
{
|
||||||
"url": {
|
"url": {
|
||||||
"registrationAction": "${url.registrationAction?no_esc}"
|
"registrationAction": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${url.registrationAction?no_esc}";
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
},
|
},
|
||||||
"messagesPerField": {
|
"messagesPerField": {
|
||||||
"printIfExists": function (key, x) {
|
"printIfExists": function (key, x) {
|
||||||
switch(key){
|
switch(key){
|
||||||
case "userLabel": "${messagesPerField.printIfExists('userLabel','1')}" ? x : undefined;
|
case "userLabel": return (function (){
|
||||||
case "username": "${messagesPerField.printIfExists('username','1')}" ? x : undefined;
|
|
||||||
case "email": "${messagesPerField.printIfExists('email','1')}" ? x : undefined;
|
<#attempt>
|
||||||
case "firstName": "${messagesPerField.printIfExists('firstName','1')}" ? x : undefined;
|
return "${messagesPerField.printIfExists('userLabel','1')}" ? x : undefined;
|
||||||
case "lastName": "${messagesPerField.printIfExists('lastName','1')}" ? x : undefined;
|
<#recover>
|
||||||
case "password": "${messagesPerField.printIfExists('password','1')}" ? x : undefined;
|
</#attempt>
|
||||||
case "password-confirm": "${messagesPerField.printIfExists('password-confirm','1')}" ? x : undefined;
|
|
||||||
|
})();
|
||||||
|
case "username": return (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${messagesPerField.printIfExists('username','1')}" ? x : undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})();
|
||||||
|
case "email": return (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${messagesPerField.printIfExists('email','1')}" ? x : undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})();
|
||||||
|
case "firstName": return (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${messagesPerField.printIfExists('firstName','1')}" ? x : undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})();
|
||||||
|
case "lastName": return (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${messagesPerField.printIfExists('lastName','1')}" ? x : undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})();
|
||||||
|
case "password": return (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${messagesPerField.printIfExists('password','1')}" ? x : undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})();
|
||||||
|
case "password-confirm": return (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${messagesPerField.printIfExists('password-confirm','1')}" ? x : undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"register": {
|
"register": {
|
||||||
"formData": {
|
"formData": {
|
||||||
"firstName": "${register.formData.firstName!''}" || undefined,
|
"firstName": (function (){
|
||||||
"displayName": "${register.formData.displayName!''}" || undefined,
|
|
||||||
"lastName": "${register.formData.lastName!''}" || undefined,
|
<#attempt>
|
||||||
"email": "${register.formData.email!''}" || undefined,
|
return "${register.formData.firstName!''}" || undefined;
|
||||||
"username": "${register.formData.username!''}" || undefined
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"displayName": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${register.formData.displayName!''}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"lastName": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${register.formData.lastName!''}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"email": (function(){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${register.formData.email!''}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})(),
|
||||||
|
"username": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${register.formData.username!''}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"passwordRequired": (function (){
|
"passwordRequired": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
<#if passwordRequired??>
|
<#if passwordRequired??>
|
||||||
return true;
|
return true;
|
||||||
</#if>
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
})(),
|
})(),
|
||||||
"recaptchaRequired": (function (){
|
"recaptchaRequired": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
<#if passwordRequired??>
|
<#if passwordRequired??>
|
||||||
return true;
|
return true;
|
||||||
</#if>
|
</#if>
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
})(),
|
})(),
|
||||||
"recaptchaSiteKey": "${recaptchaSiteKey!''}" || undefined
|
"recaptchaSiteKey": (function (){
|
||||||
|
|
||||||
|
<#attempt>
|
||||||
|
return "${recaptchaSiteKey!''}" || undefined;
|
||||||
|
<#recover>
|
||||||
|
</#attempt>
|
||||||
|
|
||||||
|
})()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -1,114 +0,0 @@
|
|||||||
<script>const _=
|
|
||||||
{
|
|
||||||
"url": {
|
|
||||||
"loginAction": "${url.loginAction?no_esc}",
|
|
||||||
"resourcesPath": "${url.resourcesPath?no_esc}",
|
|
||||||
"resourcesCommonPath": "${url.resourcesCommonPath?no_esc}",
|
|
||||||
"loginRestartFlowUrl": "${url.loginRestartFlowUrl?no_esc}",
|
|
||||||
"loginUrl": "${url.loginUrl?no_esc}"
|
|
||||||
},
|
|
||||||
"realm": {
|
|
||||||
"displayName": "${realm.displayName!''}" || undefined,
|
|
||||||
"displayNameHtml": "${realm.displayNameHtml!''}" || undefined,
|
|
||||||
"internationalizationEnabled": ${realm.internationalizationEnabled?c},
|
|
||||||
"registrationEmailAsUsername": ${realm.registrationEmailAsUsername?c},
|
|
||||||
},
|
|
||||||
"locale": (function (){
|
|
||||||
|
|
||||||
<#if realm.internationalizationEnabled>
|
|
||||||
|
|
||||||
return {
|
|
||||||
"supported": (function(){
|
|
||||||
|
|
||||||
<#if realm.internationalizationEnabled>
|
|
||||||
|
|
||||||
var out= [];
|
|
||||||
|
|
||||||
<#list locale.supported as lng>
|
|
||||||
out.push({
|
|
||||||
"url": "${lng.url?no_esc}",
|
|
||||||
"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": String.htmlUnescape("${message.summary}")
|
|
||||||
};
|
|
||||||
|
|
||||||
</#if>
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
|
|
||||||
})(),
|
|
||||||
"isAppInitiatedAction": (function (){
|
|
||||||
|
|
||||||
<#if isAppInitiatedAction??>
|
|
||||||
return true;
|
|
||||||
</#if>
|
|
||||||
return false;
|
|
||||||
|
|
||||||
})()
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -3,10 +3,10 @@ import { transformCodebase } from "../tools/transformCodebase";
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { join as pathJoin } from "path";
|
import { join as pathJoin } from "path";
|
||||||
import {
|
import {
|
||||||
replaceImportFromStaticInCssCode,
|
replaceImportsInCssCode,
|
||||||
replaceImportFromStaticInJsCode
|
replaceImportsFromStaticInJsCode
|
||||||
} from "./replaceImportFromStatic";
|
} from "./replaceImportFromStatic";
|
||||||
import { generateFtlFilesCodeFactory, pageIds, Mode } from "./generateFtl";
|
import { generateFtlFilesCodeFactory, pageIds } from "./generateFtl";
|
||||||
import { builtinThemesUrl } from "../install-builtin-keycloak-themes";
|
import { builtinThemesUrl } from "../install-builtin-keycloak-themes";
|
||||||
import { downloadAndUnzip } from "../tools/downloadAndUnzip";
|
import { downloadAndUnzip } from "../tools/downloadAndUnzip";
|
||||||
import * as child_process from "child_process";
|
import * as child_process from "child_process";
|
||||||
@ -20,11 +20,11 @@ export function generateKeycloakThemeResources(
|
|||||||
themeName: string;
|
themeName: string;
|
||||||
reactAppBuildDirPath: string;
|
reactAppBuildDirPath: string;
|
||||||
keycloakThemeBuildingDirPath: string;
|
keycloakThemeBuildingDirPath: string;
|
||||||
mode: Mode;
|
urlPathname: string;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
|
||||||
const { themeName, reactAppBuildDirPath, keycloakThemeBuildingDirPath, mode } = params;
|
const { themeName, reactAppBuildDirPath, keycloakThemeBuildingDirPath, urlPathname } = params;
|
||||||
|
|
||||||
const themeDirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", themeName, "login");
|
const themeDirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", themeName, "login");
|
||||||
|
|
||||||
@ -45,11 +45,10 @@ export function generateKeycloakThemeResources(
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode.type === "standalone") {
|
|
||||||
|
|
||||||
if (/\.css?$/i.test(filePath)) {
|
if (/\.css?$/i.test(filePath)) {
|
||||||
|
|
||||||
const { cssGlobalsToDefine, fixedCssCode } = replaceImportFromStaticInCssCode(
|
const { cssGlobalsToDefine, fixedCssCode } = replaceImportsInCssCode(
|
||||||
{ "cssCode": sourceCode.toString("utf8") }
|
{ "cssCode": sourceCode.toString("utf8") }
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -62,20 +61,18 @@ export function generateKeycloakThemeResources(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (/\.js?$/i.test(filePath)) {
|
if (/\.js?$/i.test(filePath)) {
|
||||||
|
|
||||||
const { fixedJsCode } = replaceImportFromStaticInJsCode({
|
const { fixedJsCode } = replaceImportsFromStaticInJsCode({
|
||||||
"jsCode": sourceCode.toString("utf8"),
|
"jsCode": sourceCode.toString("utf8"),
|
||||||
ftlValuesGlobalName,
|
ftlValuesGlobalName
|
||||||
mode
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return { "modifiedSourceCode": Buffer.from(fixedJsCode, "utf8") };
|
return { "modifiedSourceCode": Buffer.from(fixedJsCode, "utf8") };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return { "modifiedSourceCode": sourceCode };
|
return { "modifiedSourceCode": sourceCode };
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -87,7 +84,7 @@ export function generateKeycloakThemeResources(
|
|||||||
"indexHtmlCode": fs.readFileSync(
|
"indexHtmlCode": fs.readFileSync(
|
||||||
pathJoin(reactAppBuildDirPath, "index.html")
|
pathJoin(reactAppBuildDirPath, "index.html")
|
||||||
).toString("utf8"),
|
).toString("utf8"),
|
||||||
mode
|
urlPathname
|
||||||
});
|
});
|
||||||
|
|
||||||
pageIds.forEach(pageId => {
|
pageIds.forEach(pageId => {
|
||||||
|
@ -11,8 +11,6 @@ import { URL } from "url";
|
|||||||
|
|
||||||
const reactProjectDirPath = process.cwd();
|
const reactProjectDirPath = process.cwd();
|
||||||
|
|
||||||
const doUseExternalAssets = process.argv[2]?.toLowerCase() === "--external-assets";
|
|
||||||
|
|
||||||
const parsedPackageJson: ParsedPackageJson = require(pathJoin(reactProjectDirPath, "package.json"));
|
const parsedPackageJson: ParsedPackageJson = require(pathJoin(reactProjectDirPath, "package.json"));
|
||||||
|
|
||||||
export const keycloakThemeBuildingDirPath = pathJoin(reactProjectDirPath, "build_keycloak");
|
export const keycloakThemeBuildingDirPath = pathJoin(reactProjectDirPath, "build_keycloak");
|
||||||
@ -26,8 +24,7 @@ if (require.main === module) {
|
|||||||
keycloakThemeBuildingDirPath,
|
keycloakThemeBuildingDirPath,
|
||||||
"reactAppBuildDirPath": pathJoin(reactProjectDirPath, "build"),
|
"reactAppBuildDirPath": pathJoin(reactProjectDirPath, "build"),
|
||||||
"themeName": parsedPackageJson.name,
|
"themeName": parsedPackageJson.name,
|
||||||
"mode": (() => {
|
"urlPathname": (() => {
|
||||||
|
|
||||||
|
|
||||||
const url = (() => {
|
const url = (() => {
|
||||||
|
|
||||||
@ -39,37 +36,12 @@ if (require.main === module) {
|
|||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const urlPathname =
|
return url === undefined ?
|
||||||
url === undefined ?
|
|
||||||
"/" :
|
"/" :
|
||||||
url.pathname.replace(/([^/])$/, "$1/");
|
url.pathname.replace(/([^/])$/, "$1/");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return !doUseExternalAssets ?
|
|
||||||
{
|
|
||||||
"type": "standalone",
|
|
||||||
urlPathname
|
|
||||||
} as const
|
|
||||||
:
|
|
||||||
{
|
|
||||||
"type": "external assets",
|
|
||||||
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({
|
const { jarFilePath } = generateJavaStackFiles({
|
||||||
|
@ -1,45 +1,45 @@
|
|||||||
|
|
||||||
import * as crypto from "crypto";
|
import * as crypto from "crypto";
|
||||||
|
|
||||||
type Mode = {
|
export function replaceImportsFromStaticInJsCode(
|
||||||
type: "standalone";
|
|
||||||
} | {
|
|
||||||
type: "external assets";
|
|
||||||
urlOrigin: string;
|
|
||||||
urlPathname: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function replaceImportFromStaticInJsCode(
|
|
||||||
params: {
|
params: {
|
||||||
ftlValuesGlobalName: string;
|
ftlValuesGlobalName: string;
|
||||||
jsCode: string;
|
jsCode: string;
|
||||||
mode: Mode;
|
|
||||||
}
|
}
|
||||||
): { fixedJsCode: string; } {
|
): { fixedJsCode: string; } {
|
||||||
|
|
||||||
const { jsCode, ftlValuesGlobalName, mode } = params;
|
const { jsCode, ftlValuesGlobalName } = params;
|
||||||
|
|
||||||
const fixedJsCode = (() => {
|
const fixedJsCode = jsCode.replace(
|
||||||
switch (mode.type) {
|
|
||||||
case "standalone":
|
|
||||||
return jsCode!.replace(
|
|
||||||
/[a-z]+\.[a-z]+\+"static\//g,
|
/[a-z]+\.[a-z]+\+"static\//g,
|
||||||
`window.${ftlValuesGlobalName}.url.resourcesPath + "/build/static/`
|
`window.${ftlValuesGlobalName}.url.resourcesPath + "/build/static/`
|
||||||
);
|
);
|
||||||
case "external assets":
|
|
||||||
return jsCode!.replace(
|
|
||||||
/[a-z]+\.[a-z]+\+"static\//g,
|
|
||||||
`"${mode.urlOrigin}${mode.urlPathname}static/`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
|
|
||||||
return { fixedJsCode };
|
return { fixedJsCode };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function replaceImportFromStaticInCssCode(
|
export function replaceImportsInInlineCssCode(
|
||||||
|
params: {
|
||||||
|
cssCode: string;
|
||||||
|
urlPathname: string;
|
||||||
|
}
|
||||||
|
): { fixedCssCode: string; } {
|
||||||
|
|
||||||
|
const { cssCode, urlPathname } = params;
|
||||||
|
|
||||||
|
const fixedCssCode = cssCode.replace(
|
||||||
|
urlPathname === "/" ?
|
||||||
|
/url\(\/([^/][^)]+)\)/g :
|
||||||
|
new RegExp(`url\\(${urlPathname}([^)]+)\\)`, "g"),
|
||||||
|
(...[, group]) => `url(${"${url.resourcesPath}/build/" + group})`
|
||||||
|
);
|
||||||
|
|
||||||
|
return { fixedCssCode };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export function replaceImportsInCssCode(
|
||||||
params: {
|
params: {
|
||||||
cssCode: string;
|
cssCode: string;
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ export function replaceImportFromStaticInCssCode(
|
|||||||
|
|
||||||
const cssGlobalsToDefine: Record<string, string> = {};
|
const cssGlobalsToDefine: Record<string, string> = {};
|
||||||
|
|
||||||
new Set(cssCode.match(/url\(\/[^)]+\)[^;}]*/g) ?? [])
|
new Set(cssCode.match(/url\(\/[^/][^)]+\)[^;}]*/g) ?? [])
|
||||||
.forEach(match =>
|
.forEach(match =>
|
||||||
cssGlobalsToDefine[
|
cssGlobalsToDefine[
|
||||||
"url" + crypto
|
"url" + crypto
|
||||||
|
@ -25,7 +25,7 @@ export type TemplateProps = {
|
|||||||
showUsernameNode?: ReactNode;
|
showUsernameNode?: ReactNode;
|
||||||
formNode: ReactNode;
|
formNode: ReactNode;
|
||||||
infoNode?: ReactNode;
|
infoNode?: ReactNode;
|
||||||
} & { kcContext: KcContext.Template; } & KcTemplateProps;
|
} & { kcContext: KcContext; } & KcTemplateProps;
|
||||||
|
|
||||||
export const Template = memo((props: TemplateProps) => {
|
export const Template = memo((props: TemplateProps) => {
|
||||||
|
|
||||||
|
@ -10,12 +10,17 @@ import type { LanguageLabel } from "./i18n/KcLanguageTag";
|
|||||||
type ExtractAfterStartingWith<Prefix extends string, StrEnum> =
|
type ExtractAfterStartingWith<Prefix extends string, StrEnum> =
|
||||||
StrEnum extends `${Prefix}${infer U}` ? U : never;
|
StrEnum extends `${Prefix}${infer U}` ? U : never;
|
||||||
|
|
||||||
|
/** Take theses type definition with a grain of salt.
|
||||||
|
* Some values might be undefined on some pages.
|
||||||
|
* (ex: url.loginAction is undefined on error.ftl)
|
||||||
|
*/
|
||||||
export type KcContext =
|
export type KcContext =
|
||||||
KcContext.Login | KcContext.Register | KcContext.Info |
|
KcContext.Login | KcContext.Register | KcContext.Info |
|
||||||
KcContext.Error | KcContext.LoginResetPassword | KcContext.LoginVerifyEmail;
|
KcContext.Error | KcContext.LoginResetPassword | KcContext.LoginVerifyEmail;
|
||||||
|
|
||||||
export declare namespace KcContext {
|
export declare namespace KcContext {
|
||||||
|
|
||||||
export type Template = {
|
export type Common = {
|
||||||
url: {
|
url: {
|
||||||
loginAction: string;
|
loginAction: string;
|
||||||
resourcesPath: string;
|
resourcesPath: string;
|
||||||
@ -27,7 +32,7 @@ export declare namespace KcContext {
|
|||||||
displayName?: string;
|
displayName?: string;
|
||||||
displayNameHtml?: string;
|
displayNameHtml?: string;
|
||||||
internationalizationEnabled: boolean;
|
internationalizationEnabled: boolean;
|
||||||
registrationEmailAsUsername: boolean; //<---
|
registrationEmailAsUsername: boolean;
|
||||||
};
|
};
|
||||||
/** Undefined if !realm.internationalizationEnabled */
|
/** Undefined if !realm.internationalizationEnabled */
|
||||||
locale?: {
|
locale?: {
|
||||||
@ -55,7 +60,7 @@ export declare namespace KcContext {
|
|||||||
isAppInitiatedAction: boolean;
|
isAppInitiatedAction: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Login = Template & {
|
export type Login = Common & {
|
||||||
pageId: "login.ftl";
|
pageId: "login.ftl";
|
||||||
url: {
|
url: {
|
||||||
loginResetCredentialsUrl: string;
|
loginResetCredentialsUrl: string;
|
||||||
@ -88,7 +93,7 @@ export declare namespace KcContext {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Register = Template & {
|
export type Register = Common & {
|
||||||
pageId: "register.ftl";
|
pageId: "register.ftl";
|
||||||
url: {
|
url: {
|
||||||
registrationAction: string;
|
registrationAction: string;
|
||||||
@ -120,7 +125,7 @@ export declare namespace KcContext {
|
|||||||
recaptchaSiteKey?: string;
|
recaptchaSiteKey?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Info = Template & {
|
export type Info = Common & {
|
||||||
pageId: "info.ftl";
|
pageId: "info.ftl";
|
||||||
messageHeader?: string;
|
messageHeader?: string;
|
||||||
requiredActions?: ExtractAfterStartingWith<"requiredAction.", MessageKey>[];
|
requiredActions?: ExtractAfterStartingWith<"requiredAction.", MessageKey>[];
|
||||||
@ -132,21 +137,21 @@ export declare namespace KcContext {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Error = Template & {
|
export type Error = Common & {
|
||||||
pageId: "error.ftl";
|
pageId: "error.ftl";
|
||||||
client?: {
|
client?: {
|
||||||
baseUrl?: string;
|
baseUrl?: string;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LoginResetPassword = Template & {
|
export type LoginResetPassword = Common & {
|
||||||
pageId: "login-reset-password.ftl";
|
pageId: "login-reset-password.ftl";
|
||||||
realm: {
|
realm: {
|
||||||
loginWithEmailAllowed: boolean;
|
loginWithEmailAllowed: boolean;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LoginVerifyEmail = Template & {
|
export type LoginVerifyEmail = Common & {
|
||||||
pageId: "login-verify-email.ftl";
|
pageId: "login-verify-email.ftl";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,11 +6,11 @@ import { getKcLanguageTagLabel } from "../i18n/KcLanguageTag";
|
|||||||
//NOTE: Aside because we want to be able to import them from node
|
//NOTE: Aside because we want to be able to import them from node
|
||||||
import { resourcesCommonPath, resourcesPath } from "./urlResourcesPath";
|
import { resourcesCommonPath, resourcesPath } from "./urlResourcesPath";
|
||||||
|
|
||||||
export const kcTemplateContext: KcContext.Template = {
|
const kcCommonContext: KcContext.Common = {
|
||||||
"url": {
|
"url": {
|
||||||
"loginAction": "#",
|
"loginAction": "#",
|
||||||
"resourcesPath": "/" + resourcesPath,
|
"resourcesPath": `${process.env["PUBLIC_URL"]}/${resourcesPath}`,
|
||||||
"resourcesCommonPath": "/" + resourcesCommonPath,
|
"resourcesCommonPath": `${process.env["PUBLIC_URL"]}/${resourcesCommonPath}`,
|
||||||
"loginRestartFlowUrl": "/auth/realms/myrealm/login-actions/restart?client_id=account&tab_id=HoAx28ja4xg",
|
"loginRestartFlowUrl": "/auth/realms/myrealm/login-actions/restart?client_id=account&tab_id=HoAx28ja4xg",
|
||||||
"loginUrl": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg",
|
"loginUrl": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg",
|
||||||
},
|
},
|
||||||
@ -111,7 +111,7 @@ export const kcTemplateContext: KcContext.Template = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Object.defineProperty(
|
Object.defineProperty(
|
||||||
kcTemplateContext.locale!,
|
kcCommonContext.locale!,
|
||||||
"current",
|
"current",
|
||||||
{
|
{
|
||||||
"get": () => getKcLanguageTagLabel(getEvtKcLanguage().state),
|
"get": () => getKcLanguageTagLabel(getEvtKcLanguage().state),
|
||||||
@ -120,22 +120,22 @@ Object.defineProperty(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const kcLoginContext: KcContext.Login = {
|
export const kcLoginContext: KcContext.Login = {
|
||||||
...kcTemplateContext,
|
...kcCommonContext,
|
||||||
"pageId": "login.ftl",
|
"pageId": "login.ftl",
|
||||||
"url": {
|
"url": {
|
||||||
...kcTemplateContext.url,
|
...kcCommonContext.url,
|
||||||
"loginResetCredentialsUrl": "/auth/realms/myrealm/login-actions/reset-credentials?client_id=account&tab_id=HoAx28ja4xg",
|
"loginResetCredentialsUrl": "/auth/realms/myrealm/login-actions/reset-credentials?client_id=account&tab_id=HoAx28ja4xg",
|
||||||
"registrationUrl": "/auth/realms/myrealm/login-actions/registration?client_id=account&tab_id=HoAx28ja4xg"
|
"registrationUrl": "/auth/realms/myrealm/login-actions/registration?client_id=account&tab_id=HoAx28ja4xg"
|
||||||
},
|
},
|
||||||
"realm": {
|
"realm": {
|
||||||
...kcTemplateContext.realm,
|
...kcCommonContext.realm,
|
||||||
"loginWithEmailAllowed": true,
|
"loginWithEmailAllowed": true,
|
||||||
"rememberMe": true,
|
"rememberMe": true,
|
||||||
"password": true,
|
"password": true,
|
||||||
"resetPasswordAllowed": true,
|
"resetPasswordAllowed": true,
|
||||||
"registrationAllowed": true
|
"registrationAllowed": true
|
||||||
},
|
},
|
||||||
"auth": kcTemplateContext.auth!,
|
"auth": kcCommonContext.auth!,
|
||||||
"social": {
|
"social": {
|
||||||
"displayInfo": true
|
"displayInfo": true
|
||||||
},
|
},
|
||||||
@ -147,7 +147,7 @@ export const kcLoginContext: KcContext.Login = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const kcRegisterContext: KcContext.Register = {
|
export const kcRegisterContext: KcContext.Register = {
|
||||||
...kcTemplateContext,
|
...kcCommonContext,
|
||||||
"url": {
|
"url": {
|
||||||
...kcLoginContext.url,
|
...kcLoginContext.url,
|
||||||
"registrationAction": "http://localhost:8080/auth/realms/myrealm/login-actions/registration?session_code=gwZdUeO7pbYpFTRxiIxRg_QtzMbtFTKrNu6XW_f8asM&execution=12146ce0-b139-4bbd-b25b-0eccfee6577e&client_id=account&tab_id=uS8lYfebLa0"
|
"registrationAction": "http://localhost:8080/auth/realms/myrealm/login-actions/registration?session_code=gwZdUeO7pbYpFTRxiIxRg_QtzMbtFTKrNu6XW_f8asM&execution=12146ce0-b139-4bbd-b25b-0eccfee6577e&client_id=account&tab_id=uS8lYfebLa0"
|
||||||
@ -166,7 +166,7 @@ export const kcRegisterContext: KcContext.Register = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const kcInfoContext: KcContext.Info ={
|
export const kcInfoContext: KcContext.Info ={
|
||||||
...kcTemplateContext,
|
...kcCommonContext,
|
||||||
"pageId": "info.ftl",
|
"pageId": "info.ftl",
|
||||||
"messageHeader": "<Message header>",
|
"messageHeader": "<Message header>",
|
||||||
"requiredActions": undefined,
|
"requiredActions": undefined,
|
||||||
@ -178,7 +178,7 @@ export const kcInfoContext: KcContext.Info ={
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const kcErrorContext: KcContext.Error = {
|
export const kcErrorContext: KcContext.Error = {
|
||||||
...kcTemplateContext,
|
...kcCommonContext,
|
||||||
"pageId": "error.ftl",
|
"pageId": "error.ftl",
|
||||||
"client": {
|
"client": {
|
||||||
"baseUrl": "#"
|
"baseUrl": "#"
|
||||||
@ -186,16 +186,16 @@ export const kcErrorContext: KcContext.Error = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const kcLoginResetPasswordContext: KcContext.LoginResetPassword = {
|
export const kcLoginResetPasswordContext: KcContext.LoginResetPassword = {
|
||||||
...kcTemplateContext,
|
...kcCommonContext,
|
||||||
"pageId": "login-reset-password.ftl",
|
"pageId": "login-reset-password.ftl",
|
||||||
"realm":{
|
"realm":{
|
||||||
...kcTemplateContext.realm,
|
...kcCommonContext.realm,
|
||||||
"loginWithEmailAllowed": false
|
"loginWithEmailAllowed": false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const kcLoginVerifyEmailContext: KcContext.LoginVerifyEmail = {
|
export const kcLoginVerifyEmailContext: KcContext.LoginVerifyEmail = {
|
||||||
...kcTemplateContext,
|
...kcCommonContext,
|
||||||
"pageId": "login-verify-email.ftl"
|
"pageId": "login-verify-email.ftl"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,12 +66,11 @@ export function createKeycloakAdapter(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
"login": options => {
|
"login": options => {
|
||||||
window.location.replace(
|
window.location.href=
|
||||||
transformUrlBeforeRedirect(
|
transformUrlBeforeRedirect(
|
||||||
keycloakInstance.createLoginUrl(
|
keycloakInstance.createLoginUrl(
|
||||||
options
|
options
|
||||||
)
|
)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
return neverResolvingPromise;
|
return neverResolvingPromise;
|
||||||
},
|
},
|
||||||
@ -86,13 +85,13 @@ export function createKeycloakAdapter(
|
|||||||
return neverResolvingPromise;
|
return neverResolvingPromise;
|
||||||
},
|
},
|
||||||
"register": options => {
|
"register": options => {
|
||||||
window.location.replace(
|
window.location.href =
|
||||||
transformUrlBeforeRedirect(
|
transformUrlBeforeRedirect(
|
||||||
keycloakInstance.createRegisterUrl(
|
keycloakInstance.createRegisterUrl(
|
||||||
options
|
options
|
||||||
)
|
)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return neverResolvingPromise;
|
return neverResolvingPromise;
|
||||||
},
|
},
|
||||||
"accountManagement": () => {
|
"accountManagement": () => {
|
||||||
|
@ -12,9 +12,6 @@ generateKeycloakThemeResources({
|
|||||||
"themeName": "keycloakify-demo-app",
|
"themeName": "keycloakify-demo-app",
|
||||||
"reactAppBuildDirPath": pathJoin(sampleReactProjectDirPath, "build"),
|
"reactAppBuildDirPath": pathJoin(sampleReactProjectDirPath, "build"),
|
||||||
"keycloakThemeBuildingDirPath": pathJoin(sampleReactProjectDirPath, "build_keycloak_theme"),
|
"keycloakThemeBuildingDirPath": pathJoin(sampleReactProjectDirPath, "build_keycloak_theme"),
|
||||||
"mode": {
|
|
||||||
"type": "standalone",
|
|
||||||
"urlPathname": "/keycloakify-demo-app/"
|
"urlPathname": "/keycloakify-demo-app/"
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
replaceImportFromStaticInJsCode,
|
replaceImportsFromStaticInJsCode,
|
||||||
replaceImportFromStaticInCssCode,
|
replaceImportsInCssCode,
|
||||||
generateCssCodeToDefineGlobals
|
generateCssCodeToDefineGlobals
|
||||||
} from "../bin/build-keycloak-theme/replaceImportFromStatic";
|
} from "../bin/build-keycloak-theme/replaceImportFromStatic";
|
||||||
|
|
||||||
const { fixedJsCode } = replaceImportFromStaticInJsCode({
|
const { fixedJsCode } = replaceImportsFromStaticInJsCode({
|
||||||
"ftlValuesGlobalName": "keycloakFtlValues",
|
"ftlValuesGlobalName": "keycloakFtlValues",
|
||||||
"jsCode": `
|
"jsCode": `
|
||||||
function f() {
|
function f() {
|
||||||
@ -19,13 +19,12 @@ const { fixedJsCode } = replaceImportFromStaticInJsCode({
|
|||||||
3: "0664cdc0"
|
3: "0664cdc0"
|
||||||
}[e] + ".chunk.js"
|
}[e] + ".chunk.js"
|
||||||
}
|
}
|
||||||
`,
|
`
|
||||||
"mode": { "type": "standalone" }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log({ fixedJsCode });
|
console.log({ fixedJsCode });
|
||||||
|
|
||||||
const { fixedCssCode, cssGlobalsToDefine } = replaceImportFromStaticInCssCode({
|
const { fixedCssCode, cssGlobalsToDefine } = replaceImportsInCssCode({
|
||||||
"cssCode": `
|
"cssCode": `
|
||||||
|
|
||||||
.my-div {
|
.my-div {
|
||||||
|
16
yarn.lock
16
yarn.lock
@ -747,10 +747,10 @@ path@^0.12.7:
|
|||||||
process "^0.11.1"
|
process "^0.11.1"
|
||||||
util "^0.10.3"
|
util "^0.10.3"
|
||||||
|
|
||||||
powerhooks@^0.0.27:
|
powerhooks@^0.0.32:
|
||||||
version "0.0.27"
|
version "0.0.32"
|
||||||
resolved "https://registry.yarnpkg.com/powerhooks/-/powerhooks-0.0.27.tgz#e9dc29258860d2f6bf32b249d9cba07c6f53f393"
|
resolved "https://registry.yarnpkg.com/powerhooks/-/powerhooks-0.0.32.tgz#a6aa19573b22f38f4f0bb44573c3242116e9eed1"
|
||||||
integrity sha512-ohayWhtIEdLqiC2th/GEhaRfOhqekFg2uFo0JZ8Dn7oTnAZybs618QJeq5ag9oy3lFVzl+kbROpVa8Ch5zrkaA==
|
integrity sha512-atxsb/zcN8O72hqtfz6tv4XLlh4X22+iTO96PPKpa//nrdvX8KTpFoGiUTh+RQ9RONdR4hP/RmfsDu1zPp2G8Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
evt "2.0.0-beta.15"
|
evt "2.0.0-beta.15"
|
||||||
memoizee "^0.4.15"
|
memoizee "^0.4.15"
|
||||||
@ -927,10 +927,10 @@ to-fast-properties@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||||
integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
|
integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
|
||||||
|
|
||||||
tss-react@^0.0.11:
|
tss-react@^0.0.12:
|
||||||
version "0.0.11"
|
version "0.0.12"
|
||||||
resolved "https://registry.yarnpkg.com/tss-react/-/tss-react-0.0.11.tgz#1cd061927744cd4fc9b7346e2fd1cfcf896a18d5"
|
resolved "https://registry.yarnpkg.com/tss-react/-/tss-react-0.0.12.tgz#6463617ae5e7f670742e48e497d8825d59e2a2e9"
|
||||||
integrity sha512-j8CDpHHIl6S6/mX+AmK08v7waPqwgNA7urHOD3qknCgbY79LRlS7he5DF4NUNE/5B4/Btc3F25w+KqgChNbyGw==
|
integrity sha512-oHekukqdaE71uhHx4XEdHy6aMnDYhoHLWB94iy2Fy9X8btH2lJH1joPj0zS1q7+1Xy2TydkLEZsTq3ElVd7ZqA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@emotion/css" "^11.1.3"
|
"@emotion/css" "^11.1.3"
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user