diff --git a/package.json b/package.json index 64a4dd0a..8264f908 100755 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "grant-exec-perms": "node dist/bin/tools/grant-exec-perms.js", "test": "node dist/test", "enable_short_import_path": "yarn build && denoify_enable_short_npm_import_path", - "copy-files": "copyfiles -u 1 src/**/*.ftl src/**/*.xml dist/", + "copy-files": "copyfiles -u 1 src/**/*.ftl src/**/*.xml src/**/*.js dist/", "generate-messages": "node dist/bin/generate-i18n-messages.js", "watch": "tsc -w" }, @@ -52,11 +52,11 @@ "typescript": "^4.1.5" }, "dependencies": { - "scripting-tools": "^0.19.13", "cheerio": "^1.0.0-rc.5", "evt": "2.0.0-beta.15", "minimal-polyfills": "^2.1.6", - "powerhooks": "^0.0.17", + "powerhooks": "^0.0.19", + "scripting-tools": "^0.19.13", "tss-react": "^0.0.11" } } diff --git a/src/bin/build-keycloak-theme/generateFtl/Object.deepAssign.js b/src/bin/build-keycloak-theme/generateFtl/Object.deepAssign.js new file mode 100644 index 00000000..028d9990 --- /dev/null +++ b/src/bin/build-keycloak-theme/generateFtl/Object.deepAssign.js @@ -0,0 +1,28 @@ + +Object.defineProperty( + Object, + "deepAssign", + { + "value": function callee(target, source) { + Object.keys(source).forEach(function (key) { + var value = source[key]; + if (target[key] === undefined) { + target[key] = value; + return; + } + if (value instanceof Object) { + if (value instanceof Array) { + value.forEach(function (entry) { + target[key].push(entry); + }); + return; + } + callee(target[key], value); + return; + } + target[key] = value; + }); + return target; + } + } +); \ No newline at end of file diff --git a/src/bin/build-keycloak-theme/generateFtl/String.htmlUnescape.js b/src/bin/build-keycloak-theme/generateFtl/String.htmlUnescape.js new file mode 100644 index 00000000..1b54857b --- /dev/null +++ b/src/bin/build-keycloak-theme/generateFtl/String.htmlUnescape.js @@ -0,0 +1,26 @@ + +var es = /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34);/g; + +var unes = { + '&': '&', + '&': '&', + '<': '<', + '<': '<', + '>': '>', + '>': '>', + ''': "'", + ''': "'", + '"': '"', + '"': '"' +}; +var cape = function (m) { return unes[m]; }; + +Object.defineProperty( + String, + "htmlUnescape", + { + "value": function (un) { + return String.prototype.replace.call(un, es, cape); + } + } +); diff --git a/src/bin/build-keycloak-theme/generateFtl/index.ts b/src/bin/build-keycloak-theme/generateFtl/index.ts index b6155351..691905b7 100644 --- a/src/bin/build-keycloak-theme/generateFtl/index.ts +++ b/src/bin/build-keycloak-theme/generateFtl/index.ts @@ -9,15 +9,20 @@ import fs from "fs"; import { join as pathJoin } from "path"; import { objectKeys } from "evt/tools/typeSafety/objectKeys"; -export type PageId = "login.ftl" | "register.ftl" | "info.ftl" | "error.ftl"; +export const pageIds= [ "login.ftl", "register.ftl", "info.ftl", "error.ftl"] as const; + +export type PageId = typeof pageIds[number]; + +function loadAdjacentFile(fileBasename: string){ + return fs.readFileSync(pathJoin(__dirname, fileBasename)) + .toString("utf8"); +}; function loadFtlFile(ftlFileBasename: PageId | "template.ftl") { - return fs.readFileSync(pathJoin(__dirname, ftlFileBasename)) - .toString("utf8") + return loadAdjacentFile(ftlFileBasename) .match(/^', ' ', - '', + '' ].join("\n") }; + const pageSpecificCodePlaceholder = ""; + $("head").prepend( [ ...(Object.keys(cssGlobalsToDefine).length === 0 ? [] : [ @@ -83,19 +89,26 @@ export function generateFtlFilesCodeFactory( '', '' ]), + ...["Object.deepAssign.js", "String.htmlUnescape.js"].map( + fileBasename => [ + "" + ].join("\n") + ), '', '', - objectKeys(ftlCommonPlaceholders)[1], - '' + pageSpecificCodePlaceholder, + '', + objectKeys(ftlCommonPlaceholders)[1] ].join("\n"), ); - const partiallyFixedIndexHtmlCode = $.html(); function generateFtlFilesCode( @@ -113,50 +126,22 @@ export function generateFtlFilesCodeFactory( ...ftlCommonPlaceholders }; - $("head").prepend( - [ - '', - '', - '' - ].join("\n") - ); - - let ftlCode = $.html(); + let ftlCode = $.html() + .replace( + pageSpecificCodePlaceholder, + [ + '' + ].join("\n") + ); objectKeys(ftlPlaceholders) .forEach(id => ftlCode = ftlCode.replace(id, ftlPlaceholders[id])); diff --git a/src/bin/build-keycloak-theme/generateFtl/template.ftl b/src/bin/build-keycloak-theme/generateFtl/template.ftl index bcc55957..05a0296c 100644 --- a/src/bin/build-keycloak-theme/generateFtl/template.ftl +++ b/src/bin/build-keycloak-theme/generateFtl/template.ftl @@ -94,7 +94,7 @@ return {  "type": "${message.type}", - "summary": "${kcSanitize(message.summary)?no_esc}" + "summary": String.htmlUnescape("${message.summary}") }; diff --git a/src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts b/src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts index e46bde13..3a7168aa 100644 --- a/src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts +++ b/src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts @@ -6,7 +6,7 @@ import { replaceImportFromStaticInCssCode, replaceImportFromStaticInJsCode } from "./replaceImportFromStatic"; -import { generateFtlFilesCodeFactory } from "./generateFtl"; +import { generateFtlFilesCodeFactory, pageIds } from "./generateFtl"; import { builtinThemesUrl } from "../install-builtin-keycloak-themes"; import { downloadAndUnzip } from "../tools/downloadAndUnzip"; import * as child_process from "child_process"; @@ -70,14 +70,14 @@ export function generateKeycloakThemeResources( ).toString("utf8") }); - (["login.ftl", "register.ftl"] as const).forEach(pageId => { + pageIds.forEach(pageId => { const { ftlCode } = generateFtlFilesCode({ pageId }); fs.writeFileSync( pathJoin(themeDirPath, pageId), Buffer.from(ftlCode, "utf8") - ) + ); }); diff --git a/yarn.lock b/yarn.lock index dbf79257..5b6251e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -708,6 +708,11 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +html-escaper@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-3.0.3.tgz#4d336674652beb1dcbc29ef6b6ba7f6be6fdfed6" + integrity sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ== + htmlparser2@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.0.0.tgz#c2da005030390908ca4c91e5629e418e0665ac01" @@ -932,10 +937,10 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -powerhooks@^0.0.17: - version "0.0.17" - resolved "https://registry.yarnpkg.com/powerhooks/-/powerhooks-0.0.17.tgz#840295271d989c27b83047fad44973434c509ba7" - integrity sha512-9z0C5pnVJI3SRKgcoAjbOxVa1lf/e58N+YdByThue1C4DUqfp8umx9XvrRJJ3dGwl6A0RRrJlyPM1KXjVChQMQ== +powerhooks@^0.0.19: + version "0.0.19" + resolved "https://registry.yarnpkg.com/powerhooks/-/powerhooks-0.0.19.tgz#86f4157dbde32cd44082c756ab747c64f6045449" + integrity sha512-yaODFWkflrZCSz4lvRQ2O4AjolheiE6oXa1F4mny2LUOwai4ip+zer16fgXEM53R+IiDnqj6ff8wooU5x4GslQ== dependencies: evt "2.0.0-beta.13" memoizee "^0.4.15"