Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
node.js script to inline static includes
<!DOCTYPE html>
<!-- #include "inc_header.html" title="Example" header="Sample Title" -->
<html>
<head>
<meta charset="utf-8">
<title>Example</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<h1>Sample Title</h1>
<!-- endinclude -->
<div role="main">
content goes here
</div>
<!-- #include "inc_footer.html" msg="yeah" -->
<footer>yeah</footer>
<!-- endinclude -->
</body>
</html>
<html>
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<h1>{{header}}</h1>
#!/usr/bin/env node
// This script will search for HTML files on the root folder and process
// static includes wrapped by the HTML comments like this:
//
// <!-- #include "example/foo.html" -->
// anything wrapped by these comments will be replaced
// by the content of the "example/foo.html" file
// <!-- endinclude -->
//
// You can also add some replacements to the include using a mustache-like
// syntax (only basic replacements are supported so far):
//
// <!-- #include "inc/header.html" title="Example Title" foo="bar" -->
// the copy inside {{title}} and {{foo}} will be replaced.
// <!-- endinclude -->
//
// Author: Miller Medeiros
// Version: 0.2.0 (2012/08/28)
// ---
var _glob = require('glob');
var _fs = require('fs');
var FILE_ENCODING = 'utf-8';
// ---
// $1 = include start
// $2 = file name
// $3 = props
// $4 = content
// $5 = end include
//
var _reInc = /(^\s*<!--\s*\#include\s*["']([^"']+)["']\s*(.+)?\s*-->\s*$)([\s\S]*?)(^\s*<!--\s*end\s*include\s*-->\s*$)/gm;
// $1 = prop name
// $2 = value
var _reProp = /([-_\w]+)\s*=\s*["']([^"']+)["']/g;
// mustache-like syntax
var _reStache = /\{\{([-_\w]+)\}\}/g;
// ---
_glob('./*.html', function(err, files){
if (err) throw err;
files.forEach(function(filePath){
_fs.readFile(filePath, FILE_ENCODING, function(err, data){
if (err) throw err;
data = data.replace(_reInc, function(match, includeStart, fileName, props, content, includeEnd){
content = _fs.readFileSync(fileName, FILE_ENCODING);
content = interpolate( content, parseProps(props) );
return includeStart +'\n'+ content + includeEnd;
});
_fs.writeFile(filePath, data, FILE_ENCODING, function(err){
if (err) throw err;
console.log('updated: '+ filePath);
});
});
});
});
function parseProps(props){
var obj = {};
var match;
while (match = _reProp.exec(props)) {
obj[ match[1] ] = match[2];
}
return obj;
}
// borrowed from amd-utils/string/interpolate
function interpolate(template, data, regexp){
function replaceFn(match, prop){
return (prop in data)? data[prop] : '';
}
return template.replace(regexp || _reStache, replaceFn);
}
@millermedeiros
Copy link
Author

My current project have ~5 static pages that shares the same header and footer so I wrote this simple script to inline external files based on comments on the markup so I can keep all files in sync without having to manually update them. It could be further extended to support variables/arguments but for now that isn't needed.

automate all things!

@rafaelrinaldi
Copy link

This is very cool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment