diff --git a/cli.js b/cli.js index d33efdd..b1668b8 100755 --- a/cli.js +++ b/cli.js @@ -98,6 +98,7 @@ module.exports = { const destination = flags.dest.replace(/^\/|\/$/g, ''); const baseurl = flags.baseurl.replace(/^\/|\/$/g, ''); const sitemap = (flags.sitemap || 'sitemap.xml').replace(/^\/|\/$/g, ''); + const rss = (flags.rss || '').replace(/^\/|\/$/g, ''); const port = this.checkPortNumber(flags.port) || defaultPort; const split = flags.split || 1; @@ -112,6 +113,7 @@ module.exports = { dest: destination, baseurl: baseurl, sitemap: sitemap, + rss: rss, fullPathToSource: path.resolve(cwd, source), fullPathToDest: path.resolve(cwd, destination, baseurl) }, diff --git a/index.js b/index.js index 475e6f5..dc80c00 100755 --- a/index.js +++ b/index.js @@ -11,7 +11,7 @@ Commands: clone-assets Clones non CSS and HTML files from src to dest rewrite-css Clones CSS files from src to dest and rewrites urls to include baseurl rewrite-html Clones HTML files from src to dest and rewrites attributes to include baseurl - rewrite-sitemap Finds all sitemap files based on index sitemap, and rewrites links to include baseurl + rewrite-sitemap Finds all sitemap files based on index sitemap, and rewrites links to include baseurl serve Runs 'build' then a local webserver on the dest folder watch Watches the src folder and triggers builds @@ -24,7 +24,8 @@ Options: -b | --baseurl The base-URL to prepend to the files once copied -p | --port The portnumber to serve the cloned site on -e | --extrasrc A list of extra src attributes to be rewritten - -m | --sitemap A path to a valid sitemap file + -m | --sitemap A path to a valid sitemap or sitemapindex file + -r | --rss A path to a valid RSS file -o | --overwrite When cleaning --dest, don't prompt for confirmation --split The number of partitions to divide files into --partition The partition number to process @@ -59,6 +60,10 @@ const inputs = meow( alias: 'e', isMultiple: true }, + rss: { + type: 'string', + alias: 'r' + }, sitemap: { type: 'string', alias: 'm' diff --git a/lib/processors/sitemap.js b/lib/processors/xml.js similarity index 81% rename from lib/processors/sitemap.js rename to lib/processors/xml.js index 55fe114..06b2ec6 100644 --- a/lib/processors/sitemap.js +++ b/lib/processors/xml.js @@ -36,21 +36,32 @@ function rewriteXML(xml, baseurl) { } }); - $('xhtml\\:link').each(function () { + $('link').each(function () { const $el = $(this); - const originalValue = $el.attr('href'); + const originalValue = $el.text(); const updated = rewritePath(baseurl, originalValue); - $el.attr('href', updated); + $el.text(updated); + }); + + $('[href]').each(function () { + const $el = $(this); + const href = $el.attr('href'); + const updated = rewritePath(baseurl, href); + + if (updated !== href) { + $el.attr('href', updated); + } }); + return $.xml(); } module.exports = { rewrite: rewriteXML, - /** Handles rewriting urls in sitemap(s) + /** Handles rewriting urls in xml(s) * - * @param {string} file the absolute path to the sitemap file. + * @param {string} file the absolute path to the xml file. * @param {string} destination the absolute path to the destination directory. * @param {string} baseurl the baseurl to prepend to the source files. */ diff --git a/lib/runner.js b/lib/runner.js index 4561ce1..82c6710 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -11,7 +11,7 @@ const { URL } = require('url'); const cssRewrite = require('./processors/css').plugin; const htmlRewrite = require('./processors/html').plugin; -const sitemapRewrite = require('./processors/sitemap').plugin; +const xmlRewrite = require('./processors/xml').plugin; const regex = { css: /\.s?css$/i, @@ -88,7 +88,7 @@ module.exports = { filesByType.css.push(file); } else if (regex.html.test(ext)) { filesByType.html.push(file); - } else if (!regex.css.test(ext) && !regex.html.test(ext)) { + } else { filesByType.other.push(file); } }); @@ -183,14 +183,25 @@ module.exports = { return 1; } - const otherFiles = await this.clone_assets(options, sourceFiles.other); + const cloneExitCode = await this.clone_assets(options, sourceFiles.other); const cssExitCode = await this.rewrite_css(options, sourceFiles.css); const htmlExitCode = await this.rewrite_html(options, sourceFiles.html); const sitemapExitCode = await this.rewrite_sitemap(options); - - if (!otherFiles || cssExitCode > 1 || htmlExitCode > 1 || sitemapExitCode > 1) { + const rssExitCode = options.paths.rss ? await this.rewrite_rss(options) : 0; + + const processExitCode = Math.max( + cloneExitCode || 0, + cssExitCode || 0, + htmlExitCode || 0, + sitemapExitCode || 0, + rssExitCode || 0 + ); + + // Exit code 1 in the function calls above means that there were no files + // of that type to process, so ignorable (i.e. shouldn't halt process). + if (processExitCode > 1) { log.error('There was an error building your site 😓'); - return otherFiles ? Math.max(cssExitCode || 0, htmlExitCode || 0, sitemapExitCode || 0) : 1; + return processExitCode; } return 0; }, @@ -201,8 +212,7 @@ module.exports = { */ clean: async function (options) { if (!options.flags.overwrite && fs.pathExistsSync(options.paths.dest)) { - const question = `Warning: The destination ${options.paths.dest} already exists.` - + 'Continuing will delete this folder and everything in it. Do you wish to continue? (Y or N): '; + const question = `Warning: The destination ${options.paths.dest} already exists.\nContinuing will delete this folder and everything in it.\nDo you wish to continue? (Y or N): `; const isYes = await this._askYesNo(question); if (!isYes) return 1; } @@ -228,7 +238,7 @@ module.exports = { const { split, partition } = flags; files = await getFiles(options.paths.fullPathToSource, { partition: { split: split, partition: partition }, - ignorePatterns: ['/**/*.htm?', '/**/*.css'] + ignorePatterns: ['/**/*.htm', '/**/*.html', '/**/*.css', '/**/*.scss'] }); if (!files || !files.length) return 1; } @@ -239,7 +249,7 @@ module.exports = { return 4; } - return otherFiles; + return 0; }, /** @@ -356,13 +366,13 @@ module.exports = { if (options.fromIndex) { copiedFiles.forEach((file) => { - const exit = sitemapRewrite(file, options.paths.fullPathToDest, options.paths.baseurl); + const exit = xmlRewrite(file, options.paths.fullPathToDest, options.paths.baseurl); if (exit > 0) return exit; // if error }); } else { log('rewriting sitemap...'); const file = copiedFiles[0]; - const exit = sitemapRewrite(file, options.paths.fullPathToDest, options.paths.baseurl); + const exit = xmlRewrite(file, options.paths.fullPathToDest, options.paths.baseurl); if (Array.isArray(exit) && !options.fromIndex) { options.fromIndex = true; @@ -384,6 +394,30 @@ module.exports = { return 0; }, + /** + * Rewrites s in an RSS file to include baseurl. + * + * @param {Object} options The options object. + * @returns {[String]} The copied files (TODO). + */ + rewrite_rss: async function (options) { + const files = await getFiles(options.paths.fullPathToSource, + { globPattern: options.paths.rss }); + if (!files || !files.length) { + return 1; + } + + const copiedFiles = await this._copyFiles(files, options); + if (!copiedFiles) { + return 4; + } + + log('rewriting rss feed...'); + const file = copiedFiles[0]; + const exit = xmlRewrite(file, options.paths.fullPathToDest, options.paths.baseurl); + return exit; + }, + /** * Serves the files on a local webserver, so that they may be viewed on a browser. * diff --git a/test/runner.test.js b/test/runner.test.js index ba2e586..1696892 100644 --- a/test/runner.test.js +++ b/test/runner.test.js @@ -235,14 +235,14 @@ describe('build', function () { before(function () { cleanStub.returns([]); fetchStub.returns([]); - cloneAssetsStub.returns(); + cloneAssetsStub.returns(2); rewriteCssStub.returns(0); rewriteHtmlStub.returns(0); }); it('should return with exit code 1', async function () { const result = await runner.build(testOp); - expect(result).to.equal(1); + expect(result).to.equal(2); }); }); @@ -372,9 +372,9 @@ describe('clone-assets', function () { }); context('Cloning from a valid directory', function () { - it('should return the cloned files', async function () { - const results = await runner.clone_assets(testOp); - expect(results.length).to.equal(2); + it('should return exit code 0', async function () { + const result = await runner.clone_assets(testOp); + expect(result).to.equal(0); }); }); @@ -604,6 +604,54 @@ describe('rewrite_sitemap()', function () { }); }); +describe('rewrite_rss()', function () { + context('no rss feed', function () { + it('should return error exit code (1)', async function () { + const results = await runner.rewrite_rss(testOp); + expect(results).to.equal(1); + }); + }); + + context('Uses rss file', function () { + before(function () { + mock({ + 'test/src': { + 'index.xml': ` + + + Site title + http://example.org/testBaseurl/ + Site description + Generator + en-us + Fri, 12 Aug 2016 00:00:00 +0000 + + Advice + http://example.org/testBaseurl/advice/ + Fri, 12 Aug 2016 00:00:00 +0000 + + http://example.org/advice/ + Advice + + + ` + } + }); + }); + + it('should return exit code 0', async function () { + const options = cloneObject(testOp); + options.paths.rss = 'index.xml'; + const results = await runner.rewrite_sitemap(options); + expect(results).to.equal(0); + }); + + after(function () { + mock.restore(); + }); + }); +}); + describe('serve', function () { }); diff --git a/test/xml.test.js b/test/xml.test.js index 9198e92..ca22c1e 100644 --- a/test/xml.test.js +++ b/test/xml.test.js @@ -1,19 +1,19 @@ /* eslint-disable prefer-arrow-callback */ const { expect } = require('chai'); const mock = require('mock-fs'); -const xmlRewrite = require('../lib/processors/sitemap'); +const xmlRewrite = require('../lib/processors/xml'); describe('rewrite xml', function () { - context('elements with some src attribute', function () { - it('should rewrite the url in each loc node', function () { + context('sitemap with "xhtml:link" and "loc" nodes', function () { + it('should rewrite the url in each node', function () { const xmlString = ` http://example.org/advice/ 2016-11-11T00:00:00+13:00 - - + + @@ -27,8 +27,8 @@ describe('rewrite xml', function () { http://example.org/testBaseurl/advice/ 2016-11-11T00:00:00+13:00 - - + + @@ -40,6 +40,51 @@ describe('rewrite xml', function () { expect(rewrittenElement).to.equal(expectedXmlString); }); }); + + context('rss feed with "link" nodes', function () { + it('should rewrite the url in each node', function () { + const xmlString = ` + + + Site title + http://example.org/ + Site description + Generator + en-us + Fri, 12 Aug 2016 00:00:00 +0000 + + Advice + http://example.org/advice/ + Fri, 12 Aug 2016 00:00:00 +0000 + + http://example.org/advice/ + Advice + + + `; + const expectedXmlString = ` + + + Site title + http://example.org/testBaseurl/ + Site description + Generator + en-us + Fri, 12 Aug 2016 00:00:00 +0000 + + Advice + http://example.org/testBaseurl/advice/ + Fri, 12 Aug 2016 00:00:00 +0000 + + http://example.org/advice/ + Advice + + + `; + const rewrittenElement = xmlRewrite.rewrite(xmlString, 'testBaseurl'); + expect(rewrittenElement).to.equal(expectedXmlString); + }); + }); }); describe('plugin', function () {