diff --git a/src/context/directory/handlers/branding.ts b/src/context/directory/handlers/branding.ts index 35e4148d7..aca4408f9 100644 --- a/src/context/directory/handlers/branding.ts +++ b/src/context/directory/handlers/branding.ts @@ -1,7 +1,7 @@ import path from 'path'; import fs from 'fs-extra'; import { constants, loadFileAndReplaceKeywords } from '../../../tools'; -import { dumpJSON, existsMustBeDir, getFiles, isFile, loadJSON } from '../../../utils'; +import { dumpJSON, existsMustBeDir, getFiles, isFile, loadJSON, nomalizedYAMLPath } from '../../../utils'; import { DirectoryHandler } from '.'; import DirectoryContext from '..'; import { Asset, ParsedAsset } from '../../../types'; @@ -38,8 +38,10 @@ function parse(context: DirectoryContext): ParsedBranding { mappings: context.mappings, disableKeywordReplacement: context.disableKeywordReplacement, }); + + const normalizedPathArray = nomalizedYAMLPath(definition.body); definition.body = loadFileAndReplaceKeywords( - path.join(brandingTemplatesFolder, definition.body), + path.join(brandingTemplatesFolder, ...normalizedPathArray), { mappings: context.mappings, disableKeywordReplacement: context.disableKeywordReplacement, @@ -94,7 +96,7 @@ const dumpBrandingTemplates = ({ filePath, assets }: DirectoryContext): void => } // save the location as relative file. - templateDefinition.body = `.${path.sep}${templateDefinition.template}.html`; + templateDefinition.body = `./${templateDefinition.template}.html`; dumpJSON( path.join(brandingTemplatesFolder, `${templateDefinition.template}.json`), templateDefinition diff --git a/src/context/yaml/handlers/branding.ts b/src/context/yaml/handlers/branding.ts index 109a86c43..a1f6e74a1 100644 --- a/src/context/yaml/handlers/branding.ts +++ b/src/context/yaml/handlers/branding.ts @@ -6,6 +6,7 @@ import { YAMLHandler } from '.'; import YAMLContext from '..'; import { Asset, ParsedAsset } from '../../../types'; import log from '../../../logger'; +import { nomalizedYAMLPath } from '../../../utils'; type BrandingTemplate = { template: string; @@ -32,12 +33,8 @@ async function parse(context: YAMLContext): Promise { const parsedTemplates: BrandingTemplate[] = templates.map( (templateDefinition: BrandingTemplate): BrandingTemplate => { - const brandingTemplatesFolder = path.join( - context.basePath, - constants.BRANDING_TEMPLATES_YAML_DIRECTORY - ); - const file = `${templateDefinition.template}.html`; - const markupFile = path.join(brandingTemplatesFolder, file); + const normalizedPathArray = nomalizedYAMLPath(templateDefinition.body); + const markupFile = path.join(context.basePath, ...normalizedPathArray); return { template: templateDefinition.template, body: loadFileAndReplaceKeywords(markupFile, { diff --git a/src/utils.ts b/src/utils.ts index 46e254242..97561159b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -205,3 +205,29 @@ export function mapClientID2NameSorted(enabledClients: string[], knownClients: A ...(enabledClients || []).map((clientId) => convertClientIdToName(clientId, knownClients)), ].sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); } + +export function nomalizedYAMLPath(filePath: string): string[] { + // Trim any leading or trailing whitespace + filePath = filePath.trim(); + + // Handle empty path cases + if (filePath === '') { + return []; + } + + // Normalize the path by replacing backslashes with forward slashes + const normalizedPath = filePath.replace(/\\/g, '/'); + + // Split the path using the forward slash as the separator + let pathSplit = normalizedPath.split('/'); + + // Remove empty components resulting from leading or redundant slashes + pathSplit = pathSplit.filter(component => component !== ''); + + // Remove the first '.' if it's the first component + if (pathSplit.length > 0 && pathSplit[0] === '.') { + pathSplit.shift(); + } + + return pathSplit; +} diff --git a/test/context/yaml/branding.test.js b/test/context/yaml/branding.test.js index 3e0e793f9..62b438d09 100644 --- a/test/context/yaml/branding.test.js +++ b/test/context/yaml/branding.test.js @@ -34,7 +34,6 @@ describe('#YAML context branding templates', () => { const config = { AUTH0_INPUT_FILE: yamlFile, AUTH0_KEYWORD_REPLACE_MAPPINGS: { foo: 'bar' } }; const context = new Context(config, mockMgmtClient()); - context.basePath = baseDir; await context.loadAssetsFromLocal(); expect(context.assets.branding).to.deep.equal({ colors: {