Skip to content

Commit

Permalink
add websitePath for those using subdirectories on your website
Browse files Browse the repository at this point in the history
add srcPathRemove for removing unwanted template code such as {$basePath}
  • Loading branch information
jamesj2 committed Sep 18, 2014
1 parent 5fe84ae commit 9b66d9c
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 151 deletions.
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ If exist used for modify files. If does not contain string 'concat', then it add
Type: `String`
Relative location to html file for new concatenated js and css.

#### websitePath
Type: `String`
Website base path for new concatenated js and css.

#### srcPathRemove
Type: `Array`
List of string or regex to remove from script path. Useful for template paths.

## Use case

```
Expand All @@ -107,12 +115,12 @@ Relative location to html file for new concatenated js and css.
We want to optimize `foo.js` and `bar.js` into `optimized.js`, referenced using relative path. `index.html` should contain the following block:

```
<!-- build:css style.css -->
<!-- build:css {destination}style.css -->
<link rel="stylesheet" href="css/clear.css"/>
<link rel="stylesheet" href="css/main.css"/>
<!-- endbuild -->
<!-- build:js js/optimized.js -->
<!-- build:js {destination}js/optimized.js -->
<script src="assets/js/foo.js"></script>
<script src="assets/js/bar.js"></script>
<!-- endbuild -->
Expand Down
317 changes: 168 additions & 149 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,168 +7,187 @@ var gutil = require('gulp-util');
var glob = require('glob');

module.exports = function(options) {
options = options || {};
var startReg = /<!--\s*build:(\w+)(?:\(([^\)]+?)\))?\s+(\/?([^\s]+?))?\s*-->/gim;
var endReg = /<!--\s*endbuild\s*-->/gim;
var jsReg = /<\s*script\s+.*?src\s*=\s*("|')([^"']+?)\1.*?><\s*\/\s*script\s*>/gi;
var cssReg = /<\s*link\s+.*?href\s*=\s*("|')([^"']+)\1.*?>/gi;
var startCondReg = /<!--\[[^\]]+\]>/gim;
var endCondReg = /<!\[endif\]-->/gim;
var basePath, mainPath, mainName, alternatePath;

function createFile(name, content) {
var filePath = path.join(path.relative(basePath, mainPath), name)
var isStatic = name.split('.').pop() === 'js' || name.split('.').pop() === 'css'

if (options.outputRelativePath && isStatic)
filePath = options.outputRelativePath + name;

return new gutil.File({
path: filePath,
contents: new Buffer(content)
})
}

function getBlockType(content) {
return jsReg.test(content) ? 'js' : 'css';
}

function getFiles(content, reg) {
var paths = [];
var files = [];

content
.replace(startCondReg, '')
.replace(endCondReg, '')
.replace(/<!--(?:(?:.|\r|\n)*?)-->/gim, '')
.replace(reg, function (a, quote, b) {
var filePath = path.resolve(path.join(alternatePath || mainPath, b));

if (options.assetsDir)
filePath = path.resolve(path.join(options.assetsDir, path.relative(basePath, filePath)));

paths.push(filePath);
});

for (var i = 0, l = paths.length; i < l; ++i) {
var filepaths = glob.sync(paths[i]);
if(filepaths[0] === undefined) {
throw new gutil.PluginError('gulp-usemin', 'Path ' + paths[i] + ' not found!');
}
filepaths.forEach(function (filepath) {
files.push(new gutil.File({
path: filepath,
contents: fs.readFileSync(filepath)
}));
});
options = options || {};
var startReg = /<!--\s*build:(\w+)(?:\(([^\)]+?)\))?\s+(\/?([^\s]+?))?\s*-->/gim;
var endReg = /<!--\s*endbuild\s*-->/gim;
var jsReg = /<\s*script\s+.*?src\s*=\s*("|')([^"']+?)\1.*?><\s*\/\s*script\s*>/gi;
var cssReg = /<\s*link\s+.*?href\s*=\s*("|')([^"']+)\1.*?>/gi;
var startCondReg = /<!--\[[^\]]+\]>/gim;
var endCondReg = /<!\[endif\]-->/gim;
var basePath, mainPath, mainName, alternatePath;

function createFile(name, content) {
var filePath = path.join(path.relative(basePath, mainPath), name);
var isStatic = name.split('.').pop() === 'js' || name.split('.').pop() === 'css';

if (options.outputRelativePath && isStatic)
filePath = options.outputRelativePath + name;

return new gutil.File({
path: filePath,
contents: new Buffer(content)
})
}

return files;
}

function concat(files, name) {
var buffer = [];
function getBlockType(content) {
return jsReg.test(content) ? 'js' : 'css';
}

files.forEach(function(file) {
buffer.push(String(file.contents));
});
function getFiles(content, reg) {
var paths = [];
var files = [];

content
.replace(startCondReg, '')
.replace(endCondReg, '')
.replace(/<!--(?:(?:.|\r|\n)*?)-->/gim, '')
.replace(reg, function (a, quote, b) {
if (options.srcPathRemove) {
for (var i = 0; i < options.srcPathRemove.length; i++) {
b = b.replace(options.srcPathRemove[i],'');
}
}

var filePath = path.resolve(path.join(alternatePath || mainPath, b));

if (options.assetsDir)
filePath = path.resolve(path.join(options.assetsDir, path.relative(basePath, filePath)));

paths.push(filePath);
});

for (var i = 0, l = paths.length; i < l; ++i) {
var filepaths = glob.sync(paths[i]);
if(filepaths[0] === undefined) {
throw new gutil.PluginError('gulp-usemin', 'Path ' + paths[i] + ' not found!');
}
filepaths.forEach(function (filepath) {
files.push(new gutil.File({
path: filepath,
contents: fs.readFileSync(filepath)
}));
});
}
//console.log(filepaths);
// console.log(files);
return files;
}

return createFile(name, buffer.join(EOL));
}
function concat(files, name) {
var buffer = [];

function processTask(index, tasks, name, files, callback) {
var newFiles = [];
files.forEach(function(file) {
buffer.push(String(file.contents));
});

if (tasks[index] == 'concat') {
newFiles = [concat(files, name)];
}
else {
var stream = tasks[index];

function write(file) {
newFiles.push(file);
}

stream.on('data', write);
files.forEach(function(file) {
stream.write(file);
});
stream.removeListener('data', write);
return createFile(name, buffer.join(EOL));
}

if (tasks[++index])
processTask(index, tasks, name, newFiles, callback);
else
newFiles.forEach(callback);
}

function process(name, files, pipelineId, callback) {
var tasks = options[pipelineId] || [];
if (tasks.indexOf('concat') == -1)
tasks.unshift('concat');

processTask(0, tasks, name, files, callback);
}

function processHtml(content, push, callback) {
var html = [];
var sections = content.split(endReg);

for (var i = 0, l = sections.length; i < l; ++i) {
if (sections[i].match(startReg)) {
var section = sections[i].split(startReg);
alternatePath = section[2];

html.push(section[0]);

var startCondLine = section[5].match(startCondReg);
var endCondLine = section[5].match(endCondReg);
if (startCondLine && endCondLine)
html.push(startCondLine[0]);

if (section[1] !== 'remove') {
if (getBlockType(section[5]) == 'js') {
process(section[4], getFiles(section[5], jsReg), section[1], function(name, file) {
push(file);
if (path.extname(file.path) == '.js')
html.push('<script src="' + name.replace(path.basename(name), path.basename(file.path)) + '"></script>');
}.bind(this, section[3]));
} else {
process(section[4], getFiles(section[5], cssReg), section[1], function(name, file) {
push(file);
html.push('<link rel="stylesheet" href="' + name.replace(path.basename(name), path.basename(file.path)) + '"/>');
}.bind(this, section[3]));
}
}
function processTask(index, tasks, name, files, callback) {
var newFiles = [];

if (startCondLine && endCondLine) {
html.push(endCondLine[0]);
if (tasks[index] == 'concat') {
newFiles = [concat(files, name)];
}
else {
var stream = tasks[index];

function write(file) {
newFiles.push(file);
}

stream.on('data', write);
files.forEach(function(file) {
stream.write(file);
});
stream.removeListener('data', write);
}
} else {
html.push(sections[i]);
}
}
process(mainName, [createFile(mainName, html.join(''))], 'html', function(file) {
push(file);
callback();
});
}

return through.obj(function(file, enc, callback) {
if (file.isNull()) {
this.push(file); // Do nothing if no contents
callback();
if (tasks[++index])
processTask(index, tasks, name, newFiles, callback);
else
newFiles.forEach(callback);
}
else if (file.isStream()) {
this.emit('error', new gutil.PluginError('gulp-usemin', 'Streams are not supported!'));
callback();

function process(name, files, pipelineId, callback) {
var tasks = options[pipelineId] || [];
if (tasks.indexOf('concat') == -1)
tasks.unshift('concat');

processTask(0, tasks, name, files, callback);
}
else {
basePath = file.base;
mainPath = path.dirname(file.path);
mainName = path.basename(file.path);

processHtml(String(file.contents), this.push.bind(this), callback);
function processHtml(content, push, callback) {
var html = [];
var sections = content.split(endReg);
var srcPath = null;

for (var i = 0, l = sections.length; i < l; ++i) {
if (sections[i].match(startReg)) {
var section = sections[i].split(startReg);
alternatePath = section[2];

html.push(section[0]);

var startCondLine = section[5].match(startCondReg);
var endCondLine = section[5].match(endCondReg);
if (startCondLine && endCondLine)
html.push(startCondLine[0]);

if (section[1] !== 'remove') {
if (getBlockType(section[5]) == 'js') {
process(section[4], getFiles(section[5], jsReg), section[1], function(name, file) {
push(file);
if (path.extname(file.path) == '.js') {
srcPath = name.replace(path.basename(name), path.basename(file.path));

if (options.websitePath)
srcPath = options.websitePath + srcPath;

html.push('<script src="' + srcPath + '"></script>');
}
}.bind(this, section[3]));
} else {
process(section[4], getFiles(section[5], cssReg), section[1], function(name, file) {
push(file);
srcPath = name.replace(path.basename(name), path.basename(file.path));

if (options.websitePath)
srcPath = options.websitePath + srcPath;

html.push('<link rel="stylesheet" href="' + srcPath + '"/>');
}.bind(this, section[3]));
}
}

if (startCondLine && endCondLine) {
html.push(endCondLine[0]);
}
} else {
html.push(sections[i]);
}
}
process(mainName, [createFile(mainName, html.join(''))], 'html', function(file) {
push(file);
callback();
});
}
});

return through.obj(function(file, enc, callback) {
if (file.isNull()) {
this.push(file); // Do nothing if no contents
callback();
}
else if (file.isStream()) {
this.emit('error', new gutil.PluginError('gulp-usemin', 'Streams are not supported!'));
callback();
}
else {
basePath = file.base;
mainPath = path.dirname(file.path);
mainName = path.basename(file.path);

processHtml(String(file.contents), this.push.bind(this), callback);
}
});
};

0 comments on commit 9b66d9c

Please sign in to comment.