├── .codeclimate.yml ├── .editorconfig ├── .github └── workflows │ └── pr.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── bin └── index.js ├── lib └── index.js ├── package.json ├── pnpm-lock.yaml └── tests ├── __fixtures__ ├── test.gif ├── test.jpg ├── test.png └── test.svg ├── __snapshots__ └── index.spec.js.snap └── index.spec.js /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | # This is a sample .codeclimate.yml configured for Engine analysis on Code 2 | # Climate Platform. For an overview of the Code Climate Platform, see here: 3 | # http://docs.codeclimate.com/article/300-the-codeclimate-platform 4 | 5 | # Under the engines key, you can configure which engines will analyze your repo. 6 | # Each key is an engine name. For each value, you need to specify enabled: true 7 | # to enable the engine as well as any other engines-specific configuration. 8 | 9 | # For more details, see here: 10 | # http://docs.codeclimate.com/article/289-configuring-your-repository-via-codeclimate-yml#platform 11 | 12 | # For a list of all available engines, see here: 13 | # http://docs.codeclimate.com/article/296-engines-available-engines 14 | 15 | engines: 16 | # to turn on an engine, add it here and set enabled to `true` 17 | # to turn off an engine, set enabled to `false` or remove it 18 | eslint: 19 | enabled: true 20 | 21 | # Engines can analyze files and report issues on them, but you can separately 22 | # decide which files will receive ratings based on those issues. This is 23 | # specified by path patterns under the ratings key. 24 | 25 | # For more details see here: 26 | # http://docs.codeclimate.com/article/289-configuring-your-repository-via-codeclimate-yml#platform 27 | 28 | ratings: 29 | paths: 30 | - src/** 31 | 32 | # You can globally exclude files from being analyzed by any engine using the 33 | # exclude_paths key. 34 | 35 | exclude_paths: 36 | - lib/** 37 | - **/__tests__/ 38 | - **/__fixtures__/ 39 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # Matches multiple files with brace expansion notation 12 | # Set default charset 13 | [*.{js,py}] 14 | charset = utf-8 15 | 16 | # 4 space indentation 17 | [*.py] 18 | indent_style = space 19 | indent_size = 4 20 | 21 | # Tab indentation (no size specified) 22 | [Makefile] 23 | indent_style = tab 24 | 25 | # Indentation override for all JS under lib directory 26 | [*.js] 27 | indent_style = space 28 | indent_size = 2 29 | 30 | # Matches the exact files either package.json or .travis.yml 31 | [{package.json,.travis.yml}] 32 | indent_style = space 33 | indent_size = 2 34 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: PR Workflow 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | node-version: [14, 16, 18] 14 | steps: 15 | - uses: actions/checkout@master 16 | - uses: pnpm/action-setup@master 17 | with: 18 | version: 7 19 | 20 | - name: Use Node.js ${{ matrix.node-version }} 21 | uses: actions/setup-node@master 22 | with: 23 | node-version: ${{ matrix.node-version }} 24 | cache: 'pnpm' 25 | 26 | - name: Install dependencies 27 | run: pnpm install 28 | 29 | - name: Run tests 30 | run: pnpm test 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by http://www.gitignore.io 2 | 3 | ### Editor 4 | *.swp 5 | 6 | ### Node ### 7 | # Logs 8 | logs 9 | *.log 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | 16 | # OSX 17 | .DS_Store 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Compiled binary addons (http://nodejs.org/api/addons.html) 29 | build/Release 30 | 31 | # Dependency directory 32 | # Commenting this out is preferred by some people, see 33 | # https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 34 | node_modules 35 | 36 | # Users Environment Variables 37 | .lock-wscript 38 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: node_js 4 | node_js: 5 | - '6' 6 | - '8' 7 | before_script: 8 | - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter 9 | - chmod +x ./cc-test-reporter 10 | - "./cc-test-reporter before-build" 11 | script: 12 | - npm test -- --coverage 13 | after_script: 14 | - if [[ "$TRAVIS_PULL_REQUEST" == "false" && `node --version` == *v8* ]]; then ./cc-test-reporter 15 | after-build --exit-code $TRAVIS_TEST_RESULT; fi 16 | env: 17 | global: 18 | secure: afTzTI4cFi/PB+p2svh9xy2wtzpgz5OD1cm0JipofHxWmartj4hSQJR62bX0bdq1eJvW2v6/Vso5W+F92GK+oi5i6S91So4S35JgjDPX9Xa+21h8iBRVOq9BhmwsDu2th67uTFKPNgnnvhRXi52JLi7kypsMwYqD+aDT+272BwVLK4nQ/nZC8lAySFDIKee+nmOBdBpRJrzC/oRSUmRbdzQUFdTh4uSpY7zmU5d3uNEP8JH94SMOsRcNtvNds/5e8nCMw5o/6b5GYZ8tZhkXlWtpm6SZrCMB0IjUKGX/tNGpl3mGIrIJSg2kW/9G+SZpR9FKTAbvpCXRQU4lnQ7Rgdug3QffUg79oje/p4Kf4q8oLENUU52Lm76ct6uP2Q1D6dD+wX+Gqd3VbIH5+jow0kENRKIrLnkAdLn+DVGpyeYl6iMOk9qnIvTrpDBK0JEa4z4ljryafhge1HYwnB8pdoYjysRl1mba/30ZmZpeMsuRbXrymPgwgypfZSacUiuNHh74CTK0ytGF9zVEg7WBziKe+9BCMaPpcxYp7wTfBoZ+4Pbg1knwCyphzAeh68KrMQhm+4Yghc1O5uJ/0OeNqBQh4UEj/Aj/sA2VmTvV0TwdM43+mx7XYR/bXjLn5jrVGXyTB7o7oORJwBDhVtdEfeU5qPjVparifVA1FMSHEpY= 19 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [0.5.1](https://github.com/tomchentw/imagemin-lint-staged/compare/v0.5.0...v0.5.1) (2022-06-24) 6 | 7 | ## [0.5.0](https://github.com/tomchentw/imagemin-lint-staged/compare/v0.4.0...v0.5.0) (2022-06-24) 8 | 9 | 10 | ### Features 11 | 12 | * **package.json:** upgrade dependencies ([#14](https://github.com/tomchentw/imagemin-lint-staged/issues/14)) ([d80565a](https://github.com/tomchentw/imagemin-lint-staged/commit/d80565a15e5b747cf6e8c67152cb16830b8e4042)) 13 | 14 | 15 | # [0.4.0](https://github.com/tomchentw/imagemin-lint-staged/compare/v0.3.1...v0.4.0) (2019-01-02) 16 | 17 | 18 | ### Features 19 | 20 | * **lib:** change to commonjs export ([11e3382](https://github.com/tomchentw/imagemin-lint-staged/commit/11e3382)) 21 | * **package.json:** remove `babel-multi-env` ([f427662](https://github.com/tomchentw/imagemin-lint-staged/commit/f427662)) 22 | 23 | 24 | 25 | 26 | ## [0.3.1](https://github.com/tomchentw/imagemin-lint-staged/compare/v0.3.0...v0.3.1) (2019-01-02) 27 | 28 | 29 | ### Bug Fixes 30 | 31 | * **package.json:** update core dependencies ([#4](https://github.com/tomchentw/imagemin-lint-staged/issues/4)) ([c6a96f2](https://github.com/tomchentw/imagemin-lint-staged/commit/c6a96f2)) 32 | 33 | 34 | 35 | 36 | # [0.3.0](https://github.com/tomchentw/imagemin-lint-staged/compare/v0.2.1...v0.3.0) (2017-11-23) 37 | 38 | 39 | ### Features 40 | 41 | * **index.js:** export minifyFile ([23b608f](https://github.com/tomchentw/imagemin-lint-staged/commit/23b608f)) 42 | 43 | 44 | 45 | 46 | ## [0.2.1](https://github.com/tomchentw/imagemin-lint-staged/compare/v0.2.0...v0.2.1) (2017-11-14) 47 | 48 | 49 | ### Bug Fixes 50 | 51 | * **index.js:** use separate CLI entry file ([3c5d7fc](https://github.com/tomchentw/imagemin-lint-staged/commit/3c5d7fc)) 52 | * **package.json:** use separate CLI entry file ([a605c3f](https://github.com/tomchentw/imagemin-lint-staged/commit/a605c3f)) 53 | 54 | 55 | 56 | 57 | # 0.2.0 (2017-11-14) 58 | 59 | 60 | ### Features 61 | 62 | * **index.js:** add imagemin-lint-staged CLI ([341f094](https://github.com/tomchentw/imagemin-lint-staged/commit/341f094)) 63 | * **package.json:** add with dependencies ([42c4166](https://github.com/tomchentw/imagemin-lint-staged/commit/42c4166)) 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Tom Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # imagemin-lint-staged 2 | > imagemin CLI designed for lint-staged usage with sensible defaults 3 | 4 | [![Version][npm-image]][npm-url] [![PR Workflow][github-workflows-pr-image]][github-workflows-pr-url] 5 | 6 | 7 | ## Installation 8 | 9 | ```sh 10 | npm i --save-dev imagemin-lint-staged 11 | ``` 12 | 13 | ## Usage 14 | 15 | Use in conjuntion with [lint-staged][lint-staged]. In your `package.json` 16 | 17 | ```json 18 | "lint-staged": { 19 | "*.{png,jpeg,jpg,gif,svg}": ["imagemin-lint-staged"] 20 | }, 21 | ``` 22 | 23 | 24 | ## Options 25 | 26 | N/A 27 | 28 | 29 | ## Contributing 30 | 31 | 1. Fork it 32 | 2. Create your feature branch (`git checkout -b my-new-feature`) 33 | 3. Commit your changes (`git commit -am 'Add some feature'`) 34 | 4. Push to the branch (`git push origin my-new-feature`) 35 | 5. Create new Pull Request 36 | 37 | 38 | [lint-staged]: https://github.com/okonet/lint-staged 39 | [npm-image]: https://img.shields.io/npm/v/imagemin-lint-staged.svg?style=flat-square 40 | [npm-url]: https://www.npmjs.org/package/imagemin-lint-staged 41 | 42 | [github-workflows-pr-image]: https://github.com/tomchentw/imagemin-lint-staged/actions/workflows/pr.yml/badge.svg 43 | [github-workflows-pr-url]: https://github.com/tomchentw/imagemin-lint-staged/actions/workflows/pr.yml 44 | -------------------------------------------------------------------------------- /bin/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | const { minifyFile } = require("../lib/index.js"); 4 | 5 | Promise.all(process.argv.slice(2).map(minifyFile)).catch(function(e) { 6 | console.error(e); 7 | process.exit(1); 8 | }); 9 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const fs = require("fs"); 3 | const promisify = require("util.promisify"); 4 | 5 | const readFile = promisify(fs.readFile); 6 | const writeFile = promisify(fs.writeFile); 7 | 8 | const plugins = [ 9 | [ 10 | "imagemin-gifsicle", 11 | { 12 | interlaced: true, 13 | }, 14 | ], 15 | [ 16 | "imagemin-jpegtran", 17 | { 18 | progressive: true, 19 | }, 20 | ], 21 | [ 22 | "imagemin-optipng", 23 | { 24 | optimizationLevel: 5, 25 | }, 26 | ], 27 | [ 28 | "imagemin-svgo", 29 | { 30 | plugins: [ 31 | { 32 | name: "preset-default", 33 | params: { 34 | overrides: { 35 | removeViewBox: false, 36 | }, 37 | }, 38 | }, 39 | ], 40 | }, 41 | ], 42 | ].map(([name, opts]) => require(name)(opts)); 43 | 44 | const minifyFile = (exports.minifyFile = (filename) => 45 | [...plugins, (it) => writeFile(filename, it)].reduce( 46 | (acc, it) => acc.then(it), 47 | readFile(filename) 48 | )); 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "imagemin-lint-staged", 3 | "version": "0.5.1", 4 | "description": "imagemin CLI designed for lint-staged usage with sensible defaults", 5 | "license": "MIT", 6 | "author": { 7 | "name": "tomchentw", 8 | "email": "developer@tomchentw.com", 9 | "url": "https://github.com/tomchentw" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/tomchentw/imagemin-lint-staged" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/tomchentw/imagemin-lint-staged/issues" 17 | }, 18 | "homepage": "https://github.com/tomchentw/imagemin-lint-staged/", 19 | "bin": "bin/index.js", 20 | "files": [ 21 | "bin/", 22 | "lib/", 23 | "CHANGELOG.md" 24 | ], 25 | "keywords": [ 26 | "imagemin", 27 | "CLI", 28 | "git hook", 29 | "compress images", 30 | "lint-staged" 31 | ], 32 | "scripts": { 33 | "test": "jest --runInBand", 34 | "release": "standard-version" 35 | }, 36 | "lint-staged": { 37 | "*.{png,jpeg,jpg,gif,svg}": [ 38 | "node ./bin/index.js" 39 | ], 40 | "*.{js,jsx,json,css}": [ 41 | "prettier --write" 42 | ] 43 | }, 44 | "babel": { 45 | "env": { 46 | "test": { 47 | "presets": [ 48 | "@babel/preset-env" 49 | ] 50 | } 51 | } 52 | }, 53 | "jest": { 54 | "testPathIgnorePatterns": [ 55 | "\\d+\\.\\d+\\.\\d+" 56 | ] 57 | }, 58 | "dependencies": { 59 | "imagemin-gifsicle": "^7.0.0", 60 | "imagemin-jpegtran": "^7.0.0", 61 | "imagemin-optipng": "^8.0.0", 62 | "imagemin-svgo": "^9.0.0", 63 | "util.promisify": "^1.0.0" 64 | }, 65 | "devDependencies": { 66 | "@babel/core": "^7.2.2", 67 | "@babel/preset-env": "^7.2.3", 68 | "babel-jest": "^28.1.1", 69 | "husky": "^8.0.1", 70 | "jest": "^28.1.1", 71 | "lint-staged": "^13.0.2", 72 | "prettier": "^2.7.1", 73 | "rimraf": "^3.0.2", 74 | "standard-version": "^9.5.0" 75 | }, 76 | "husky": { 77 | "hooks": { 78 | "pre-commit": "lint-staged" 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /tests/__fixtures__/test.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomchentw/imagemin-lint-staged/9882d7cd9b6de02fc6cdf7f1978a2f0096c20e20/tests/__fixtures__/test.gif -------------------------------------------------------------------------------- /tests/__fixtures__/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomchentw/imagemin-lint-staged/9882d7cd9b6de02fc6cdf7f1978a2f0096c20e20/tests/__fixtures__/test.jpg -------------------------------------------------------------------------------- /tests/__fixtures__/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomchentw/imagemin-lint-staged/9882d7cd9b6de02fc6cdf7f1978a2f0096c20e20/tests/__fixtures__/test.png -------------------------------------------------------------------------------- /tests/__fixtures__/test.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 25 | 27 | 29 | 31 | 34 | 37 | 40 | 42 | 44 | 47 | 49 | 50 | 51 | 54 | 56 | 58 | 59 | 62 | 67 | 69 | 71 | 73 | 74 | 77 | 79 | 80 | 81 | 82 | 92 | 93 | 94 | 99 | 100 | 101 | 107 | 108 | 109 | 110 | 111 | 113 | 114 | 115 | 121 | 122 | 123 | 127 | 129 | 130 | 132 | 133 | 138 | 142 | 146 | 147 | 149 | 151 | 153 | 155 | 157 | 160 | 163 | 166 | 168 | 170 | 173 | 175 | 176 | 177 | 180 | 182 | 184 | 185 | 190 | 192 | 194 | 196 | 197 | 200 | 202 | 203 | 204 | 205 | 215 | 220 | 221 | 222 | 227 | 228 | 229 | 235 | 236 | 237 | 238 | 239 | 241 | 242 | 243 | 249 | 250 | 251 | 255 | 257 | 259 | 262 | 263 | 265 | 266 | 271 | 275 | 279 | 280 | 281 | 289 | 290 | 292 | 293 | 294 | 295 | -------------------------------------------------------------------------------- /tests/__snapshots__/index.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`index module minifyFile function should work as expected 1`] = ` 4 | Array [ 5 | Object { 6 | "f": "./__fixtures__/test.gif", 7 | "size": 78080, 8 | }, 9 | Object { 10 | "f": "./__fixtures__/test.jpg", 11 | "size": 50986, 12 | }, 13 | Object { 14 | "f": "./__fixtures__/test.png", 15 | "size": 71834, 16 | }, 17 | Object { 18 | "f": "./__fixtures__/test.svg", 19 | "size": 25118, 20 | }, 21 | ] 22 | `; 23 | 24 | exports[`index module minifyFile function should work as expected 2`] = ` 25 | Array [ 26 | Object { 27 | "f": "./__fixtures__/test.gif", 28 | "size": 80201, 29 | }, 30 | Object { 31 | "f": "./__fixtures__/test.jpg", 32 | "size": 45131, 33 | }, 34 | Object { 35 | "f": "./__fixtures__/test.png", 36 | "size": 61692, 37 | }, 38 | Object { 39 | "f": "./__fixtures__/test.svg", 40 | "size": 20698, 41 | }, 42 | ] 43 | `; 44 | -------------------------------------------------------------------------------- /tests/index.spec.js: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import fs from "fs"; 3 | import child_process from "child_process"; 4 | import promisify from "util.promisify"; 5 | 6 | const stat = promisify(fs.stat); 7 | const exec = promisify(child_process.exec); 8 | 9 | describe("index module", () => { 10 | const FILENAMES = 11 | "./__fixtures__/test.gif ./__fixtures__/test.jpg ./__fixtures__/test.png ./__fixtures__/test.svg".split( 12 | " " 13 | ); 14 | 15 | const stats = () => 16 | Promise.all( 17 | FILENAMES.map(async (f) => { 18 | const { size } = await stat(path.resolve(__dirname, f)); 19 | return { f, size }; 20 | }) 21 | ); 22 | 23 | const { minifyFile } = require("../lib"); 24 | 25 | describe("minifyFile function", () => { 26 | it("should work as expected", async () => { 27 | const before = await stats(); 28 | await Promise.all( 29 | FILENAMES.map((f) => minifyFile(path.resolve(__dirname, f))) 30 | ); 31 | const after = await stats(); 32 | await exec(`git checkout .`); 33 | expect(after).not.toEqual(before); 34 | 35 | expect(before).toMatchSnapshot(); 36 | expect(after).toMatchSnapshot(); 37 | }); 38 | }); 39 | }); 40 | --------------------------------------------------------------------------------