Skip to content

Commit

Permalink
Add path-specific opts, streamline customization, add linting
Browse files Browse the repository at this point in the history
  • Loading branch information
schneidmaster committed Jan 4, 2017
1 parent c4227cf commit 1128efc
Show file tree
Hide file tree
Showing 31 changed files with 284 additions and 69 deletions.
1 change: 1 addition & 0 deletions .jshintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/*
1 change: 0 additions & 1 deletion .npmignore

This file was deleted.

69 changes: 39 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,69 +10,78 @@ Webpack plugin to generate a sitemap. Designed to work with [static-site-generat

## Usage

Add to your webpack config -- see below for an example. The plugin signature is:
Add to your webpack config -- see below for examples. The plugin signature is:

new SitemapPlugin(base, paths, filename)
new SitemapPlugin(base, paths, options)

* `base` is the root URL of your site (e.g. 'https://mysite.com')
* `paths` is the array of locations on your site -- this can be the same one you pass to `static-site-generator-webpack-plugin`
* `filename` is the name of the output file -- the default is `sitemap.xml`
* `paths` is the array of locations on your site -- this can be the same one you pass to `static-site-generator-webpack-plugin`. If you want to customize each path in the sitemap, you can also pass an array of objects; objects must have a `path` attribute and may have a `lastMod`, `priority`, and/or `changeFreq` attribute. (However, an array of objects will not be directly compatible with `static-site-generator-webpack-plugin`.)
* `options` is an optional object of configurable options -- see below

### Options

* `lastMod` [boolean] default `false`
* `priority` [number] default `null`
* `changeFreq` [string] default `null`, list of applicable values based on [sitemaps.org](http://www.sitemaps.org/protocol.html)

```
always
hourly
daily
weekly
monthly
yearly
never
```
* `fileName` (string) -- default `sitemap.xml` -- name of the output file
* `lastMod` (boolean) -- default `false` -- whether to include the current date as the `<lastmod>`. Can be overridden by path-specific `lastMod`.
* `priority` (number) -- default `null` -- a `<priority>` to be set globally on all locations. Can be overridden by path-specific `priority`.
* `changeFreq` (string) -- default `null` -- a `<changefreq>` to be set globally on all locations; list of applicable values based on [sitemaps.org](http://www.sitemaps.org/protocol.html): `always`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, `never`. Can be overridden by path-specific `changeFreq`.

### webpack.config.js

```js
var SitemapPlugin = require('sitemap-webpack-plugin');

/* basic paths -- directly compatible with static-site-generator-webpack-plugin */
var paths = [
'/foo/',
'/bar/'
];

/* object paths -- more fine-grained but not directly compatible with static-site-generator-webpack-plugin */
/* object paths must have a `path` attribute -- others are optional, and fall back to global config (if any) */
var paths = [
{
path: '/foo/',
lastMod: '2015-01-04',
priority: '0.8',
changeFreq: 'monthly'
}
];

/* you can also convert object paths back into static-site-generator-webpack-plugin compatible paths */
var staticSiteGeneratorCompatiblePaths = paths.map(function(path) { return path.path });

module.exports = {

/* snip */

/* basic (output defaults to sitemap.xml) */
plugins: [
new SitemapPlugin('https://mysite.com', paths, 'map.xml')
new SitemapPlugin('https://mysite.com', paths)
]

/* with options */
/* with custom output filename */
plugins: [
new SitemapPlugin('https://mysite.com', paths, {
fileName: 'map.xml'
})
]

/* with global options */
plugins: [
new SitemapPlugin(
'https://mysite.com',paths, 'map.xml',
{
lastMod: true,
changeFreq: 'monthly',
priority: 0.4,
}
)
new SitemapPlugin('https://mysite.com', paths, {
fileName: 'map.xml',
lastMod: true,
changeFreq: 'monthly',
priority: '0.4'
})
]

};
```



## Contributing

1. Fork it ( https://github.com/schneidmaster/sitemap-webpack-plugin/fork )
1. Fork it (https://github.com/schneidmaster/sitemap-webpack-plugin/fork)
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
Expand Down
3 changes: 3 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
test:
override:
- npm test
- npm run lint
post:
- npm run coveralls
2 changes: 1 addition & 1 deletion date.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ module.exports = function() {
date.splice(0, 0, year);
var formattedDate = date.join("-");
return formattedDate;
}
};
117 changes: 87 additions & 30 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,103 @@
var GenerateDate = require('./date');

function SitemapWebpackPlugin(base, paths, fileName) {
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
var GenerateSitemap = function(self) {
// Validate configuration
if(typeof(self.base) !== 'string') {
throw new Error('Provided base URL is not a string');
} else if(self.base.substr(-1) === '/') {
self.base = self.base.replace(/\/$/, '');
}
if(!Array.isArray(self.paths)) {
throw new Error('Provided paths are not an array');
}

// Create sitemap from paths
var out = '<?xml version="1.0" encoding="UTF-8"?>';
out += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';

var locs = self.paths.map(function(path) {
if(typeof(path) === 'object') {
if(typeof(path.path) !== 'string') {
throw new Error('Path is not a string: ' + path);
}
} else if(typeof(path) === 'string') {
path = { path: path };
} else {
throw new Error('Path is not a string: ' + path);
}

var loc = '<url>';

var stringPath = path.path;
if(stringPath.substr(0, 1) !== '/') {
stringPath = '/' + path.path;
}
loc += '<loc>' + self.base + stringPath + '</loc>';

// Add loc lastMod or default if set.
if(path.lastMod) {
loc += '<lastmod>' + path.lastMod + '</lastmod>';
} else if(self.lastMod) {
loc += '<lastmod>' + GenerateDate() + '</lastmod>';
}

// Add loc changeFreq or default if set.
if(path.changeFreq) {
loc += '<changefreq>' + path.changeFreq + '</changefreq>';
} else if(self.changeFreq) {
loc += '<changefreq>' + self.changeFreq + '</changefreq>';
}

// Add loc priority or default if set.
if(path.priority) {
loc += '<priority>' + path.priority + '</priority>';
} else if(self.priority) {
loc += '<priority>' + self.priority + '</priority>';
}

loc += '</url>';
return loc;
});

out += locs.join('');
out += '</urlset>';
return out;
};

function SitemapWebpackPlugin(base, paths, options) {
// Set mandatory values
this.base = base;
this.paths = paths;

// Set options
if(typeof(options) === 'undefined') {
options = {};
}
this.fileName = options.fileName || 'sitemap.xml';
this.lastMod = options.lastMod || false;
this.changeFreq = options.changeFreq || null;
this.priority = options.priority || null;

this.base = base;
this.paths = paths;
this.fileName = fileName || 'sitemap.xml';
}

SitemapWebpackPlugin.prototype.apply = function(compiler) {
var self = this;

// Create sitemap from paths
var out = '<?xml version="1.0" encoding="UTF-8"?>';
out += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
for(var i = 0; i < self.paths.length; i++) {
var path = self.paths[i];

out += '<url>';
out += '<loc>' + self.base + path + '</loc>';
self.lastMod ? out += '<lastmod>' + GenerateDate() + '</lastmod>' : null;
self.changeFreq ? out += '<changefreq>' + self.changeFreq + '</changefreq>' : null;
self.priority ? out += '<priority>' + self.priority + '</priority>' : null;
out += '</url>';
}
out += '</urlset>';

compiler.plugin('emit', function(compilation, callback) {
compilation.fileDependencies.push(self.fileName);
compilation.assets[self.fileName] = {
source: function () {
return out;
},
size: function () {
return Buffer.byteLength(out, 'utf8');
}
};
try {
var sitemap = GenerateSitemap(self);

compilation.fileDependencies.push(self.fileName);
compilation.assets[self.fileName] = {
source: function () {
return sitemap;
},
size: /* istanbul ignore next */ function () {
return Buffer.byteLength(out, 'utf8');
}
};
} catch (err) {
compilation.errors.push(err.stack);
}
callback();
});
};
Expand Down
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
{
"name": "sitemap-webpack-plugin",
"version": "0.1.2",
"version": "0.2.0",
"description": "Webpack plugin to generate a sitemap.",
"main": "index.js",
"scripts": {
"test": "istanbul cover _mocha test -- --timeout 20000",
"coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
"coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage",
"lint": "jshint ./**/*.js"
},
"jshintConfig": {
"expr": true
},
"repository": {
"type": "git",
Expand All @@ -29,6 +33,7 @@
"coveralls": "^2.11.15",
"glob": "^7.1.1",
"istanbul": "^0.4.5",
"jshint": "^2.9.4",
"mocha": "^3.2.0",
"rimraf": "^2.5.4",
"timecop": "git+https://github.com/jamesarosen/Timecop.js.git",
Expand Down
1 change: 1 addition & 0 deletions test/error-cases/invalid-path/desc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 'Invalid path in paths array';
1 change: 1 addition & 0 deletions test/error-cases/invalid-path/expected-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 'Error: Path is not a string: 42';
13 changes: 13 additions & 0 deletions test/error-cases/invalid-path/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var SitemapPlugin = require('../../../');

module.exports = {
output: {
filename: 'index.js',
path: __dirname + '/actual-output',
libraryTarget: 'umd'
},

plugins: [
new SitemapPlugin('https://mysite.com', [42])
]
};
1 change: 1 addition & 0 deletions test/error-cases/invalid-paths/desc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 'Invalid object passed for paths array';
1 change: 1 addition & 0 deletions test/error-cases/invalid-paths/expected-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 'Error: Provided paths are not an array';
13 changes: 13 additions & 0 deletions test/error-cases/invalid-paths/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var SitemapPlugin = require('../../../');

module.exports = {
output: {
filename: 'index.js',
path: __dirname + '/actual-output',
libraryTarget: 'umd'
},

plugins: [
new SitemapPlugin('https://mysite.com', 'fail')
]
};
1 change: 1 addition & 0 deletions test/error-cases/missing-base/desc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 'Base URL is not a string';
1 change: 1 addition & 0 deletions test/error-cases/missing-base/expected-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 'Error: Provided base URL is not a string';
13 changes: 13 additions & 0 deletions test/error-cases/missing-base/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var SitemapPlugin = require('../../../');

module.exports = {
output: {
filename: 'index.js',
path: __dirname + '/actual-output',
libraryTarget: 'umd'
},

plugins: [
new SitemapPlugin(null, ['/', '/about'])
]
};
1 change: 1 addition & 0 deletions test/error-cases/missing-object-path/desc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 'Path object is missing path attribute';
1 change: 1 addition & 0 deletions test/error-cases/missing-object-path/expected-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 'Error: Path is not a string: [object Object]';
13 changes: 13 additions & 0 deletions test/error-cases/missing-object-path/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var SitemapPlugin = require('../../../');

module.exports = {
output: {
filename: 'index.js',
path: __dirname + '/actual-output',
libraryTarget: 'umd'
},

plugins: [
new SitemapPlugin('https://mysite.com', [{ priority: '1.0' }])
]
};
Loading

0 comments on commit 1128efc

Please sign in to comment.