Search code examples
javascriptgruntjsgrunt-contrib-concat

How can I add to a data array from multiple files?


I've got a folder structure that looks like this:

.
├── Gruntfile.js
└── src
    └── assets
        └── blocks
          └── content.js
          └── buttons
              └── buttons1.js
              └── buttons2.js
          └── images
              └── images.js

Within my content.js file there is an empty array:

var data = {
    'snippets': []
};

And within each of the files i.e buttons1.js buttons2.js and images.js there is an array, example:

var snippet = [
    {
        'thumbnail': 'preview/button-01.png',
        'category': '119',
        'html':
            '<div>' +
            '<a href="#" class="is-btn is-btn-ghost2 is-upper">Read More</a> &nbsp;' +
            '\n<a href="#" class="is-btn is-btn-ghost1 is-upper">Buy Now</a>' +
            '</div>'
    }
]

Is there a way with Grunt (or any other process runner) to loop through all the .js files within the folder and read the value of the snippet array and then add it to the snippets in the content.js file?

So I'd end up with an array that looks like this (plus any other from the other files appended)

var data = {
    'snippets': [
 {
        'thumbnail': 'preview/button-01.png',
        'category': '119',
        'html':
            '<div>' +
            '<a href="#" class="is-btn is-btn-ghost2 is-upper">Read More</a> &nbsp;' +
            '\n<a href="#" class="is-btn is-btn-ghost1 is-upper">Buy Now</a>' +
            '</div>'
    }

]
};

I tried out the grunt-contrib-concat with the following configuration which simply creates a file with multiple snippet variables, not sure if there is a way to amend how it concats? Or if there is a different plugin available

    concat: {
      options: {
        separator: ';',
      },
      dist: {
        src: 'src/assets/blocks/*/*.js',
        dest: 'src/assets/blocks/content.js',
      },
    },

Solution

  • I ended up writing a custom task for Grunt which does what I want it to

        merge_blocks: {
          build: {
            src: 'src/assets/blocks/*/*.js',
            dest: 'src/assets/blocks/content.js'
          }
        }
    
    
      grunt.registerMultiTask('merge_blocks', 'Merge blocks', function () {
        const fs = require('fs');
        grunt.log.write('[Block Merge] Loaded dependencies...').ok();
    
        // This is the main array
        var data_basic = {
          'snippets': []
        };
    
        this.files.forEach(function (file) {
          grunt.log.writeln('Processing ' + file.src.length + ' files.');
    
          //file.src is the list of all matching file names.
          file.src.forEach(function (f) {
            var data = require('./' + f);
            data_basic.snippets.push(...data);
            data = null;
          });
    
          grunt.log.writeln('Now saving file:' + file.dest);
          fs.appendFileSync(file.dest, 'var data_basic = ' + JSON.stringify(data_basic, null, '  '));
    
        });
      });