How do I pull multiple JSON files into SWIG on Node.js? - json

This is actually two questions...
I have a single SWIG template (index.html) that I would like to pull multiple JSON files into for compiling using Node.js. An "index.json" file with variables that pertain just to that page, then a "common.json" file that contains a set of common variables that I would like to use across the entire system.
I also then have a "header.html" template and a "footer.html" template inside "index.html". How would I get them to each pull their own "header.json" and "footer.json" files respectively?
Ultimately, I am trying to get this all working within GULP-SWIG since we already have a GULP process running at all times for the rest of the project.
UPDATE: GULP-SWIG automatically looks for a JSON file with the same name and processes it, but there is no documentation on including additional JSON files.
I tried it this way:
// Include gulp
var gulp = require('gulp');
// Include Our Plugins
var swig = require('gulp-swig');
// Swig Variables
var common = require('./json/common.json'); // <--- NEW CODE
var optEng = {
load_json: true,
json_path: 'json/',
data: {
locale: 'en_US',
currencyval: 'USD'
}
};
// Tasks
gulp.task('swig-eng', function() {
gulp.src('templates/*.html')
.pipe(swig(common)) // <--- NEW CODE
.pipe(swig(optEng))
.pipe(gulp.dest('./compiled/'));
});
gulp.task('watch', function() {
gulp.watch('templates/*.html', ['swig-eng']);
gulp.watch('includes/*.html', ['swig-eng']);
gulp.watch('json/*.json', ['swig-eng']);
});
gulp.task('build', ['swig-eng', 'watch']);
And I tried it this way:
// Include gulp
var gulp = require('gulp');
// Include Our Plugins
var swig = require('gulp-swig');
// Swig Variables
var optEng = {
common: require('./json/common.json'), // <--- NEW CODE
load_json: true,
json_path: 'json/',
data: {
locale: 'en_US',
currencyval: 'USD'
}
};
// Tasks
gulp.task('swig-eng', function() {
gulp.src('templates/*.html')
.pipe(swig(optEng))
.pipe(gulp.dest('./compiled/'));
});
gulp.task('watch', function() {
gulp.watch('templates/*.html', ['swig-eng']);
gulp.watch('includes/*.html', ['swig-eng']);
gulp.watch('json/*.json', ['swig-eng']);
});
gulp.task('build', ['swig-eng', 'watch']);
I have created a ZIP file containing the required file structure:
https://www.dropbox.com/s/psxsdn31rd5177h/Gulp-Swig%20Sample.zip
The gulpfile.js file is the ONLY file that should need to be updated.

require them
You can just require the json files and pass them as local variables to swig
swig.renderFile('/path/to/template.html', {
common: require('path/to/your/common.json'),
index: require('path/to/your/index.json')
// etc
});
Supossing you are...
"including" your header and footer templates as partials, i.e.
index.swig.html
{# ... #}
{% include "header.swig.html" %}
{# ... #}
{% include "footer.swig.html" %}
{# ... #}
They will receive all the local variables, unless you specify a with *whatever* only statement. Check the include docs for further understanding.
{% include "./partial.html" with my_obj only %}
You can...
require all your json files and pass them as local variables, specifying the objects you want to pass into.
swig.renderFile('/path/to/index.swig.html', {
common: require('path/to/your/common.json'),
index: require('path/to/your/index.json'),
header: require('path/to/your/header.json'),
footer: require('path/to/your/footer.json')
// etc
});
And on index.swig.html...
{# ... #}
{% include "header.swig.html" with header only %}
{# ... #}
{% include "footer.swig.html" with footer only %}
{# ... #}

You can use the setup option in gulp-swig which gives you direct access to the swig object. Once you have access, you can read the Swig documentation on how to pass data. Here's an example:
var opts = {
setup: function(swig) {
swig.setDefaults({
locals: {
common: require('path/to/your/common.json'),
header: require('path/to/your/header.json'),
footer: require('path/to/your/footer.json')
}
});
}
};
gulp.task('templates', function() {
gulp.src('./lib/*.html')
.pipe(swig(opts))
.pipe(gulp.dest('./dist/'))
});

Related

Gulp Nunjucks: Case insensitiv include?

I have a large project built on windows which uses loads of includes written in uppercase
{% include 'TEMPLATE.html' %}
but the files are named in lowercase template.html
Now the project won't build on Linux ... Is there a way to fix this in the gulpfile nunjucks.compile()?
Thanks
If gulp doesn't have the required option, you can use a custom loader or override include-tag.
Template test.html: TEST - {{result or 'Failed'}}
const nunjucks = require('nunjucks');
const fileLoader = new nunjucks.FileSystemLoader('views')
const MyLoader = nunjucks.Loader.extend({
getSource: path => fileLoader.getSource(path.toLowerCase())
});
const env = new nunjucks.Environment(new MyLoader(), {autoescape: true});
const html = env.render('TEST.html', {result: 'OK'});
console.log(html);

Include json file as path using lottie.js

In my Laravel homestead project I want to use airbnb/lottie to displat animations.
I have placed my lottie.js and script.js in my assets folder.
my script.js looks like this:
var anim = document.getElementById('bodymovin');
var animData = bodymovin.loadAnimation({
container: anim,
renderer: 'svg',
loop: false,
autoplay: false,
path: 'data.json',
});
btn = document.getElementById('animBtn');
btn.addEventListener('click', function() {
animData.setDirection(1);
animData.play();
});
now the problem is that it can't find data.json, error:
GET http://bertels.test/nl/vacatures/data.json 404 (Not Found)
my data.json is in the same directory as my script.js.
My question is: How can I use data.json in script.js?
Regards,
burnerPhone
You could use a custom route to return the desired files. Copy your file to /storage/app/public and append the following code to routes/web.php:
Route::get('/files/{filename}', function($filename){
return \Storage::download($filename); // assuming default disk is set to 'public'
});
Then access the file in your browser using PROTOCOL://SERVER_HOST/files/data.json
Of course, you can use file_get_contents as well but you'll need to wrap it within a response and test the file for proper headers output.

How to get gulp-html-minifier's output into gulp-inject-stringified-html?

I'm trying to use these two gulp plugins together:
gulp-html-minifier
gulp-inject-stringified-html
Or put differently, I'm trying to inject the contents of files containing html fragments into my javascript files after they're minified.
When I'm trying to run a straight up gulp build I get this:
Error: ENOENT: no such file or directory, open 'C:\path\to\.temp\template.html'
Here's a repro of my situation. My folder structure:
/src/app.js
/src/template.html
/gulpfile.js
/package.json
My gulpfile.js:
var gulp = require('gulp');
var injectHtml = require('gulp-inject-stringified-html');
var htmlmin = require('gulp-html-minifier');
gulp.task('minify', [], function() {
gulp.src('src/*.html')
.pipe(htmlmin())
.pipe(gulp.dest('.temp'));
});
gulp.task('default', ['minify'], function() {
gulp.src('src/*.js')
.pipe(injectHtml())
.pipe(gulp.dest('.build'));
});
The template.html file:
<div>My Template</div>
The app.js file:
var html = { gulp_inject: "../.temp/template.html" };
Now, if I run minify manually first, things will work as expected. From this I speculate I'm not using Gulp correctly. I reckon I'd need to pipe the result of htmlmin into the injectHtml method. But I fail to see how.
How can I get these two plugins to play together nicely?
You are missing a return in the minify task. It should look like that:
gulp.task('minify', [], function() {
return gulp.src('src/*.html')
.pipe(htmlmin())
.pipe(gulp.dest('.temp'));
});
Without return, the default task doesn't have any way to know that minify finished, so it may start before the minified html file was created.

Gulp Front Matter +Markdown through Nunjucks

I'm working on adding some simple Markdown processing to my Gulp process, but I can't quite get the pieces to work together. I seem to be missing the step between getting the front matter content, and determining which Nunjuck template to apply.
Here's the section in my Gulp file:
gulp.task('pages:md', function() {
gulp.src('./content/**/*.md')
.pipe(frontMatter({ // optional configuration
property: 'frontMatter', // property added to file object
remove: true // should we remove front-matter header?
}))
.pipe(marked({
// optional : marked options
}))
.pipe(nunjucks({
// ?? Feels like I need to specify which template applies based on the front matter "layout" property?
}))
.pipe(gulp.dest('build/'))
});
The markdown file looks like this:
---
title: Title
layout: layout.html
nav_active: home
---
...markdown content...
I feel like it's going the right direction but being able to visualise where that front matter data has gone, and how to expose it to the Nunjucks rendering, is not clear. Any help?
You need gulp-wrap and original nunjucks.
gulp-nunjucks is a tool for compiling the stream of nunjucks templates, but what you need to do is to wrap your contents in a nunjucks template and that is what gulp-wrap is for.
Try npm install gulp-wrap nunjucks in addition to other settings and then the following should work.
gulpfile
var gulp = require('gulp')
var wrap = require('gulp-wrap')
var frontMatter = require('gulp-front-matter')
var marked = require('gulp-marked')
var fs = require('fs')
gulp.task('pages:md', function() {
gulp.src('./content/**/*.md')
.pipe(frontMatter())
.pipe(marked())
.pipe(wrap(function (data) {
return fs.readFileSync('path/to/layout/' + data.file.frontMatter.layout).toString()
}, null, {engine: 'nunjucks'}))
.pipe(gulp.dest('build/'))
});
markdown
---
title: Title
layout: layout.nunjucks
nav_active: home
---
...markdown content...
layout.nunjucks
<h1>{{ file.frontMatter.title }}</h1>
<p>{{ contents }}</p>
You might want to have a look a the plugin gulp-ssg. I don't know what it's worth, but it was mentionned in this issue for someone who had the same problem as you.
Not exactly what you're looking, but for this kind of work, I've had success using metalsmith. You can even mix it with gulp if, like me, you have more complex processing for your javascripts resources for example.

Creating a style guide / pattern library with gulp

I know there is already a tonne of automated tools to create a style guide / pattern library but in the interest of learning I'd like to see if I can roll my own.
Compiling the SASS is straight forward. Same with the js. I can also see how to wrap blocks of HTML from multiple files with a class and compiled into a single file. Ideal for displaying all the 'partials' together on one page.
gulp.task('inject:wrap', function(){
return gulp.src('./_patterns/*/*/*.html')
/// get the partial html filename here and insert below ###
.pipe(inject.wrap('<div id="###" class="pattern">', '</div>'))
.pipe(concat('patterns.html'))
.pipe(gulp.dest('build'));
});
gulp.task('process', ['inject:wrap']);
What I struggling with is how I can get the filename of the block - let's say _button.html - and pass this to the wrapper as the element id "###" above. Which I can then use to build the style guides navigation / anchor links.
Here's a sample code I've got, uses jade template language (which takes care of injections, partials, evaluation etc. by itself); There are two tasks, one generates static HTML pages, other pre-compiles templates to be used as runtime template functions wrapped in AMD
// preprocess & render jade static templates
gulp.task('views:preprocess', function () {
return gulp.src([ 'source/views/*.jade', '!source/views/layout.jade' ])
.pipe(plumber()) // plumber, because why not?
.pipe(data(function (file) {
// prepare data to be passed to the template
// here we can use the file name to map specific data to each file
return _.assign(settingsData, { timestamp: timestamp });
}))
// render template with data
.pipe(jade())
.pipe(gulp.dest('destination'));
});
// precompile jade runtime templates
gulp.task('views:precompile', function () {
// grab folder names
var folders = fs.readdirSync('source/templates').filter(function (file) {
return fs.statSync(path.join('source/templates', file)).isDirectory();
});
// create a separate task for each folder
var tasks = folders.map(function (folder) {
return gulp.src(path.join('source/templates', folder, '*.jade'))
.pipe(plumber())
// pre-compile the template as functions, for runtime
.pipe(jade({
client: true
}))
// wrap it in AMD, so we can use stuff like require.js to fetch them later
.pipe(wrap({
moduleRoot: 'source/templates',
modulePrefix: 'templates',
deps: [ 'jade' ],
params: [ 'jade' ]
}))
// concat all the templates in each folder to a single .js file
.pipe(concat(folder + '.js'))
.pipe(uglify())
.pipe(header(banner, { package: packageData }))
.pipe(gulp.dest('destination/scripts/templates'));
});
return merge(tasks);
});
Modules I've used are merge-stream, path, gulp, fs, gulp-data, gulp-jade, gulp-plumber etc.
Didn't quite understand what you're trying to achieve, but I hope this gives you some clues.