Skip to content

Instantly share code, notes, and snippets.

@chrisgonzalez
Last active August 29, 2015 14:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisgonzalez/979bf20908b8743f0524 to your computer and use it in GitHub Desktop.
Save chrisgonzalez/979bf20908b8743f0524 to your computer and use it in GitHub Desktop.
Buildify Script for CSS and JS tag replacement and minification
/**
* This file will replace blocks of script tags or css link tags nested between comments
* in html or any text file with the minified equivalents. The structure is as follows:
*
* For JavaScript:
* <!-- scripts [output file name w/ directory] -->
* [<script> tags live here]
* <!-- /scripts [output file name w/directory (matches above)] -->
*
* For CSS:
* <!-- styles [output file name w/ directory] -->
* [style <link> tags live here]
* <!-- /styles [output file name w/directory (matches above)] -->
*
* You can insert as many of these blocks as you'd like in your html/other file,
* all will be replaced with a single <link> or <script> per block, referencing
* the file name and path you specified in the opening comment. While it's not
* necessary to have the opening comment match the closing comment, they do need
* to be unique per block, as regex is annoying :)
*
* All files will be output to a /dist directory, and the html file will be output
* as index.html in the /dist directory. Look to line 94 for the index.html file name
* and look for /dist if you'd like to change the output directory.
*
**/
var buildify = require('buildify'),
scripts = [],
styles = [];
// extract all comments: /<!--[\s\S]*?-->/g
// match anything between two (word)[\s\S]*(word)
buildify('src')
.load('index.html')
.perform(function(content) {
var i, j, outputFileName,
comments = content.match(/<!--[\s\S]*?-->/g);
// for each matching set of comments w/ filename
for (i = 0; i < comments.length; i+=2) {
// check that comment is of the type to parse (skip if it isn't!)
while (comments[i].indexOf('scripts') < 0 && comments[i].indexOf('styles') < 0) {
i++;
}
// opening and closing comment
var opening = comments[i],
closing = comments[i+1];
// take entire block of scripts or styles
var regex = new RegExp('(' + opening + ')[\\s\\S]*' + '(' + closing + ')', 'gi');
var enclosed = content.match(regex)[0];
// if the match is a scripts block
if (enclosed.indexOf('scripts') > -1) {
console.log('Found a script block!');
// parse out the file name
outputFileName = opening.replace('<!-- scripts', '').replace('-->', '').trim();
// parse out the src attributes
var scriptSrc = enclosed.match(/src=\"[\s\S]*?\"/gi);
var scriptFiles = [];
for (j = 0; j < scriptSrc.length; j++) {
// strip out src and quotes
var src = scriptSrc[j].replace('src="', '').replace('"', '');
scriptFiles.push(src);
}
// push a record for the build
scripts.push({
filename: outputFileName,
files: scriptFiles
});
// replace the whole block with a single script
content = content.replace(regex, '<script src="' + outputFileName + '"></script>')
// else if we've found a styles block
} else if (enclosed.indexOf('styles') > -1) {
console.log('Found a styles block!');
// extract the desired css filename
outputFileName = opening.replace('<!-- styles', '').replace('-->', '').trim();
// find the href attributes
var linkHref = enclosed.match(/href=\"[\s\S]*?\"/gi);
var styleFiles = [];
// parse out the desired file name
for (j = 0; j < linkHref.length; j++) {
var href = linkHref[j].replace('href="', '').replace('"', '');
styleFiles.push(href);
}
// push a record of the stylesheet for the build
styles.push({
filename: outputFileName,
files: styleFiles
});
// replace the whole block with a single stylesheet <link>
content = content.replace(regex, '<link type="text/css" rel="stylesheet" href="' + outputFileName + '" />');
}
}
return content;
})
// change directory to 'dist'
.changeDir('../dist')
// save the file
.save('index.html');
// for each script record
for (var i = 0; i < scripts.length; i++) {
// if it starts with '/' ie a root file, strip out the slash for finding it here
if (scripts[i].filename.charAt(0) === '/' ) {
scripts[i].filename = scripts[i].filename.substring(1);
}
// if more than one script, concat then uglify then save
if (scripts[i].files.length > 1) {
buildify('src')
.load(scripts[i].files[0])
.concat(scripts[i].files.slice(1))
.uglify()
.changeDir('../')
.save('dist/' + scripts[i].filename);
// else just uglify and save
} else {
buildify('src')
.load(scripts[i].files[0])
.uglify()
.changeDir('../')
.save('dist/' + scripts[i].filename);
}
}
// for each style record
for (var j = 0; j < styles.length; j++) {
// if it's got a '/', strip that out so we can find the file
if (styles[j].filename.charAt(0) === '/' ) {
styles[j].filename = styles[j].filename.substring(1);
}
// if there's more than one style in the block, concat, minify then save
if (styles[j].files.length > 1) {
buildify('src')
.load(styles[j].files[0])
.concat(styles[j].files.slice(1))
.cssmin()
.changeDir('../')
.save('dist/' + styles[j].filename);
// else just minify and save
} else {
buildify('src')
.load(styles[j].files[0])
.cssmin()
.changeDir('../')
.save('dist/' + styles[j].filename);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment