How to combine JSON and Handlebars with particles in HTML using Gulp?

I am creating a static site using Handlebars and Gulp. Here is my folder structure:

app/ content/ intro.json header.json faq.json features.json footer.json templates/ home.hbs partials/ home-section.hbs header.hbs footer.hbs index.html Gulpfile.js 

The contents of home.hbs are as follows:

 <!DOCTYPE html> <html lang="en"> <head> <title>Test</title> </head> <body> {{> header}} {{> home-section}} {{> home-section}} {{> home-section}} {{> footer}} </body> </html> 

I want to pass intro.json , faq.json and features.json for each part of home-section and header.json to header and footer.json in the footer.

This is what I have in my Gulpfile:

 var gulp = require('gulp'); var handlebars = require('gulp-compile-handlebars'); var rename = require('gulp-rename'); gulp.task('html', function() { return gulp.src('./app/templates/*.hbs') .pipe(handlebars({}, { ignorePartials: true, batch: ['./app/templates/partials'] })) .pipe(rename({ extname: '.html' })) .pipe(gulp.dest('build')); }); 

I was not able to figure out how to transfer more than one JSON file at a time, especially in home-section s. Thanks in advance!

+5
source share
2 answers

The first parameter to handlebars is your global context, available to all of your templates. You can load individual JSON files into a context object and use this as the first parameter.

(There are definitely better ways to do this, but hey, it's quick and easy!)

 var infoData = require('./app/content/info.json'); var faqData = require('./app/content/faq.json'); var featuresData = require('./app/content/features.json'); 

You can then pass these objects through the global context to your handlebars function

 .pipe(handlebars({ info: infoData, faq: faqData, features: featuresData })) 

Once the data is inside your context, you can access it as follows:

 {{> home-section content=info }} {{> home-section content=faq }} {{> home-section content=features }} 

Inside the partial home-section , you will have a content object that will contain the data of the file that you passed into it. So, if your info.json file looked like this:

 { "header": "Info", "details": "This is some information" } 

Partial home-content.hbs can then access the following data:

 <h2>{{ content.header }}</h2> <p>{{ content.details }}</p> 
+3
source

Unfortunately, the gulp-compile-handlerbars takes two arguments , the first of which is all the data passed into your templates. This means that you need to download all your json files and transfer them as a single object.

You can do this with a little helper, for example:

 function requireJsons(fileNames) { return fileNames.reduce(function(jsons, fileName) { jsons[fileName] = require('app/content/' + fileNames[i] + '.json'); return jsons; }, {}); } 

What you can use to create a data object for all your templates:

 var data = requireJsons(['intro', 'header', 'faq', 'features', 'footer']); gulp.task('html', function() { return gulp.src('./app/templates/*.hbs') .pipe(handlebars(data, { // ... 

If you always need to download all json files from the app/content directory, you can use readdirSync to get all .json file names and then pass them to requireJsons :

 var path = require('path'); var fileNames = fs.readdirSync('app/content') .filter(function(fileName) { return path.extname(fileName) === '.json'; }); var data = requireJsons(fileNames); 

Of course, if speed is important, you can combine the two methods into one method, which loads jsons and builds a data object in one pass.


Another option is the ability to individually compile each template and transfer the corresponding data to each compilation. It would be useful to use the gulp-foreach tool.

+2
source

Source: https://habr.com/ru/post/1262856/


All Articles