Skip to content

Commit

Permalink
Trim index.js, improve modularity and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pgilad committed Jun 21, 2014
1 parent 24f815a commit 2504b5d
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 153 deletions.
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) [2014] [Gilad Peleg]
Copyright ©2014 Gilad Peleg

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
Expand Down
123 changes: 38 additions & 85 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,69 +1,37 @@
'use strict';
var gutil = require('gulp-util');
var slash = require('slash');
var through = require('through2');
/* needed to get mstats of a file parsed with data only */
var fs = require('fs');
var path = require('path');

var xmlHeader = ['<?xml version="1.0" encoding="UTF-8"?>',
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
];
var gutil = require('gulp-util');
var through = require('through2');
var defaults = require('lodash.defaults');
var sitemap = require('./lib/sitemap');

module.exports = function (params) {
params = params || {};
//first file to capture cwd
var firstFile;
//set newline separator
var newLine = params.newLine || gutil.linefeed;
//default output filename
var fileName = params.fileName || 'sitemap.xml';
//set default change frequency
var changeFreq = params.changeFreq || 'daily';
//set default priority
var priority = params.priority && params.priority.toString() || '0.5';
var siteUrl;
//set xml spacing. can be \t for tabs
var spacing = params.spacing || ' ';
//array to hold lines of output sitemap.xml
var xmlOutput = [].concat(xmlHeader);

/**
* addFile
*
* @param file
* @param lastmod
* @param spacing
* @param cb
* @return
*/
var addFile = function (filename, lastmod, cb) {
//format mtime to ISO (same as +00:00)
lastmod = new Date(lastmod).toISOString();
//turn index.html into -> /
var relativeFile = filename.replace(/(index)\.(html?){1}$/, '', 'i');
//url location. Use slash to convert windows \\ or \ to /
var loc = siteUrl + slash(relativeFile);

//push file to xml
xmlOutput.push(spacing + '<url>');
xmlOutput.push(spacing + spacing + '<loc>' + loc + '</loc>');
xmlOutput.push(spacing + spacing + '<lastmod>' + lastmod + '</lastmod>');
xmlOutput.push(spacing + spacing + '<changefreq>' + changeFreq + '</changefreq>');
xmlOutput.push(spacing + spacing + '<priority>' + priority + '</priority>');
xmlOutput.push(spacing + '</url>');

return cb();
};

if (!params.siteUrl) {
siteUrl = null;
} else {
siteUrl = params.siteUrl;
//ensure trailing slash
if (siteUrl.slice(-1) !== '/') {
siteUrl += '/';
}
throw new gutil.PluginError('gulp-todo', 'siteUrl is a required param');
}
var config = defaults(params, {
//set newline separator
newLine: gutil.linefeed,
//default output filename
fileName: 'sitemap.xml',
//set default change frequency
changeFreq: 'daily',
//set xml spacing. can be \t for tabs
spacing: ' ',
//set default priority
priority: '0.5'
});
//enforce priority to be a string
config.priority = config.priority.toString();
//ensure siteUrl ends with a slash
if (config.siteUrl.slice(-1) !== '/') {
config.siteUrl += '/';
}
//first file to capture cwd
var firstFile, entries = [];

return through.obj(function (file, enc, cb) {
//pass through empty file
Expand All @@ -72,16 +40,12 @@ module.exports = function (params) {
return cb();
}

//we don't handle streams for now
if (file.isStream()) {
this.emit('error', new gutil.PluginError('gulp-sitemap', 'Streaming not supported'));
return cb();
}

if (!siteUrl) {
this.emit('error', new gutil.PluginError('gulp-sitemap', 'siteUrl is a required param'));
return cb();
}

//skip 404 file
if (/404\.html?$/i.test(file.relative)) {
return cb();
Expand All @@ -94,51 +58,40 @@ module.exports = function (params) {

//if file has stat.mtime use it
if (file.stat && file.stat.mtime) {
//get modified time
var lastmod = file.stat.mtime;
//add file to xml
return addFile(file.relative, lastmod, cb);
entries = entries.concat(sitemap.processFile(file.relative, file.stat.mtime, config));
return cb();
}

//otherwise get it from file using fs
fs.stat(file.path, function (err, stats) {
if (err || !stats || !stats.mtime) {
//file not found
//file not found - skip it
if (err.code === 'ENOENT') {
//skip it
return cb();
}
err = err || 'No stats found for file ' + file.path;
this.emit('error', new gutil.PluginError('gulp-sitemap', err));
return cb();
}

//add file to xml
return addFile(file.relative, stats.mtime, cb);
entries = entries.concat(sitemap.processFile(file.relative, stats.mtime, config));
return cb();
}.bind(this));
},
function (cb) {
if (!firstFile) {
//no files
return cb();
}
//close off urlset
xmlOutput.push('</urlset>');
//build as string
var sitemapContent = xmlOutput.join(newLine);

//create vinyl file
var sitemapFile = new gutil.File({
//create and push new vinyl file for sitemap
this.push(new gutil.File({
cwd: firstFile.cwd,
base: firstFile.base,
path: path.join(firstFile.base, fileName),
contents: new Buffer(sitemapContent)
});

//push file to stream
this.push(sitemapFile);
gutil.log('Generated', gutil.colors.blue(fileName));
path: path.join(firstFile.base, config.fileName),
contents: new Buffer(sitemap.prepareSitemap(entries, config))
}));

gutil.log('Generated', gutil.colors.blue(config.fileName));
return cb();
});
};
48 changes: 48 additions & 0 deletions lib/sitemap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict';
var slash = require('slash');

//TODO: export this to an external module

var xmlHeader = [
'<?xml version="1.0" encoding="UTF-8"?>',
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
];

var prepareSitemap = function (entries, config) {
//insert xml heaader
entries.unshift(xmlHeader);
//close off urlset
entries.push('</urlset>');
return entries.join(config.newLine);
};

/**
* processFile
*
* @param filename
* @param lastmod
* @param config
* @return {Array}
*/
var processFile = function (filename, lastmod, config) {
//format mtime to ISO (same as +00:00)
lastmod = new Date(lastmod).toISOString();
//turn index.html into -> /
var relativeFile = filename.replace(/(index)\.(html?){1}$/, '', 'i');
//url location. Use slash to convert windows \\ or \ to /
var loc = config.siteUrl + slash(relativeFile);
var returnArr = [];

//push file to xml
//TODO: skip spacing and use an xml beautifier
returnArr.push(config.spacing + '<url>');
returnArr.push(config.spacing + config.spacing + '<loc>' + loc + '</loc>');
returnArr.push(config.spacing + config.spacing + '<lastmod>' + lastmod + '</lastmod>');
returnArr.push(config.spacing + config.spacing + '<changefreq>' + config.changeFreq + '</changefreq>');
returnArr.push(config.spacing + config.spacing + '<priority>' + config.priority + '</priority>');
returnArr.push(config.spacing + '</url>');
return returnArr;
};

exports.prepareSitemap = prepareSitemap;
exports.processFile = processFile;
98 changes: 50 additions & 48 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,50 +1,52 @@
{
"name": "gulp-sitemap",
"version": "0.2.6",
"description": "Generate a search engine friendly sitemap.xml using a Gulp stream",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/pgilad/gulp-sitemap"
},
"homepage": "https://github.com/pgilad/gulp-sitemap",
"bugs": "https://github.com/pgilad/gulp-sitemap/issues",
"author": {
"name": "Gilad Peleg",
"email": "[email protected]"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js",
"LICENSE.md"
],
"scripts": {
"watchTest": "mocha -R spec --watch test/test.js",
"test": "mocha test/test.js"
},
"main": "index.js",
"keywords": [
"gulpplugin",
"gulp",
"js",
"javascript",
"seo",
"sitemap",
"sitemap.xml",
"google",
"search-engine",
"xml"
],
"dependencies": {
"gulp-util": "~2.2.12",
"slash": "^0.1.3",
"through2": "^0.5.1"
},
"devDependencies": {
"gulp": "^3.6.2",
"mocha": "^1.19.0",
"should": "^4.0.4"
}
"name": "gulp-sitemap",
"version": "0.2.6",
"description": "Generate a search engine friendly sitemap.xml using a Gulp stream",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/pgilad/gulp-sitemap"
},
"homepage": "https://github.com/pgilad/gulp-sitemap",
"bugs": "https://github.com/pgilad/gulp-sitemap/issues",
"author": {
"name": "Gilad Peleg",
"email": "[email protected]"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js",
"LICENSE.md",
"lib"
],
"scripts": {
"watchTest": "mocha -R spec --watch test/test.js",
"test": "mocha test/test.js -R spec"
},
"main": "index.js",
"keywords": [
"gulpplugin",
"gulp",
"js",
"javascript",
"seo",
"sitemap",
"sitemap.xml",
"google",
"search-engine",
"xml"
],
"dependencies": {
"gulp-util": "~2.2.12",
"lodash.defaults": "^2.4.1",
"slash": "^0.1.3",
"through2": "^0.5.1"
},
"devDependencies": {
"gulp": "^3.6.2",
"mocha": "^1.19.0",
"should": "^4.0.4"
}
}
28 changes: 9 additions & 19 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,19 @@
/* global it */
'use strict';
var should = require('should');
var gutil = require('gulp-util');
var gulp = require('gulp');
var fs = require('fs');
var sitemap = require('../index');

it('should throw if not provided with site url', function (cb) {
var stream = sitemap();
var testedFile = 'test/fixtures/test.html';

stream.on('error', function (err) {
should.exist(err);
err.name.should.equal('Error');
err.message.should.equal('siteUrl is a required param');
cb();
});

stream.write(new gutil.File({
cwd: __dirname,
base: __dirname,
path: testedFile,
contents: new Buffer('hello there')
}));

stream.end();
it('should throw if not provided with site url', function () {
try {
sitemap();
} catch (e) {
e.should.containEql({
message: 'siteUrl is a required param'
});
}
});

it('should generate a sitemap.xml using default values', function (cb) {
Expand Down

0 comments on commit 2504b5d

Please sign in to comment.