Skip to content

AlexanderTheGrey/image-converter-cli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Image Converter CLI

A TypeScript command-line based image converter used to convert JPEG, PNG, GIF, TIFF, BMP, and SVG images to the web-optimized WebP format. It's primarily designed for use in pre-commit hooks.

Install

npm install image-converter-cli

Usage

Command-line

image-converter-cli -i <image-glob> [OPTIONS]...

Module

ECMAScript
import { ImageConverter }

const argv = [
    "node",
    "image-converter",
    "-i",
    "<image-glob>",
    "OPTION 1",
    "OPTION 2",
    "OPTION 3..."
];

/*
If using staged files, populate .image-converter-temp/.staged_files

 If using exclusions file, populate .image-converter-temp/.converter_exclusions
 */

const imageConverterObj = new ImageConverter(argv);
await imageConverterObj.runProgram();

CommonJS and ECMAScript using a dynamic import
(async () => {
	const { imageConverter } = await import("ImageConverter");

    const argv = [
        "node",
        "image-converter",
        "-i",
        "<image-glob>",
        "OPTION 1",
        "OPTION 2",
        "OPTION 3..."
    ];

    /*
    If using staged files, populate .image-converter-temp/.staged_files

    If using exclusions file, populate .image-converter-temp/.converter_exclusions
    */

    const imageConverterObj = new ImageConverter(argv);
    await imageConverterObj.runProgram();
})();

Use in a pre-commit hook

Example of command-line use in a POSIX shell script (Apache-2.0 License)
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
reject_commit=0
code_change=0
converterDir=./.image-converter-temp
bold=$(tput bold)
red=$(tput setaf 1)
redbg=$(tput setab 1)
green=$(tput setaf 2)
blue=$(tput setaf 4)
bluebg=$(tput setab 4)
yellow=$(tput setaf 3)
cyan=$(tput setaf 6)
normal=$(tput sgr0)
mkdir -p "$converterDir/"
git diff --name-status --staged --diff-filter=AMR | awk -F '\t' '$1 ~ /(A|M)/ {print $2}; $1 ~ /R100/ {print $3};' > "$converterDir/.staged_files"
sed -e '/^[[:blank:]]*#.*$/d' -e '/^[[:blank:]]*$/d' "./.converterignore" > "$converterDir/.converter_exclusions"
image-converter -i './{src,public}/**/*.(jpeg|jpg|jpe|jif|jfif|jfi|png|gif|tiff|tif|bmp|webp|heif|heifs|heic|heics|avci|avcs|avif|avifs)' -c './{src,public}/**/*.(js|vue|html)'
rm -f "$converterDir/.staged_files" "$converterDir/.converter_exclusions"
if [ -e "$converterDir/.conversion" ]; then
    printf "\n%s\n" "${blue}Searching for non-WebP image extensions in code files...${normal}"
    rm -f "$converterDir/.conversion"
    current_date=$(date +"%Y-%m-%d_%H:%M:%S")
    mkdir -p "./.image_backup/$current_date"
    while read -r imagePath; do
        git restore --staged "$imagePath"
        mv -- "$imagePath" "./.image_backup/$current_date"
    done < "$converterDir/.converted_source_image_files"
    if [ -e "$converterDir/.code_search_files" ]; then
        sed -i.bak -E 's/[^a-zA-Z 0-9]/\\&/g' "$converterDir/.converted_source_image_files"
        rm -f "$converterDir/.converted_source_image_files.bak"
        while read -r imagePath; do
            basename="${imagePath##*/}"
            filenameTemp="${basename%.*}"
            filename="${filenameTemp%\\}"
            ext="${basename##*.}"
            while read -r codePath; do
                sed -i.bak -E "s/($filename).$ext/\1\.webp/g w $converterDir/.changes" "./$codePath"
                if [ -s "$converterDir/.changes" ]; then
                    printf "%s\n\n" "${cyan}Updated $codePath${normal}"
                    if [ $code_change -eq 0 ]; then
                        mkdir -p "./.code_backup/$current_date"
                        code_change=1
                    fi
                    mv -- "./$codePath.bak" "./.code_backup/$current_date/${codePath##*/}"
                else
                    rm -f "./$codePath.bak"
                fi
            done < "$converterDir/.code_search_files"
        done < "$converterDir/.converted_source_image_files"
    fi
    rm -f "$converterDir/.converted_source_image_files" "$converterDir/.converted_target_image_files" "$converterDir/.code_search_files" "$converterDir/.changes"
    if [ $code_change -eq 1 ]; then
        if ! [ -e "$converterDir/.converter_errors" ]; then
            printf "%s\n" "${green}Successfully converted images and changed their references in code.${normal}"
        else
            printf "%s\n" "${green}Successfully converted some images and changed their references in code.${normal}"
        fi
        printf "\n%s\n%s\n\n" "${cyan}Original image files located at:" "$PWD/.image_backup/$current_date/${normal}"
        printf "\n%s\n%s\n\n" "${cyan}Original code files located at:" "$PWD/.code_backup/$current_date/${normal}"
        printf "%s\n" "${bold}${bluebg}Review the converted images/code changes and re-commit.${normal}"
        printf "%s\n" "${bold}${blue}Use \"git diff\" to examine changes.${normal}"
    else
        printf "%s\n" "${yellow}No code files need updating.${normal}"
        if ! [ -e "$converterDir/.converter_errors" ]; then
            printf "\n%s\n" "${green}Successfully converted images.${normal}"
        else
            printf "\n%s\n" "${green}Successfully converted some images.${normal}"
        fi
        printf "\n%s\n%s\n\n" "${cyan}Original image files located at:" "$PWD/.image_backup/$current_date/${normal}"
        printf "%s\n" "${bold}${bluebg}Review the converted images and re-commit.${normal}"
    fi
    reject_commit=1
fi
if [ -e "$converterDir/.converter_errors" ]; then
    printf "\n%s\n" "${bold}${red}Errors occured:${normal}"
     while read -r errorImagePath; do
        printf "%s\n" "${red}$errorImagePath${normal}"
        git restore --staged $errorImagePath
     done < "$converterDir/.converter_errors"
    printf "%s\n\n" "${bold}${redbg}Fix errors and re-commit.${normal}"
    rm -f "$converterDir/.converter_errors"
    reject_commit=1
fi
rm -rf "$converterDir/"
if [ $reject_commit -eq 1 ]; then
    exit 1
else
    npx pretty-quick --staged
    npm run lint
    # Do anything else that normally would occur in the pre-commit hook
fi

Ignoring Files

The root directory can contain a .converterignore, which uses the same syntax as .gitignore. The contents of this must be copied to .image-converter-temp/.converter_exclusions (with comments removed, if applicable) for the image converter to know about it.

Temporary Files

A temporary folder, .image-converter-temp is created in the project's root directory. There are seven temporary files located within this directory to be used in the pre-commit hook:

.conversion

A file created when a successful conversion happens.

.code_search_files

Created only if the -c, --code-glob option was used. Contains the code files that the code glob found. The pre-commit script can search for relevant extensions and replace them.

.staged_files

This file needs to be populated by your pre-commit script (if not overriden). POSIX shell example for getting all added, modified, and renamed files and copying them to .staged_files file within the temporary directory:

git diff --name-status --staged --diff-filter=AMR | awk -F '\t' '$1 ~ /(A|M)/ {print $2}; $1 ~ /R100/ {print $3};' > "./.image-converter-temp/.staged_files"

.converter_exclusions

The contents of .converterignore should be copied to the image-conveter-temp directory by your pre-commit hook as .converter_exclusions (unless --override-excluded-files is used). POSIX shell example that removes all comment lines which start with "#" in .converterignore and copies the output to .converter_exclusions file within the temporary directory:

sed -e '/^[[:blank:]]*#.*$/d' -e '/^[[:blank:]]*$/d' "./.converterignore" > "./.image-converter-temp/.converter_exclusions"

.converted_source_image_files

Contains the source images of successfully converted files.

.converted_target_image_files

Contains the successfully converted files.

.converter_errors

Contains all images that experienced errors when converting.

CLI Options

-v, --version

Output the version number.

-i, --image-glob <value>

Glob to search image files.

-c, --code-glob <value>

Glob to search code files.

--process-svg-files

Process SVG files.

--override-staged-files

Don't exclude unstaged files.

--override-excluded-files

Don't exclude files from exclusions list.

--create-fallback-image

Create a PNG/GIF file if a JPEG, PNG, GIF, TIFF, or BMP file doesn't exist.

-h, --help

Display help for command.

Example Run

image-converter -i './{src,public}/**/*.(jpeg|jpg|jpe|jif|jfif|jfi|png|gif|tiff|tif|bmp|webp|heif|heifs|heic|heics|avci|avcs|avif|avifs)' -c './{src,public}/**/*.(js|vue|html)'

Note: Glob options must be single quoted to avoid interpretation by the shell

About

Automate converting images to WebP in pre-commit hooks

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published