Skip to content

Commit

Permalink
feat(nsis): custom icon for file association #409
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Aug 16, 2016
1 parent e108f5f commit 09497cc
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 11 deletions.
1 change: 1 addition & 0 deletions docs/Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ NSIS only, [in progress](https://github.com/electron-userland/electron-builder/i
| **ext** | <a name="FileAssociation-ext"></a>The extension (minus the leading period). e.g. `png`
| **name** | <a name="FileAssociation-name"></a>The name. e.g. `PNG`
| description | <a name="FileAssociation-description"></a>*windows-only.* The description.
| icon | <a name="FileAssociation-icon"></a>*windows-only.* The path to icon (`.ico`), relative to `build` (build resources directory). Defaults to `${ext}.ico`.

<a name="MetadataDirectories"></a>
## `.directories`
Expand Down
5 changes: 5 additions & 0 deletions src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,11 @@ export interface FileAssociation {
*windows-only.* The description.
*/
readonly description?: string

/*
*windows-only.* The path to icon (`.ico`), relative to `build` (build resources directory). Defaults to `${ext}.ico`.
*/
readonly icon?: string
}

/*
Expand Down
31 changes: 20 additions & 11 deletions src/targets/nsis.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { WinPackager } from "../winPackager"
import { Arch, NsisOptions } from "../metadata"
import { Arch, NsisOptions, FileAssociation } from "../metadata"
import { exec, debug, doSpawn, handleProcess, use } from "../util/util"
import * as path from "path"
import { Promise as BluebirdPromise } from "bluebird"
Expand Down Expand Up @@ -30,10 +30,17 @@ export default class NsisTarget extends Target {

private readonly nsisTemplatesDir = path.join(__dirname, "..", "..", "templates", "nsis")

private readonly fileAssociations: Array<FileAssociation>

constructor(private packager: WinPackager, private outDir: string) {
super("nsis")

this.options = packager.info.devMetadata.build.nsis || Object.create(null)

// CFBundleTypeName
// https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-101685
// CFBundleTypeExtensions
this.fileAssociations = asArray(packager.devMetadata.build.fileAssociations).concat(asArray(packager.platformSpecificBuildOptions.fileAssociations))
}

async build(arch: Arch, appOutDir: string) {
Expand Down Expand Up @@ -221,24 +228,26 @@ export default class NsisTarget extends Target {
const binDir = process.platform === "darwin" ? "mac" : (process.platform === "win32" ? "Bin" : "linux")
const nsisPath = await nsisPathPromise

const packager = this.packager
// CFBundleTypeName
// https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-101685
// CFBundleTypeExtensions
const fileAssociations = asArray(packager.devMetadata.build.fileAssociations).concat(asArray(packager.platformSpecificBuildOptions.fileAssociations))

let script = originalScript
const customInclude = await this.getResource(this.options.include, "installer.nsh")
if (customInclude != null) {
script = `!include "${customInclude}"\n!addincludedir "${this.packager.buildResourcesDir}"\n${script}`
}

if (fileAssociations.length !== 0) {
if (this.fileAssociations.length !== 0) {
script = "!include FileAssociation.nsh\n" + script
if (isInstaller) {
let registerFileAssociationsScript = ""
for (let item of fileAssociations) {
const icon = '"$INSTDIR\\${APP_EXECUTABLE_FILENAME},0"'
for (let item of this.fileAssociations) {
const customIcon = await this.getResource(item.icon, `${normalizeExt(item.ext)}.ico`)
let installedIconPath = "${APP_EXECUTABLE_FILENAME},0"
if (customIcon != null) {
installedIconPath = `resources\\${path.basename(customIcon)}`
//noinspection SpellCheckingInspection
registerFileAssociationsScript += ` File "/oname=${installedIconPath}" "${customIcon}"\n`
}

const icon = `"$INSTDIR\\${installedIconPath}"`
const commandText = `"Open with ${this.packager.appInfo.productName}"`
const command = '"$INSTDIR\\${APP_EXECUTABLE_FILENAME} $\\"%1$\\""'
registerFileAssociationsScript += ` !insertmacro APP_ASSOCIATE "${normalizeExt(item.ext)}" "${item.name}" "${item.description || ""}" ${icon} ${commandText} ${command}\n`
Expand All @@ -247,7 +256,7 @@ export default class NsisTarget extends Target {
}
else {
let unregisterFileAssociationsScript = ""
for (let item of fileAssociations) {
for (let item of this.fileAssociations) {
unregisterFileAssociationsScript += ` !insertmacro APP_UNASSOCIATE "${normalizeExt(item.ext)}" "${item.name}"\n`
}
script = `!macro unregisterFileAssociations\n${unregisterFileAssociationsScript}!macroend\n${script}`
Expand Down
5 changes: 5 additions & 0 deletions test/src/nsisTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ test.ifDevOrLinuxCi("perMachine, no run after finish", app({
},
}
}
}, {
projectDirCreated: projectDir => {
let headerIconPath = path.join(projectDir, "build", "foo.ico")
return copy(getTestAsset("headerIcon.ico"), headerIconPath)
},
}))

test.ifNotCiOsx("boring", app({
Expand Down

0 comments on commit 09497cc

Please sign in to comment.