diff --git a/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts b/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts index 178c4657aef..a78509c49a1 100644 --- a/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts +++ b/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts @@ -161,18 +161,76 @@ export default class SquirrelWindowsTarget extends Target { fs.copyFileSync(path.join(vendorDirectory, `7z-${resolvedArch}.dll`), path.join(vendorDirectory, "7z.dll")) } - private async createNuspecTemplateWithProjectUrl() { + private async createNuspecTemplateWithProjectUrl(additionalFiles: { src: string; target: string }[]) { const templatePath = path.resolve(__dirname, "..", "template.nuspectemplate") const projectUrl = await this.packager.appInfo.computePackageUrl() + + // Always create a customized template to include additionalFiles + const nuspecTemplate = await this.packager.info.tempDirManager.getTempFile({ prefix: "template", suffix: ".nuspectemplate" }) + let templateContent = await fs.promises.readFile(templatePath, "utf8") + + // Add project URL if available if (projectUrl != null) { - const nuspecTemplate = await this.packager.info.tempDirManager.getTempFile({ prefix: "template", suffix: ".nuspectemplate" }) - let templateContent = await fs.promises.readFile(templatePath, "utf8") const searchString = "<%- copyright %>" templateContent = templateContent.replace(searchString, `${searchString}\n ${projectUrl}`) - await fs.promises.writeFile(nuspecTemplate, templateContent) - return nuspecTemplate } - return templatePath + + // Replace the additionalFiles loop with the actual files + if (additionalFiles.length > 0) { + const additionalFilesContent = additionalFiles.map(f => ` `).join("\n") + templateContent = templateContent.replace('<% file src="additionalFiles.src" target="additionalFiles.target" / %>', additionalFilesContent) + } else { + templateContent = templateContent.replace('<% file src="additionalFiles.src" target="additionalFiles.target" / %>', "") + } + + await fs.promises.writeFile(nuspecTemplate, templateContent) + return nuspecTemplate + } + + private async getAdditionalFiles(appOutDir: string) { + const files = await fs.promises.readdir(appOutDir, { withFileTypes: true }) + const appExe = `${this.exeName}.exe` + + const additionalFiles = files.filter(f => { + if (f.isDirectory()) { + // Filter out directories already included in template + return f.name !== "resources" && f.name !== "locales" + } + + // Filter out files already included in template.nuspectemplate + const fileName = f.name + + // Files explicitly included in template + if ( + fileName.endsWith(".bin") || + fileName.endsWith(".dll") || + fileName.endsWith(".pak") || + fileName.endsWith(".exe.config") || + fileName.endsWith(".exe.sig") || + fileName.endsWith("_ExecutionStub.exe") || + fileName === "icudtl.dat" || + fileName === "Squirrel.exe" || + fileName === "LICENSE.electron.txt" || + fileName === "LICENSES.chromium.html" || + fileName === appExe + ) { + return false + } + return true + }) + + return additionalFiles.map(f => { + if (f.isDirectory()) { + return { + src: `${f.name}\\**`, + target: `lib\\net45\\${f.name}`, + } + } + return { + src: f.name, + target: `lib\\net45\\${f.name}`, + } + }) } async computeEffectiveDistOptions(appDirectory: string, outputDirectory: string, setupFile: string): Promise { @@ -189,6 +247,7 @@ export default class SquirrelWindowsTarget extends Target { } } + const additionalFiles = await this.getAdditionalFiles(appDirectory) checkConflictingOptions(this.options) const appInfo = packager.appInfo const options: SquirrelOptions = { @@ -200,7 +259,7 @@ export default class SquirrelWindowsTarget extends Target { description: appInfo.description, exe: `${appInfo.productFilename || this.options.name || appInfo.productName}.exe`, authors: appInfo.companyName || "", - nuspecTemplate: await this.createNuspecTemplateWithProjectUrl(), + nuspecTemplate: await this.createNuspecTemplateWithProjectUrl(additionalFiles), iconUrl, copyright: appInfo.copyright, noMsi: !this.options.msi, diff --git a/packages/electron-builder-squirrel-windows/template.nuspectemplate b/packages/electron-builder-squirrel-windows/template.nuspectemplate index 688a369d20d..f7442db51a3 100644 --- a/packages/electron-builder-squirrel-windows/template.nuspectemplate +++ b/packages/electron-builder-squirrel-windows/template.nuspectemplate @@ -25,8 +25,6 @@ - <% additionalFiles.forEach(function(f) { %> - - <% }); %> + <% file src="additionalFiles.src" target="additionalFiles.target" / %> \ No newline at end of file diff --git a/test/snapshots/windows/squirrelWindowsTest.js.snap b/test/snapshots/windows/squirrelWindowsTest.js.snap index 523e46827a9..6971ae4dd52 100644 --- a/test/snapshots/windows/squirrelWindowsTest.js.snap +++ b/test/snapshots/windows/squirrelWindowsTest.js.snap @@ -272,6 +272,7 @@ exports[`squirrel.windows > squirrel window x64 msi 2`] = ` "lib/net45/d3dcompiler_47.dll", "lib/net45/ffmpeg.dll", "lib/net45/icudtl.dat", + "lib/net45/index.html", "lib/net45/libEGL.dll", "lib/net45/libGLESv2.dll", "lib/net45/LICENSE.electron.txt", diff --git a/test/src/windows/squirrelWindowsTest.ts b/test/src/windows/squirrelWindowsTest.ts index ba7e5b72b36..f5d273c35d4 100644 --- a/test/src/windows/squirrelWindowsTest.ts +++ b/test/src/windows/squirrelWindowsTest.ts @@ -77,6 +77,7 @@ describe("squirrel.windows", { sequential: true }, () => { squirrelWindows: { msi: true, }, + extraFiles: ["index.html"], }, }, { signedWin: true }