diff --git a/.gitattributes b/.gitattributes
index 391f0a4..6313b56 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1 @@
-* text=auto
-*.js text eol=lf
+* text=auto eol=lf
diff --git a/.travis.yml b/.travis.yml
index 225084f..6d9d707 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,6 @@
os: osx
language: node_js
node_js:
+ - '12'
- '10'
- '8'
diff --git a/cli.js b/cli.js
index f44ab58..fe9c616 100755
--- a/cli.js
+++ b/cli.js
@@ -117,7 +117,7 @@ async function init() {
ee.on('finish', async () => {
try {
ora.text = 'Replacing DMG icon';
- // Seticon is a native tool to change files icons (Source: https://github.com/sveinbjornt/osxiconutils)
+ // `seticon`` is a native tool to change files icons (Source: https://github.com/sveinbjornt/osxiconutils)
await execa(path.join(__dirname, 'seticon'), [composedIconPath, dmgPath]);
ora.text = 'Code signing DMG';
@@ -128,9 +128,9 @@ async function init() {
} else if (stdout.includes('Mac Developer:')) {
identity = 'Mac Developer';
} else {
- const err = new Error();
- err.stderr = 'No usable identity found';
- throw err;
+ const error = new Error();
+ error.stderr = 'No usable identity found';
+ throw error;
}
await execa('codesign', ['--sign', identity, dmgPath]);
diff --git a/compose-icon.js b/compose-icon.js
index 80ca74f..d34fe1c 100644
--- a/compose-icon.js
+++ b/compose-icon.js
@@ -9,7 +9,8 @@ const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
const filterMap = (map, filterFn) => Object.entries(map).filter(filterFn).reduce((out, [key, item]) => ({...out, [key]: item}), {});
-// Drive icon from /System/Library/Extensions/IOStorageFamily.kext/Contents/Resources/Removable.icns
+
+// Drive icon from `/System/Library/Extensions/IOStorageFamily.kext/Contents/Resources/Removable.icns``
const baseDiskIconPath = `${__dirname}/disk-icon.icns`;
async function composeIcon(type, appIcon, mountIcon, composedIcon) {
@@ -20,11 +21,13 @@ async function composeIcon(type, appIcon, mountIcon, composedIcon) {
// Change the perspective of the app icon to match the mount drive icon
appIcon = appIcon.out('-matte').out('-virtual-pixel', 'transparent').out('-distort', 'Perspective', `1,1 ${appIconSize.width * 0.08},1 ${appIconSize.width},1 ${appIconSize.width * 0.92},1 1,${appIconSize.height} 1,${appIconSize.height} ${appIconSize.width},${appIconSize.height} ${appIconSize.width},${appIconSize.height}`);
+
// Resize the app icon to fit it inside the mount icon, aspect ration should not be kept to create the perspective illution
appIcon = appIcon.resize(appIconSize.width / 1.7, appIconSize.height / 1.78, '!');
const tempAppIconPath = tempy.file({extension: 'png'});
await promisify(appIcon.write.bind(appIcon))(tempAppIconPath);
+
// Compose the two icons
const iconGravityFactor = mountIconSize.height * 0.155;
mountIcon = mountIcon.composite(tempAppIconPath).gravity('Center').geometry(`+0-${iconGravityFactor}`);
@@ -40,14 +43,16 @@ const hasGm = async () => {
if (error.code === 'ENOENT') {
return false;
}
+
throw error;
}
};
-module.exports = async function (appIconPath) {
+module.exports = async appIconPath => {
if (!await hasGm()) {
return baseDiskIconPath;
}
+
const baseDiskIcons = filterMap(icns.parse(await readFile(baseDiskIconPath)), ([key]) => icns.isImageType(key));
const appIcon = filterMap(icns.parse(await readFile(appIconPath)), ([key]) => icns.isImageType(key));
@@ -56,9 +61,13 @@ module.exports = async function (appIconPath) {
if (baseDiskIcons[type]) {
return composeIcon(type, icon, baseDiskIcons[type], composedIcon);
}
+
console.warn('There is no base image for this type', type);
}));
+
const tempComposedIcon = tempy.file({extension: 'icns'});
+
await writeFile(tempComposedIcon, icns.format(composedIcon));
+
return tempComposedIcon;
};
diff --git a/icon-example-app.png b/icon-example-app.png
index e4d9f2d..f38163c 100644
Binary files a/icon-example-app.png and b/icon-example-app.png differ
diff --git a/icon-example.png b/icon-example.png
index dfae9be..af1c697 100644
Binary files a/icon-example.png and b/icon-example.png differ
diff --git a/package.json b/package.json
index 9b59cab..193eb19 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
},
"files": [
"cli.js",
+ "compose-icon.js",
"assets",
"disk-icon.icns",
"seticon"
@@ -45,10 +46,10 @@
"meow": "^5.0.0",
"ora": "^3.0.0",
"plist": "^3.0.1",
- "tempy": "^0.2.1"
+ "tempy": "^0.3.0"
},
"devDependencies": {
- "ava": "^0.25.0",
- "xo": "^0.23.0"
+ "ava": "^1.4.1",
+ "xo": "^0.24.0"
}
}
diff --git a/readme.md b/readme.md
index 822a7f6..04f99cf 100644
--- a/readme.md
+++ b/readme.md
@@ -49,18 +49,20 @@ It will try to code sign the DMG, but the DMG is still created and fine even if
### DMG Icon
-[GraphicsMagick](http://www.graphicsmagick.org/) is required to create the DMG icon based on the application icon and macOS mounted device icon.
+[GraphicsMagick](http://www.graphicsmagick.org) is required to create the custom DMG icon that's based on the app icon and the macOS mounted device icon.
-### Steps using Brew
-```bash
-brew install imagemagick
-brew install graphicsmagick
+#### Steps using Homebrew
+
+```
+$ brew install graphicsmagick imagemagick
```
-### Icon Example
+#### Icon Example
+
+Original icon → DMG icon
+
+
-
-
## License