From afd004bef1db824bdd95e945273107a96b33880f Mon Sep 17 00:00:00 2001 From: huoxin <23447157+huoxin233@users.noreply.github.com> Date: Sun, 17 May 2026 02:18:42 +0800 Subject: [PATCH] fix: correct backslash escaping in PHP namespaces --- src/boilersmith/scaffolding/module.ts | 14 ++++++++------ src/steps/gen-ext-scaffolder.ts | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/boilersmith/scaffolding/module.ts b/src/boilersmith/scaffolding/module.ts index 3e49f73..393fb3f 100644 --- a/src/boilersmith/scaffolding/module.ts +++ b/src/boilersmith/scaffolding/module.ts @@ -225,11 +225,6 @@ export async function applyModule( string >; - // This is necessary because one layer of escaped backslashes is lost on template population. - tplData.params = Object.fromEntries(Object.entries(paramVals).map(([k, v]) => [k, typeof v === 'string' ? v.replace('\\', '\\\\') : v])) as Record< - TN, - unknown - >; for (const file of module.filesToReplace) { const path = typeof file === 'string' ? file : file.path; @@ -270,8 +265,15 @@ export async function applyModule( } const jsonPaths = cloneAndFill(module.jsonToAugment, tplDataFlat); + + // This is necessary because one layer of escaped backslashes is lost on template population. + const clonedTplData = { ...tplData }; + clonedTplData.params = Object.fromEntries( + Object.entries(paramVals).map(([k, v]) => [k, typeof v === 'string' ? v.replace('\\', '\\\\') : v]) + ) as Record; + for (const jsonPath of Object.keys(jsonPaths)) { - const scaffoldContents = readTpl(resolve(scaffoldDir, jsonPath), tplData); + const scaffoldContents = readTpl(resolve(scaffoldDir, jsonPath), clonedTplData); const scaffoldContentsJson = JSON.parse(scaffoldContents); const excludeKeys = cloneAndFill(excludeScaffolding.configKeys[jsonPath] ?? [], tplDataFlat); diff --git a/src/steps/gen-ext-scaffolder.ts b/src/steps/gen-ext-scaffolder.ts index 45ad667..0169a71 100644 --- a/src/steps/gen-ext-scaffolder.ts +++ b/src/steps/gen-ext-scaffolder.ts @@ -11,6 +11,7 @@ import { resolve } from 'path'; import simpleGit from 'simple-git'; import spdxLicenseListSimple from 'spdx-license-list/simple'; import { getComposerJson } from '../utils/composer'; +import s from 'string'; function assertUnreachable(_x: never): never { throw new Error("Didn't expect to get here"); @@ -75,6 +76,13 @@ function paramNamesToDef(name: ExtensionParams): TemplateParam + (values as unknown as Map) + .get('packageName')! + .replace('/flarum-', '/') + .split('/') + .map((b: string) => s(b).camelize().capitalize().toString()) + .join('\\'), validate: (s) => /^([\dA-Za-z]+)\\([\dA-Za-z]+)$/.test(s.trim()) || 'Invalid namespace format', format: (str: string) => str && @@ -86,7 +94,7 @@ function paramNamesToDef(name: ExtensionParams): TemplateParam { const json = getComposerJson(fs, paths); const namespace = (Object.keys(json?.autoload?.['psr-4'] ?? {})?.[0] ?? '')?.slice(0, -1); - return namespace || ''; + return (namespace || '').replace('\\\\', '\\'); }, }; @@ -124,6 +132,12 @@ function paramNamesToDef(name: ExtensionParams): TemplateParam Boolean(str.trim()) || 'The extension name is required', + initial: (_prev, values) => + s((values as unknown as Map).get('packageName')!.split('/')[1]) + .replaceAll('flarum-', '') + .humanize() + .capitalize() + .toString(), format: (str) => str .split(' ')