You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
4.5 KiB

const fs = require('fs')
const path = require('path')
const { createConverter } = require('convert-svg-to-png')
const terminalOverwrite = require('terminal-overwrite')
// Fix memoryleak warning
const maxConvertProcesses = 1
process.setMaxListeners(maxConvertProcesses + 1)
const appPaths = () => {
const fileDir = path.dirname(require.main.filename).split('/')
// Remove current bin directory
fileDir.pop()
const appDir = fileDir.join('/')
return {
basePath: fileDir,
appPath: appDir,
iconPath: appDir + '/src/images/icons',
convertPath: appDir + '/src/images/icons/converted',
}
}
/**
* Copy files from source to destination.
* @param source
* @param destination
*/
function copyFiles(source, destination) {
// File destination will be created or overwritten by default.
fs.copyFileSync(source, destination)
// console.log(`${source} -> ${destination}`)
}
/**
* Get extension of image file.
* @returns {string}
*/
function getFileExtension(filePath) {
return path.extname(filePath)
}
/**
* Get base name of image file.
* @returns {string}
*/
function getFileName(filePath) {
return path.basename(filePath, getFileExtension(filePath))
}
function getConvertFileName(filePath) {
const name = getFileName(filePath)
return `${appPaths().convertPath}/${name}.png`
}
/**
* Check if converted image exists
* @returns {boolean}
*/
function checkFileExists(imagePath) {
const fileExists = fs.existsSync(imagePath)
return fileExists
}
/**
* Check if path is a file
* @param {*} filePath
* @returns
*/
function checkIfFile(filePath) {
return fs.statSync(filePath).isFile()
}
function dateModified(file) {
return fs.statSync(file).mtime
}
function dateDiff(file) {
const now = new Date().getTime()
const then = dateModified(file).getTime()
return Math.round(Math.abs(((then - now) / 1000) * 60 * 60 * 24))
}
;(async () => {
// Main script
const files = fs.readdirSync(appPaths().iconPath)
const totalFiles = files.length
const batchNum = Math.ceil(totalFiles / maxConvertProcesses)
let batchCount = 1
const converter = createConverter()
do {
const percentComplete = `${
100 - Math.round((100 / totalFiles) * files.length)
}%`
terminalOverwrite(
`Processing Batch: ${batchCount} of ${batchNum} (${percentComplete})`
)
await Promise.all(
files.splice(0, maxConvertProcesses).map(async (fileName) => {
const path = `${appPaths().iconPath}/${fileName}`
const outputFilePath = getConvertFileName(fileName)
const ext = getFileExtension(path)
if (ext === '.svg') {
// Check if converted file exists.
if (checkFileExists(outputFilePath)) {
// Skip if destination file exists and source file hasn't changed in
// 30 days or destination file was created in the last day
const fileAgeA = dateDiff(path)
const fileAgeB = dateDiff(outputFilePath)
if (fileAgeA > 30 || fileAgeB < 1) {
return
}
}
// Convert and copy file.
for (let attempt = 1; attempt <= 3; attempt++) {
try {
await converter
.convertFile(path, {
height: 32,
width: 32,
outputFilePath,
})
.catch((error) => {
throw new Error(`${error} (${fileName})`)
})
break
} catch (error) {
if (attempt >= 3) {
throw error
} else {
// eslint-disable-next-line no-console
console.error(`${error.message || error} (attempt ${attempt})`)
await new Promise((resolve) =>
setTimeout(resolve, 500 * attempt)
)
}
}
}
} else if (this.ext === '.png') {
// If PNG, just copy the file as-is.
// eslint-disable-next-line no-lonely-if
if (checkIfFile(this.path)) {
copyFiles(this.path, this.convertPath)
}
}
})
)
batchCount++
} while (files.length)
await converter.destroy()
// eslint-disable-next-line no-console
console.log(`Converted ${totalFiles.toLocaleString()} files.`)
})()
/**
cd ; cp *.svg converted ; cd converted ; convert-svg-to-png *.svg --width 32 --height 32 ; rm *.svg
(async() => {
const inputFilePath = '/path/to/my-image.svg';
const outputFilePath = await convertFile(inputFilePath);
console.log(outputFilePath);
//=> "/path/to/my-image.png"
})();
*/