feat(tauricon): fix transparency (#1678)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
This commit is contained in:
nothingismagick 2021-05-03 00:02:58 +02:00 committed by GitHub
parent 8941790f98
commit 82a580ec45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 54 additions and 72 deletions

View File

@ -0,0 +1,10 @@
---
"cli.js": patch
---
Updates to `tauri icon`
- detect if icon is NOT transparent via metadata
- detect again on pixel level
- remove pngquant as a waste of space
- make optipng default
- relax optipng settings

View File

@ -43,7 +43,8 @@ if (argv.help) {
--help, -h Displays this message
--log, l Logging [boolean]
--target, t Target folder (default: 'src-tauri/icons')
--compression, c Compression type [pngquant|optipng|zopfli]
--compression, c Compression type [optipng|zopfli]
--ci Runs the script in CI mode
`)
process.exit(0)
}

View File

@ -58,7 +58,6 @@
"got": "11.8.2",
"imagemin": "8.0.0",
"imagemin-optipng": "8.0.0",
"imagemin-pngquant": "9.0.2",
"imagemin-zopfli": "7.0.0",
"inquirer": "8.0.0",
"is-png": "3.0.0",

View File

@ -21,7 +21,6 @@
import { access, ensureDir, ensureFileSync, writeFileSync } from 'fs-extra'
import imagemin, { Plugin } from 'imagemin'
import optipng from 'imagemin-optipng'
import pngquant, { Options as PngQuantOptions } from 'imagemin-pngquant'
import zopfli from 'imagemin-zopfli'
import isPng from 'is-png'
import path from 'path'
@ -38,7 +37,7 @@ const log = logger('app:spawn')
const warn = logger('app:spawn', chalk.red)
let image: boolean | sharp.Sharp = false
const spinnerInterval = false
let spinnerInterval: NodeJS.Timeout | null = null
const exists = async function (file: string | Buffer): Promise<boolean> {
try {
@ -70,7 +69,26 @@ const checkSrc = async (src: string): Promise<boolean | sharp.Sharp> => {
} else {
const buffer = await readChunk(src, 0, 8)
if (isPng(buffer)) {
return (image = sharp(src))
image = sharp(src)
const meta = await image.metadata()
if (!meta.hasAlpha || meta.channels !== 4) {
if (spinnerInterval) clearInterval(spinnerInterval)
warn('[ERROR] Source png for tauricon is not transparent')
process.exit(1)
}
// just because PNG is sneaky, lets look at the
// individual pixels for something weird
const stats = await image.stats()
if (stats.isOpaque) {
if (spinnerInterval) clearInterval(spinnerInterval)
warn(
'[ERROR] Source png for tauricon could not be detected as transparent'
)
process.exit(1)
}
return image
} else {
image = false
if (spinnerInterval) clearInterval(spinnerInterval)
@ -164,7 +182,10 @@ const progress = (msg: string): void => {
* // later
* clearInterval(spinnerInterval)
*/
const spinner = (): NodeJS.Timeout => {
const spinner = (): NodeJS.Timeout | null => {
if ('CI' in process.env || process.argv.some((arg) => arg === '--ci')) {
return null
}
return setInterval(() => {
process.stdout.write('/ \r')
setTimeout(() => {
@ -197,7 +218,7 @@ const tauricon = (exports.tauricon = {
if (!src) {
src = path.resolve(appDir, 'app-icon.png')
}
const spinnerInterval = spinner()
spinnerInterval = spinner()
options = options || settings.options.tauri
progress(`Building Tauri icns and ico from "${src}"`)
await this.validate(src, target)
@ -211,7 +232,7 @@ const tauricon = (exports.tauricon = {
log('no minify strategy')
}
progress('Tauricon Finished')
clearInterval(spinnerInterval)
if (spinnerInterval) clearInterval(spinnerInterval)
return true
},
@ -403,10 +424,6 @@ const tauricon = (exports.tauricon = {
strategy = minify.type
}
switch (strategy) {
case 'pngquant':
// TODO: is minify.pngquantOptions the proper format?
cmd = pngquant((minify.pngquantOptions as any) as PngQuantOptions)
break
case 'optipng':
cmd = optipng(minify.optipngOptions)
break

View File

@ -14,20 +14,10 @@ export const options = {
minify: {
batch: false,
overwrite: true,
available: ['pngquant', 'optipng', 'zopfli'],
type: 'pngquant',
pngcrushOptions: {
reduce: true
},
pngquantOptions: {
quality: [0.6, 0.8],
floyd: 0.1, // 0.1 - 1
speed: 10 // 1 - 10
},
available: ['optipng', 'zopfli'],
type: 'optipng',
optipngOptions: {
optimizationLevel: 4,
bitDepthReduction: true,
colorTypeReduction: true,
paletteReduction: true
},
zopfliOptions: {

View File

@ -27,6 +27,17 @@ describe('[CLI] tauri-icon internals', () => {
expect(process.exit.mock.calls[0][0]).toBe(1)
jest.clearAllMocks()
})
it('should fail if PNG does not have transparency', async () => {
jest.spyOn(process, 'exit').mockImplementation(() => true)
await tauricon.validate(
'test/jest/fixtures/no-alpha.png',
'test/jest/fixtures/'
)
expect(process.exit.mock.calls[0][0]).toBe(1)
jest.clearAllMocks()
})
it('can validate an image as PNG', async () => {
const valid = await tauricon.validate(
'test/jest/fixtures/tauri-logo.png',
@ -45,31 +56,18 @@ describe('[CLI] tauri-icon builder', () => {
)
expect(valid).toBe(true)
})
})
describe('[CLI] tauri-icon builder', () => {
it('will not validate a non-file', async () => {
try {
await tauricon.make(
'test/jest/fixtures/tauri-foo-not-found.png',
'test/jest/tmp/pngquant',
'pngquant'
'test/jest/tmp/optipng',
'optipng'
)
} catch (e) {
expect(e.message).toBe('Input file is missing')
}
})
})
describe('[CLI] tauri-icon builder', () => {
it('makes a set of icons with pngquant', async () => {
const valid = await tauricon.make(
'test/jest/fixtures/tauri-logo.png',
'test/jest/tmp/pngquant',
'pngquant'
)
expect(valid).toBe(true)
})
it('makes a set of icons with optipng', async () => {
const valid = await tauricon.make(

Binary file not shown.

After

Width:  |  Height:  |  Size: 863 B

View File

@ -4368,17 +4368,6 @@ imagemin-optipng@8.0.0:
is-png "^2.0.0"
optipng-bin "^7.0.0"
imagemin-pngquant@9.0.2:
version "9.0.2"
resolved "https://registry.yarnpkg.com/imagemin-pngquant/-/imagemin-pngquant-9.0.2.tgz#38155702b0cc4f60f671ba7c2b086ea3805d9567"
integrity sha512-cj//bKo8+Frd/DM8l6Pg9pws1pnDUjgb7ae++sUX1kUVdv2nrngPykhiUOgFeE0LGY/LmUbCf4egCHC4YUcZSg==
dependencies:
execa "^4.0.0"
is-png "^2.0.0"
is-stream "^2.0.0"
ow "^0.17.0"
pngquant-bin "^6.0.0"
imagemin-zopfli@7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/imagemin-zopfli/-/imagemin-zopfli-7.0.0.tgz#a44daa3bb80e2620cd1dc883d823b20b4d3788d6"
@ -6071,13 +6060,6 @@ os-tmpdir@~1.0.2:
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
ow@^0.17.0:
version "0.17.0"
resolved "https://registry.yarnpkg.com/ow/-/ow-0.17.0.tgz#4f938999fed6264c9048cd6254356e0f1e7f688c"
integrity sha512-i3keDzDQP5lWIe4oODyDFey1qVrq2hXKTuTH2VpqwpYtzPiKZt2ziRI4NBQmgW40AnV5Euz17OyWweCb+bNEQA==
dependencies:
type-fest "^0.11.0"
p-cancelable@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa"
@ -6378,16 +6360,6 @@ png2icons@2.0.1:
resolved "https://registry.yarnpkg.com/png2icons/-/png2icons-2.0.1.tgz#09d8f10b71302e98ca178d3324bc4deff9b90124"
integrity sha512-GDEQJr8OG4e6JMp7mABtXFSEpgJa1CCpbQiAR+EjhkHJHnUL9zPPtbOrjsMD8gUbikgv3j7x404b0YJsV3aVFA==
pngquant-bin@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/pngquant-bin/-/pngquant-bin-6.0.0.tgz#aff0d7e61095feb96ced379ad8c7294ad3dd1712"
integrity sha512-oXWAS9MQ9iiDAJRdAZ9KO1mC5UwhzKkJsmetiu0iqIjJuW7JsuLhmc4JdRm7uJkIWRzIAou/Vq2VcjfJwz30Ow==
dependencies:
bin-build "^3.0.0"
bin-wrapper "^4.0.1"
execa "^4.0.0"
logalot "^2.0.0"
posix-character-classes@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
@ -7827,11 +7799,6 @@ type-detect@4.0.8:
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
type-fest@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==
type-fest@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"