├── .gitattributes ├── .gitignore ├── test ├── fixtures │ ├── text1.json │ └── text2.json ├── expected │ ├── merged.json │ └── merged-with-spaces.json └── main.js ├── .travis.yml ├── .editorconfig ├── .jshintrc ├── LICENSE ├── package.json ├── index.js └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .DS_Store 3 | node_modules/ 4 | temp/ 5 | npm-debug.log 6 | -------------------------------------------------------------------------------- /test/fixtures/text1.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": { 3 | "bar": true 4 | }, 5 | "baz": false 6 | } -------------------------------------------------------------------------------- /test/fixtures/text2.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": { 3 | "other": "HELLO" 4 | }, 5 | "bah": "BYE" 6 | } -------------------------------------------------------------------------------- /test/expected/merged.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": { 3 | "bar": true, 4 | "other": "HELLO" 5 | }, 6 | "baz": false, 7 | "bah": "BYE" 8 | } -------------------------------------------------------------------------------- /test/expected/merged-with-spaces.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": { 3 | "bar": true, 4 | "other": "HELLO" 5 | }, 6 | "baz": false, 7 | "bah": "BYE" 8 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6.14.0" 4 | before_install: 5 | - currentfolder=${PWD##*/} 6 | - if [ "$currentfolder" != 'generator-gulp-plugin' ]; then cd .. && eval "mv $currentfolder generator-gulp-plugin" && cd generator-gulp-plugin; fi 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [test/fixtures/*] 16 | insert_final_newline = false 17 | trim_trailing_whitespace = false 18 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 4, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "double", 14 | "undef": true, 15 | "unused": true, 16 | "strict": true, 17 | "trailing": true, 18 | "smarttabs": true, 19 | "white": true 20 | } 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Adam Ayres 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-extend", 3 | "version": "0.3.0", 4 | "description": "A gulp plugin to extend (merge) JSON contents", 5 | "keywords": [ 6 | "gulpplugin", 7 | "extend", 8 | "merge", 9 | "gulp" 10 | ], 11 | "homepage": "https://github.com/adamayres/gulp-extend", 12 | "bugs": "https://github.com/adamayres/gulp-extend/issues", 13 | "author": { 14 | "name": "Adam Ayres", 15 | "email": "magicaj@gmail.com", 16 | "url": "https://github.com/adamayres" 17 | }, 18 | "main": "./index.js", 19 | "repository": { 20 | "type": "git", 21 | "url": "git://github.com/adamayres/gulp-extend.git" 22 | }, 23 | "scripts": { 24 | "test": "mocha" 25 | }, 26 | "dependencies": { 27 | "event-stream": "*", 28 | "node.extend": "~2.0.2", 29 | "through": "~2.3.4", 30 | "gulp-util": "~3.0.8" 31 | }, 32 | "devDependencies": { 33 | "mocha": "6.0.2", 34 | "should": "13.2.3", 35 | "gulp-util": "~3.0.8" 36 | }, 37 | "engines": { 38 | "node": ">=6.14.x", 39 | "npm": ">=1.2.10" 40 | }, 41 | "licenses": [ 42 | { 43 | "type": "MIT" 44 | } 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var extend = require('node.extend'); 4 | var through = require('through'); 5 | var path = require('path'); 6 | var gutil = require('gulp-util'); 7 | var PluginError = gutil.PluginError; 8 | var File = gutil.File; 9 | 10 | var PLUGIN_NAME = 'gulp-extend'; 11 | 12 | module.exports = function(fileName, deep, jsonSpace) { 13 | if (!fileName) { 14 | throw new PluginError(PLUGIN_NAME, PLUGIN_NAME + ': Missing fileName parameter'); 15 | } 16 | 17 | var buffer = []; 18 | var firstFile = null; 19 | 20 | deep = (deep !== undefined) ? deep : true; 21 | buffer.push(deep); // first argument 22 | 23 | function bufferContents(file) { 24 | if (file.isNull()) { 25 | return this.queue(file); 26 | } 27 | 28 | if (file.isStream()) { 29 | return this.emit('error', new PluginError(PLUGIN_NAME, PLUGIN_NAME + ': Streaming not supported')); 30 | } 31 | 32 | if (!firstFile) { 33 | firstFile = file; 34 | } 35 | 36 | var jsonContent; 37 | 38 | try { 39 | jsonContent = JSON.parse(file.contents.toString('utf8')); 40 | } catch (e) { 41 | jsonContent = {}; 42 | console.log('[' + gutil.colors.red('gulp-extend') + '] File "' + file.path + '" has errors and was skipped!'); 43 | } 44 | 45 | buffer.push(jsonContent); 46 | } 47 | 48 | function endStream() { 49 | if (buffer.length === 1) { 50 | return this.emit('end'); 51 | } 52 | 53 | var joinedContents = extend.apply(this, buffer); 54 | var joinedPath = path.join(firstFile.base, fileName); 55 | var joinedFile = new File({ 56 | cwd: firstFile.cwd, 57 | base: firstFile.base, 58 | path: joinedPath, 59 | contents: new Buffer(JSON.stringify(joinedContents, null, jsonSpace)) 60 | }); 61 | 62 | this.emit('data', joinedFile); 63 | this.emit('end'); 64 | } 65 | 66 | return through(bufferContents, endStream); 67 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gulp-extend [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][depstat-image]][depstat-url] 2 | 3 | > A [gulp](https://github.com/wearefractal/gulp) plugin to [extend](https://npmjs.org/package/node.extend) (merge) json contents 4 | 5 | ## Usage 6 | 7 | First, install `gulp-extend` as a development dependency: 8 | 9 | ```shell 10 | npm install gulp-extend --save-dev 11 | ``` 12 | 13 | Then, add it to your `gulpfile.js`: 14 | 15 | **Extend the contents of json files** 16 | 17 | ```javascript 18 | var extend = require('gulp-extend'); 19 | 20 | gulp.src('./src/*.en.json') 21 | .pipe(extend('text.en.json')) 22 | .pipe(gulp.dest('./dist')); 23 | ``` 24 | 25 | **Extend the contents of a json file and then [wrap](https://github.com/adamayres/gulp-wrap) them in a code block** 26 | 27 | ```javascript 28 | var extend = require('gulp-extend'); 29 | var wrap = require('gulp-wrap'); 30 | 31 | gulp.src('./src/*.json') 32 | .pipe(extend('text.en.js') //use .js extension since we plan to wrap 33 | .pipe(wrap('angular.module(\'text\', []).value(<%= contents %>);')) 34 | .pipe(gulp.dest("./dist")); 35 | ``` 36 | 37 | ## API 38 | 39 | ### extend(fileName[, deep [, jsonSpace]]) 40 | 41 | #### fileName 42 | Type: `String` 43 | 44 | The output filename 45 | 46 | #### deep 47 | 48 | Type: `Boolean` 49 | Default: `true` 50 | 51 | If the extend should be deep. 52 | 53 | #### jsonSpace 54 | 55 | Type: `String` or `Number` 56 | Default: `undefined` 57 | 58 | JSON.stringify's space attribute for pretty-printing the resulting JSON. 59 | See [MDN docs on JSON.stringify()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) for more information. 60 | 61 | ## License 62 | 63 | [MIT License](http://en.wikipedia.org/wiki/MIT_License) 64 | 65 | [npm-url]: https://npmjs.org/package/gulp-extend 66 | [npm-image]: https://badge.fury.io/js/gulp-extend.png 67 | 68 | [travis-url]: http://travis-ci.org/adamayres/gulp-extend 69 | [travis-image]: https://secure.travis-ci.org/adamayres/gulp-extend.png?branch=master 70 | 71 | [depstat-url]: https://david-dm.org/adamayres/gulp-extend 72 | [depstat-image]: https://david-dm.org/adamayres/gulp-extend.png 73 | -------------------------------------------------------------------------------- /test/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var extend = require('../'); 4 | var fs = require('fs'); 5 | var es = require('event-stream'); 6 | var should = require('should'); 7 | var gutil = require('gulp-util'); 8 | var path = require('path'); 9 | require('mocha'); 10 | 11 | describe('gulp-extend', function () { 12 | 13 | var expectedFile = new gutil.File({ 14 | path: 'test/expected/text1.json', 15 | cwd: 'test/', 16 | base: 'test/expected', 17 | contents: fs.readFileSync('test/expected/merged.json') 18 | }); 19 | 20 | it('should extend file contents via buffer', function (done) { 21 | 22 | var srcFile1 = new gutil.File({ 23 | path: 'test/fixtures/text1.json', 24 | cwd: 'test/', 25 | base: 'test/fixtures', 26 | contents: fs.readFileSync('test/fixtures/text1.json') 27 | }); 28 | 29 | var srcFile2 = new gutil.File({ 30 | path: 'test/fixtures/text1.json', 31 | cwd: 'test/', 32 | base: 'test/fixtures', 33 | contents: fs.readFileSync('test/fixtures/text2.json') 34 | }); 35 | 36 | var stream = extend('output.json'); 37 | 38 | stream.on('error', function(err) { 39 | should.exist(err); 40 | done(err); 41 | }); 42 | 43 | stream.on('data', function (newFile) { 44 | should.exist(newFile); 45 | should.exist(newFile.contents); 46 | 47 | var newFilePath = path.resolve(newFile.path); 48 | var expectedFilePath = path.resolve('test/fixtures/output.json'); 49 | newFilePath.should.equal(expectedFilePath); 50 | 51 | newFile.relative.should.equal('output.json'); 52 | String(newFile.contents).should.equal('{"foo":{"bar":true,"other":"HELLO"},"baz":false,"bah":"BYE"}'); 53 | Buffer.isBuffer(newFile.contents).should.equal(true); 54 | done(); 55 | }); 56 | 57 | stream.write(srcFile1); 58 | stream.write(srcFile2); 59 | stream.end(); 60 | }); 61 | 62 | it('should allow a shallow extend of file contents via buffer', function (done) { 63 | 64 | var srcFile1 = new gutil.File({ 65 | path: 'test/fixtures/text1.json', 66 | cwd: 'test/', 67 | base: 'test/fixtures', 68 | contents: fs.readFileSync('test/fixtures/text1.json') 69 | }); 70 | 71 | var srcFile2 = new gutil.File({ 72 | path: 'test/fixtures/text1.json', 73 | cwd: 'test/', 74 | base: 'test/fixtures', 75 | contents: fs.readFileSync('test/fixtures/text2.json') 76 | }); 77 | 78 | var stream = extend('output.json', false); 79 | 80 | stream.on('error', function(err) { 81 | should.exist(err); 82 | done(err); 83 | }); 84 | 85 | stream.on('data', function (newFile) { 86 | should.exist(newFile); 87 | should.exist(newFile.contents); 88 | 89 | var newFilePath = path.resolve(newFile.path); 90 | var expectedFilePath = path.resolve('test/fixtures/output.json'); 91 | newFilePath.should.equal(expectedFilePath); 92 | 93 | newFile.relative.should.equal('output.json'); 94 | String(newFile.contents).should.equal('{"foo":{"other":"HELLO"},"baz":false,"bah":"BYE"}'); 95 | Buffer.isBuffer(newFile.contents).should.equal(true); 96 | done(); 97 | }); 98 | 99 | stream.write(srcFile1); 100 | stream.write(srcFile2); 101 | stream.end(); 102 | }); 103 | 104 | it('should error on stream', function (done) { 105 | 106 | var srcFile = new gutil.File({ 107 | path: 'test/fixtures/text1.json', 108 | cwd: 'test/', 109 | base: 'test/fixtures', 110 | contents: fs.createReadStream('test/fixtures/text1.json') 111 | }); 112 | 113 | var stream = extend('World'); 114 | 115 | stream.on('error', function(err) { 116 | err.message.should.equal('gulp-extend: Streaming not supported'); 117 | should.exist(err); 118 | done(); 119 | }); 120 | 121 | stream.on('data', function (newFile) { 122 | newFile.contents.pipe(es.wait(function(err, data) { 123 | done(err); 124 | })); 125 | }); 126 | 127 | stream.write(srcFile); 128 | stream.end(); 129 | }); 130 | 131 | it('should error when no fileName is provided', function () { 132 | (function(){ 133 | extend(); 134 | }).should.throw('gulp-extend: Missing fileName parameter'); 135 | }); 136 | 137 | it('should pass json space parameter', function () { 138 | var src1 = new gutil.File({ 139 | contents: fs.readFileSync('test/fixtures/text1.json') 140 | }); 141 | 142 | var src2 = new gutil.File({ 143 | contents: fs.readFileSync('test/fixtures/text2.json') 144 | }); 145 | 146 | var extendStream = extend('result.json', true, 4); 147 | extendStream.pipe(es.through(function(file) { 148 | var result = file.contents.toString(), 149 | expected = fs.readFileSync('test/expected/merged-with-spaces.json').toString(); 150 | 151 | result.should.equal(expected); 152 | })); 153 | 154 | extendStream.write(src1); 155 | extendStream.write(src2); 156 | extendStream.end(); 157 | }); 158 | }); 159 | --------------------------------------------------------------------------------