Patch CSS for Keycloak by using relative paths instead of css variables
This commit is contained in:
parent
aba725372e
commit
5423a07c47
@ -1,7 +1,6 @@
|
|||||||
import cheerio from "cheerio";
|
import cheerio from "cheerio";
|
||||||
import { replaceImportsInJsCode } from "../replacers/replaceImportsInJsCode";
|
import { replaceImportsInJsCode } from "../replacers/replaceImportsInJsCode";
|
||||||
import { generateCssCodeToDefineGlobals } from "../replacers/replaceImportsInCssCode";
|
import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode";
|
||||||
import { replaceImportsInInlineCssCode } from "../replacers/replaceImportsInInlineCssCode";
|
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { join as pathJoin } from "path";
|
import { join as pathJoin } from "path";
|
||||||
import type { BuildContext } from "../../shared/buildContext";
|
import type { BuildContext } from "../../shared/buildContext";
|
||||||
@ -28,7 +27,6 @@ assert<BuildContext extends BuildContextLike ? true : false>();
|
|||||||
export function generateFtlFilesCodeFactory(params: {
|
export function generateFtlFilesCodeFactory(params: {
|
||||||
themeName: string;
|
themeName: string;
|
||||||
indexHtmlCode: string;
|
indexHtmlCode: string;
|
||||||
cssGlobalsToDefine: Record<string, string>;
|
|
||||||
buildContext: BuildContextLike;
|
buildContext: BuildContextLike;
|
||||||
keycloakifyVersion: string;
|
keycloakifyVersion: string;
|
||||||
themeType: ThemeType;
|
themeType: ThemeType;
|
||||||
@ -36,7 +34,6 @@ export function generateFtlFilesCodeFactory(params: {
|
|||||||
}) {
|
}) {
|
||||||
const {
|
const {
|
||||||
themeName,
|
themeName,
|
||||||
cssGlobalsToDefine,
|
|
||||||
indexHtmlCode,
|
indexHtmlCode,
|
||||||
buildContext,
|
buildContext,
|
||||||
keycloakifyVersion,
|
keycloakifyVersion,
|
||||||
@ -65,8 +62,9 @@ export function generateFtlFilesCodeFactory(params: {
|
|||||||
|
|
||||||
assert(cssCode !== null);
|
assert(cssCode !== null);
|
||||||
|
|
||||||
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
const { fixedCssCode } = replaceImportsInCssCode({
|
||||||
cssCode,
|
cssCode,
|
||||||
|
fileRelativeDirPath: ".",
|
||||||
buildContext
|
buildContext
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -97,21 +95,6 @@ export function generateFtlFilesCodeFactory(params: {
|
|||||||
);
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
if (Object.keys(cssGlobalsToDefine).length !== 0) {
|
|
||||||
$("head").prepend(
|
|
||||||
[
|
|
||||||
"",
|
|
||||||
"<style>",
|
|
||||||
generateCssCodeToDefineGlobals({
|
|
||||||
cssGlobalsToDefine,
|
|
||||||
buildContext
|
|
||||||
}).cssCodeToPrependInHead,
|
|
||||||
"</style>",
|
|
||||||
""
|
|
||||||
].join("\n")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//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.
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import { transformCodebase } from "../../tools/transformCodebase";
|
import { transformCodebase } from "../../tools/transformCodebase";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { join as pathJoin, resolve as pathResolve, relative as pathRelative } from "path";
|
import {
|
||||||
|
join as pathJoin,
|
||||||
|
resolve as pathResolve,
|
||||||
|
relative as pathRelative,
|
||||||
|
dirname as pathDirname
|
||||||
|
} from "path";
|
||||||
import { replaceImportsInJsCode } from "../replacers/replaceImportsInJsCode";
|
import { replaceImportsInJsCode } from "../replacers/replaceImportsInJsCode";
|
||||||
import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode";
|
import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode";
|
||||||
import {
|
import {
|
||||||
@ -64,8 +69,6 @@ export async function generateResourcesForMainTheme(params: {
|
|||||||
return pathJoin(resourcesDirPath, "theme", themeName, themeType);
|
return pathJoin(resourcesDirPath, "theme", themeName, themeType);
|
||||||
};
|
};
|
||||||
|
|
||||||
const cssGlobalsToDefine: Record<string, string> = {};
|
|
||||||
|
|
||||||
for (const themeType of ["login", "account"] as const) {
|
for (const themeType of ["login", "account"] as const) {
|
||||||
if (!buildContext.recordIsImplementedByThemeType[themeType]) {
|
if (!buildContext.recordIsImplementedByThemeType[themeType]) {
|
||||||
continue;
|
continue;
|
||||||
@ -127,21 +130,14 @@ export async function generateResourcesForMainTheme(params: {
|
|||||||
transformCodebase({
|
transformCodebase({
|
||||||
srcDirPath: buildContext.projectBuildDirPath,
|
srcDirPath: buildContext.projectBuildDirPath,
|
||||||
destDirPath,
|
destDirPath,
|
||||||
transformSourceCode: ({ filePath, sourceCode }) => {
|
transformSourceCode: ({ filePath, fileRelativePath, sourceCode }) => {
|
||||||
if (filePath.endsWith(".css")) {
|
if (filePath.endsWith(".css")) {
|
||||||
const {
|
const { fixedCssCode } = replaceImportsInCssCode({
|
||||||
cssGlobalsToDefine: cssGlobalsToDefineForThisFile,
|
cssCode: sourceCode.toString("utf8"),
|
||||||
fixedCssCode
|
fileRelativeDirPath: pathDirname(fileRelativePath),
|
||||||
} = replaceImportsInCssCode({
|
buildContext
|
||||||
cssCode: sourceCode.toString("utf8")
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.entries(cssGlobalsToDefineForThisFile).forEach(
|
|
||||||
([key, value]) => {
|
|
||||||
cssGlobalsToDefine[key] = value;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
modifiedSourceCode: Buffer.from(fixedCssCode, "utf8")
|
modifiedSourceCode: Buffer.from(fixedCssCode, "utf8")
|
||||||
};
|
};
|
||||||
@ -168,7 +164,6 @@ export async function generateResourcesForMainTheme(params: {
|
|||||||
indexHtmlCode: fs
|
indexHtmlCode: fs
|
||||||
.readFileSync(pathJoin(buildContext.projectBuildDirPath, "index.html"))
|
.readFileSync(pathJoin(buildContext.projectBuildDirPath, "index.html"))
|
||||||
.toString("utf8"),
|
.toString("utf8"),
|
||||||
cssGlobalsToDefine,
|
|
||||||
buildContext,
|
buildContext,
|
||||||
keycloakifyVersion: readThisNpmPackageVersion(),
|
keycloakifyVersion: readThisNpmPackageVersion(),
|
||||||
themeType,
|
themeType,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import * as crypto from "crypto";
|
|
||||||
import type { BuildContext } from "../../shared/buildContext";
|
import type { BuildContext } from "../../shared/buildContext";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import { basenameOfTheKeycloakifyResourcesDir } from "../../shared/constants";
|
import { posix } from "path";
|
||||||
|
|
||||||
export type BuildContextLike = {
|
export type BuildContextLike = {
|
||||||
urlPathname: string | undefined;
|
urlPathname: string | undefined;
|
||||||
@ -9,68 +8,37 @@ export type BuildContextLike = {
|
|||||||
|
|
||||||
assert<BuildContext extends BuildContextLike ? true : false>();
|
assert<BuildContext extends BuildContextLike ? true : false>();
|
||||||
|
|
||||||
export function replaceImportsInCssCode(params: { cssCode: string }): {
|
export function replaceImportsInCssCode(params: {
|
||||||
fixedCssCode: string;
|
cssCode: string;
|
||||||
cssGlobalsToDefine: Record<string, string>;
|
fileRelativeDirPath: string;
|
||||||
} {
|
|
||||||
const { cssCode } = params;
|
|
||||||
|
|
||||||
const cssGlobalsToDefine: Record<string, string> = {};
|
|
||||||
|
|
||||||
new Set(cssCode.match(/url\(["']?\/[^/][^)"']+["']?\)[^;}]*?/g) ?? []).forEach(
|
|
||||||
match =>
|
|
||||||
(cssGlobalsToDefine[
|
|
||||||
"url" +
|
|
||||||
crypto
|
|
||||||
.createHash("sha256")
|
|
||||||
.update(match)
|
|
||||||
.digest("hex")
|
|
||||||
.substring(0, 15)
|
|
||||||
] = match)
|
|
||||||
);
|
|
||||||
|
|
||||||
let fixedCssCode = cssCode;
|
|
||||||
|
|
||||||
Object.keys(cssGlobalsToDefine).forEach(
|
|
||||||
cssVariableName =>
|
|
||||||
//NOTE: split/join pattern ~ replace all
|
|
||||||
(fixedCssCode = fixedCssCode
|
|
||||||
.split(cssGlobalsToDefine[cssVariableName])
|
|
||||||
.join(`var(--${cssVariableName})`))
|
|
||||||
);
|
|
||||||
|
|
||||||
return { fixedCssCode, cssGlobalsToDefine };
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateCssCodeToDefineGlobals(params: {
|
|
||||||
cssGlobalsToDefine: Record<string, string>;
|
|
||||||
buildContext: BuildContextLike;
|
buildContext: BuildContextLike;
|
||||||
}): {
|
}): {
|
||||||
cssCodeToPrependInHead: string;
|
fixedCssCode: string;
|
||||||
} {
|
} {
|
||||||
const { cssGlobalsToDefine, buildContext } = params;
|
const { cssCode, fileRelativeDirPath, buildContext } = params;
|
||||||
|
|
||||||
return {
|
const fixedCssCode = cssCode.replace(
|
||||||
cssCodeToPrependInHead: [
|
/url\(["']?(\/[^/][^)"']+)["']?\)/g,
|
||||||
":root {",
|
(match, assetFileAbsoluteUrlPathname) => {
|
||||||
...Object.keys(cssGlobalsToDefine)
|
if (buildContext.urlPathname !== undefined) {
|
||||||
.map(cssVariableName =>
|
if (!assetFileAbsoluteUrlPathname.startsWith(buildContext.urlPathname)) {
|
||||||
[
|
// NOTE: Should never happen
|
||||||
`--${cssVariableName}:`,
|
return match;
|
||||||
cssGlobalsToDefine[cssVariableName].replace(
|
}
|
||||||
new RegExp(
|
assetFileAbsoluteUrlPathname = assetFileAbsoluteUrlPathname.replace(
|
||||||
`url\\(${(buildContext.urlPathname ?? "/").replace(
|
buildContext.urlPathname,
|
||||||
/\//g,
|
"/"
|
||||||
"\\/"
|
);
|
||||||
)}`,
|
}
|
||||||
"g"
|
|
||||||
),
|
const assetFileRelativeUrlPathname = posix.relative(
|
||||||
`url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/`
|
fileRelativeDirPath.replace(/\\/g, "/"),
|
||||||
)
|
assetFileAbsoluteUrlPathname.replace(/^\//, "")
|
||||||
].join(" ")
|
);
|
||||||
)
|
|
||||||
.map(line => ` ${line};`),
|
return `url(${assetFileRelativeUrlPathname})`;
|
||||||
"}"
|
}
|
||||||
].join("\n")
|
);
|
||||||
};
|
|
||||||
|
return { fixedCssCode };
|
||||||
}
|
}
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
import type { BuildContext } from "../../shared/buildContext";
|
|
||||||
import { assert } from "tsafe/assert";
|
|
||||||
import { basenameOfTheKeycloakifyResourcesDir } from "../../shared/constants";
|
|
||||||
|
|
||||||
export type BuildContextLike = {
|
|
||||||
urlPathname: string | undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
assert<BuildContext extends BuildContextLike ? true : false>();
|
|
||||||
|
|
||||||
export function replaceImportsInInlineCssCode(params: {
|
|
||||||
cssCode: string;
|
|
||||||
buildContext: BuildContextLike;
|
|
||||||
}): {
|
|
||||||
fixedCssCode: string;
|
|
||||||
} {
|
|
||||||
const { cssCode, buildContext } = params;
|
|
||||||
|
|
||||||
const fixedCssCode = cssCode.replace(
|
|
||||||
buildContext.urlPathname === undefined
|
|
||||||
? /url\(["']?\/([^/][^)"']+)["']?\)/g
|
|
||||||
: new RegExp(`url\\(["']?${buildContext.urlPathname}([^)"']+)["']?\\)`, "g"),
|
|
||||||
(...[, group]) =>
|
|
||||||
`url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/${group})`
|
|
||||||
);
|
|
||||||
|
|
||||||
return { fixedCssCode };
|
|
||||||
}
|
|
@ -1,11 +1,6 @@
|
|||||||
import { replaceImportsInJsCode_vite } from "keycloakify/bin/keycloakify/replacers/replaceImportsInJsCode/vite";
|
import { replaceImportsInJsCode_vite } from "keycloakify/bin/keycloakify/replacers/replaceImportsInJsCode/vite";
|
||||||
import { replaceImportsInJsCode_webpack } from "keycloakify/bin/keycloakify/replacers/replaceImportsInJsCode/webpack";
|
import { replaceImportsInJsCode_webpack } from "keycloakify/bin/keycloakify/replacers/replaceImportsInJsCode/webpack";
|
||||||
import {
|
import { replaceImportsInCssCode } from "keycloakify/bin/keycloakify/replacers/replaceImportsInCssCode";
|
||||||
generateCssCodeToDefineGlobals,
|
|
||||||
replaceImportsInCssCode
|
|
||||||
} from "keycloakify/bin/keycloakify/replacers/replaceImportsInCssCode";
|
|
||||||
import { replaceImportsInInlineCssCode } from "keycloakify/bin/keycloakify/replacers/replaceImportsInInlineCssCode";
|
|
||||||
import { same } from "evt/tools/inDepth/same";
|
|
||||||
import { expect, it, describe } from "vitest";
|
import { expect, it, describe } from "vitest";
|
||||||
import { basenameOfTheKeycloakifyResourcesDir } from "keycloakify/bin/shared/constants";
|
import { basenameOfTheKeycloakifyResourcesDir } from "keycloakify/bin/shared/constants";
|
||||||
|
|
||||||
@ -385,279 +380,80 @@ describe("js replacer - webpack", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("css replacer", () => {
|
describe("css replacer", () => {
|
||||||
it("transforms absolute urls to css globals properly with no urlPathname", () => {
|
it("replaceImportsInCssCode - 1", () => {
|
||||||
const { fixedCssCode, cssGlobalsToDefine } = replaceImportsInCssCode({
|
const { fixedCssCode } = replaceImportsInCssCode({
|
||||||
cssCode: `
|
cssCode: `
|
||||||
.my-div {
|
.my-div {
|
||||||
background: url(/logo192.png) no-repeat center center;
|
background: url(/background.png) no-repeat center center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-div2 {
|
.my-div2 {
|
||||||
background: url(/logo192.png) repeat center center;
|
background: url(/assets/background.png) repeat center center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-div {
|
.my-div3 {
|
||||||
background-image: url(/static/media/something.svg);
|
background-image: url(/assets/media/something.svg);
|
||||||
}
|
}
|
||||||
`
|
`,
|
||||||
});
|
fileRelativeDirPath: "assets/",
|
||||||
|
|
||||||
const fixedCssCodeExpected = `
|
|
||||||
.my-div {
|
|
||||||
background: var(--urla882a969fd39473) no-repeat center center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.my-div2 {
|
|
||||||
background: var(--urla882a969fd39473) repeat center center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.my-div {
|
|
||||||
background-image: var(--urldd75cab58377c19);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
|
||||||
|
|
||||||
const cssGlobalsToDefineExpected = {
|
|
||||||
urla882a969fd39473: "url(/logo192.png)",
|
|
||||||
urldd75cab58377c19: "url(/static/media/something.svg)"
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(same(cssGlobalsToDefine, cssGlobalsToDefineExpected)).toBe(true);
|
|
||||||
|
|
||||||
const { cssCodeToPrependInHead } = generateCssCodeToDefineGlobals({
|
|
||||||
cssGlobalsToDefine,
|
|
||||||
buildContext: {
|
buildContext: {
|
||||||
urlPathname: undefined
|
urlPathname: undefined
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const cssCodeToPrependInHeadExpected = `
|
|
||||||
:root {
|
|
||||||
--urla882a969fd39473: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/logo192.png);
|
|
||||||
--urldd75cab58377c19: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/static/media/something.svg);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
expect(isSameCode(cssCodeToPrependInHead, cssCodeToPrependInHeadExpected)).toBe(
|
|
||||||
true
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it("transforms absolute urls to css globals properly with custom urlPathname", () => {
|
|
||||||
const { fixedCssCode, cssGlobalsToDefine } = replaceImportsInCssCode({
|
|
||||||
cssCode: `
|
|
||||||
.my-div {
|
|
||||||
background: url(/x/y/z/logo192.png) no-repeat center center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.my-div2 {
|
|
||||||
background: url(/x/y/z/logo192.png) no-repeat center center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.my-div {
|
|
||||||
background-image: url(/x/y/z/static/media/something.svg);
|
|
||||||
}
|
|
||||||
`
|
|
||||||
});
|
|
||||||
|
|
||||||
const fixedCssCodeExpected = `
|
const fixedCssCodeExpected = `
|
||||||
.my-div {
|
.my-div {
|
||||||
background: var(--url749a3139386b2c8) no-repeat center center;
|
background: url(../background.png) no-repeat center center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-div2 {
|
.my-div2 {
|
||||||
background: var(--url749a3139386b2c8) no-repeat center center;
|
background: url(background.png) repeat center center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-div {
|
.my-div3 {
|
||||||
background-image: var(--url8bdc0887b97ac9a);
|
background-image: url(media/something.svg);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
const cssGlobalsToDefineExpected = {
|
it("replaceImportsInCssCode - 2", () => {
|
||||||
url749a3139386b2c8: "url(/x/y/z/logo192.png)",
|
const { fixedCssCode } = replaceImportsInCssCode({
|
||||||
url8bdc0887b97ac9a: "url(/x/y/z/static/media/something.svg)"
|
cssCode: `
|
||||||
};
|
.my-div {
|
||||||
|
background: url(/a/b/background.png) no-repeat center center;
|
||||||
expect(same(cssGlobalsToDefine, cssGlobalsToDefineExpected)).toBe(true);
|
}
|
||||||
|
|
||||||
const { cssCodeToPrependInHead } = generateCssCodeToDefineGlobals({
|
.my-div2 {
|
||||||
cssGlobalsToDefine,
|
background: url(/a/b/assets/background.png) repeat center center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-div3 {
|
||||||
|
background-image: url(/a/b/assets/media/something.svg);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
fileRelativeDirPath: "assets/",
|
||||||
buildContext: {
|
buildContext: {
|
||||||
urlPathname: "/x/y/z/"
|
urlPathname: "/a/b/"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const cssCodeToPrependInHeadExpected = `
|
const fixedCssCodeExpected = `
|
||||||
:root {
|
.my-div {
|
||||||
--url749a3139386b2c8: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/logo192.png);
|
background: url(../background.png) no-repeat center center;
|
||||||
--url8bdc0887b97ac9a: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/static/media/something.svg);
|
}
|
||||||
|
|
||||||
|
.my-div2 {
|
||||||
|
background: url(background.png) repeat center center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-div3 {
|
||||||
|
background-image: url(media/something.svg);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
expect(isSameCode(cssCodeToPrependInHead, cssCodeToPrependInHeadExpected)).toBe(
|
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
||||||
true
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("inline css replacer", () => {
|
|
||||||
describe("no url pathName", () => {
|
|
||||||
const cssCode = `
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: url("/fonts/WorkSans/worksans-regular-webfont.woff2") format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
font-display: swap;
|
|
||||||
src: url("/fonts/WorkSans/worksans-medium-webfont.woff2") format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 600;
|
|
||||||
font-display: swap;
|
|
||||||
src: url("/fonts/WorkSans/worksans-semibold-webfont.woff2") format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 700;
|
|
||||||
font-display: swap;
|
|
||||||
src: url("/fonts/WorkSans/worksans-bold-webfont.woff2") format("woff2");
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
it("transforms css for standalone app properly", () => {
|
|
||||||
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
|
||||||
cssCode,
|
|
||||||
buildContext: {
|
|
||||||
urlPathname: undefined
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const fixedCssCodeExpected = `
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/fonts/WorkSans/worksans-regular-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/fonts/WorkSans/worksans-medium-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 600;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/fonts/WorkSans/worksans-semibold-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 700;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/fonts/WorkSans/worksans-bold-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("with url pathName", () => {
|
|
||||||
const cssCode = `
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: url("/x/y/z/fonts/WorkSans/worksans-regular-webfont.woff2") format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
font-display: swap;
|
|
||||||
src: url("/x/y/z/fonts/WorkSans/worksans-medium-webfont.woff2") format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 600;
|
|
||||||
font-display: swap;
|
|
||||||
src: url("/x/y/z/fonts/WorkSans/worksans-semibold-webfont.woff2") format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 700;
|
|
||||||
font-display: swap;
|
|
||||||
src: url("/x/y/z/fonts/WorkSans/worksans-bold-webfont.woff2") format("woff2");
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
it("transforms css for standalone app properly", () => {
|
|
||||||
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
|
||||||
cssCode,
|
|
||||||
buildContext: {
|
|
||||||
urlPathname: "/x/y/z/"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const fixedCssCodeExpected = `
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/fonts/WorkSans/worksans-regular-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/fonts/WorkSans/worksans-medium-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 600;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/fonts/WorkSans/worksans-semibold-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 700;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(\${url.resourcesPath}/${basenameOfTheKeycloakifyResourcesDir}/fonts/WorkSans/worksans-bold-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user