├── .editorconfig ├── .gitignore ├── test └── jsonmin.spec.js ├── package.json ├── README.md └── index.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # Unix-style newlines with a newline ending every file 2 | [*] 3 | end_of_line = lf 4 | insert_final_newline = true 5 | trim_trailing_whitespace = true 6 | indent_style = space 7 | indent_size = 4 8 | 9 | [*.md] 10 | trim_trailing_whitespace = false 11 | 12 | [{package.json,bower.json,.travis.yml}] 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # sublime text 2 files 2 | *.sublime* 3 | *.*~*.TMP 4 | 5 | # temp files 6 | .DS_Store 7 | Thumbs.db 8 | Desktop.ini 9 | npm-debug.log 10 | 11 | # vim swap files 12 | *.sw* 13 | 14 | # emacs temp files 15 | *~ 16 | \#*# 17 | 18 | # JetBrains files 19 | .idea/ 20 | 21 | # project ignores 22 | !.gitkeep 23 | *__temp 24 | node_modules/ 25 | -------------------------------------------------------------------------------- /test/jsonmin.spec.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const File = require('vinyl'); 3 | const tap = require('tap'); 4 | 5 | const jsonmin = require('..'); 6 | 7 | tap.test('jsonmin() should minify json files', test => { 8 | const json = '{\n "hello": "world" \n}'; 9 | const expected = '{"hello":"world"}'; 10 | 11 | const stream = jsonmin() 12 | .on('data', file => { 13 | assert.strictEqual(file.contents.toString(), expected); 14 | }) 15 | .on('finish', () => { 16 | test.end(); 17 | }); 18 | stream.write(new File({ contents: Buffer.from(json) })); 19 | stream.end(); 20 | }); 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Chad Engler ", 3 | "bugs": "https://github.com/englercj/gulp-jsonmin/issues", 4 | "contributors": [ 5 | "Chad Engler ", 6 | "Emil Ajdyna", 7 | "Romain Faust " 8 | ], 9 | "dependencies": { 10 | "chalk": "^2.4.1", 11 | "fancy-log": "^1.3.2", 12 | "plugin-error": "^1.0.1", 13 | "pretty-bytes": "^5.1.0", 14 | "through2": "^2.0.3" 15 | }, 16 | "description": "Minifies json files by parsing and re-stringifying them.", 17 | "devDependencies": { 18 | "tap": "^12.0.1", 19 | "vinyl": "^2.2.0" 20 | }, 21 | "homepage": "https://github.com/englercj/gulp-jsonmin", 22 | "keywords": [ 23 | "gulp", 24 | "gulpplugin", 25 | "json", 26 | "jsonmin", 27 | "min", 28 | "minify" 29 | ], 30 | "license": "MIT", 31 | "main": "index.js", 32 | "name": "gulp-jsonmin", 33 | "repository": { 34 | "type": "git", 35 | "url": "https://github.com/englercj/gulp-jsonmin.git" 36 | }, 37 | "scripts": { 38 | "test": "tap test/**/*.spec.js" 39 | }, 40 | "version": "1.2.0" 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gulp-jsonmin 2 | 3 | Minifies json files by parsing and re-stringifying them. 4 | 5 | ## Usage 6 | 7 | ```js 8 | var jsonmin = require('gulp-jsonmin'); 9 | 10 | gulp.task('minify', function () { 11 | gulp.src('./src/**/*.json') 12 | .pipe(jsonmin()) 13 | .pipe(gulp.dest('./dist')); 14 | }); 15 | ``` 16 | 17 | ## LICENSE 18 | 19 | The MIT License 20 | 21 | Copyright (c) 2014 Chad Engler 22 | 23 | Permission is hereby granted, free of charge, to any person obtaining a copy 24 | of this software and associated documentation files (the "Software"), to deal 25 | in the Software without restriction, including without limitation the rights 26 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 27 | copies of the Software, and to permit persons to whom the Software is 28 | furnished to do so, subject to the following conditions: 29 | 30 | The above copyright notice and this permission notice shall be included in 31 | all copies or substantial portions of the Software. 32 | 33 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 34 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 35 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 36 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 37 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 38 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 39 | THE SOFTWARE. 40 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const log = require('fancy-log'); 3 | const PluginError = require('plugin-error'); 4 | const prettyBytes = require('pretty-bytes'); 5 | const trough = require('through2'); 6 | 7 | const buildSavedMessage = (savedBytes, savedPercentage) => { 8 | return `saved ${prettyBytes(savedBytes)} - ${savedPercentage.toFixed(1)}%`; 9 | }; 10 | const minifyJson = input => { 11 | if (input instanceof Buffer) { 12 | input = input.toString(); 13 | } 14 | return JSON.stringify(JSON.parse(input)); 15 | }; 16 | 17 | const DEFAULT_OPTIONS = { 18 | verbose: process.argv.includes('--verbose') 19 | }; 20 | const PLUGIN_NAME = 'gulp-jsonmin'; 21 | 22 | module.exports = options => { 23 | options = Object.assign({}, DEFAULT_OPTIONS, options); 24 | 25 | let totalFiles = 0; 26 | let totalFilesSize = 0; 27 | let totalSavedBytes = 0; 28 | 29 | return trough.obj((file, encoding, callback) => { 30 | if (file.isNull()) { 31 | return callback(null, file); 32 | } else if (file.isStream()) { 33 | return callback(new PluginError(PLUGIN_NAME, 'Streaming not supported')); 34 | } 35 | 36 | try { 37 | const fileSize = file.contents.length; 38 | file.contents = Buffer.from(minifyJson(file.contents)); 39 | const minifiedFileSize = file.contents.length; 40 | const savedBytes = fileSize - minifiedFileSize; 41 | 42 | totalFiles += 1; 43 | totalFilesSize += fileSize; 44 | totalSavedBytes += savedBytes; 45 | 46 | if (options.verbose) { 47 | const savedPercentage = fileSize ? savedBytes / fileSize * 100 : 0; 48 | const savedMessage = savedBytes ? buildSavedMessage(savedBytes, savedPercentage) : 'already minified'; 49 | log(`${PLUGIN_NAME}:`, `${chalk.green('✔')} ${file.relative} ${chalk.gray(`(${savedMessage})`)}`); 50 | } 51 | 52 | callback(null, file); 53 | } catch (error) { 54 | callback(new PluginError(PLUGIN_NAME, error), file); 55 | } 56 | }, callback => { 57 | if (options.verbose) { 58 | const savedPercentage = totalFilesSize ? totalSavedBytes / totalFilesSize * 100 : 0; 59 | const savedMessage = buildSavedMessage(totalSavedBytes, savedPercentage); 60 | log(`${PLUGIN_NAME}:`, `Minified ${totalFiles} json file(s) ${chalk.gray(`(${savedMessage})`)}`); 61 | } 62 | 63 | callback(); 64 | }); 65 | }; 66 | --------------------------------------------------------------------------------