From 0523403b5d0d8253ab75b34d41f51c3a90dc0838 Mon Sep 17 00:00:00 2001 From: Jeff Escalante Date: Wed, 11 May 2016 18:52:17 -0400 Subject: [PATCH 1/7] wip wip wip --- lib/config.js | 2 + lib/plugins/experimental_iso_plugin.js | 72 ++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 lib/plugins/experimental_iso_plugin.js diff --git a/lib/config.js b/lib/config.js index 6cc51c7..bc89139 100644 --- a/lib/config.js +++ b/lib/config.js @@ -4,6 +4,7 @@ const JadePlugin = require('./plugins/jade_plugin') const CSSPlugin = require('./plugins/css_plugin') const StaticPlugin = require('./plugins/static_plugin') const FsPlugin = require('./plugins/fs_plugin') +const ExperimentalIsoPlugin = require('./plugins/experimental_iso_plugin') const micromatch = require('micromatch') const union = require('lodash.union') const postcssImport = require('postcss-import') @@ -228,6 +229,7 @@ module.exports = class Config { new JadePlugin(util), new CSSPlugin(util), new StaticPlugin(util), + new ExperimentalIsoPlugin(util), new BrowserSyncPlugin(opts.server, { callback: (_, bs) => { if (bs.utils.devIp.length) { this.project.emit('info', `External IP: http://${bs.utils.devIp[0]}:${this.spike.server.port}`) diff --git a/lib/plugins/experimental_iso_plugin.js b/lib/plugins/experimental_iso_plugin.js new file mode 100644 index 0000000..14afeb2 --- /dev/null +++ b/lib/plugins/experimental_iso_plugin.js @@ -0,0 +1,72 @@ +const mm = require('micromatch') +const path = require('path') +const fs = require('fs') +const {addFilesAsWebpackEntries, removeAssets} = require('./plugin_utils') + +module.exports = class ExperimentalIsoPlugin { + + /** + * @constructor + * @param {Object} opts - options for configuration + * @param {String} opts.root - project root + * @param {Array} opts.dumpDirs - directories to dump to public + */ + constructor (opts) { + this.opts = opts + this.files = 'views/*.jade' + this.tempFile = path.join(this.opts.root, 'node_modules/iso.js') + } + + apply (compiler) { + let jadeFiles + + compiler.plugin('make', (compilation, done) => { + jadeFiles = compiler.options.spike.files.jade + // get paths relative to root + const filesRelative = jadeFiles.map((f) => { + return f.replace(this.opts.root + '/', '') + }) + // filter in files matching the user-defined matcher + const matchingFiles = mm.match(filesRelative, this.files) + + // now we are going to build the link injector script + let mod = '' + + // first, we require in all the matching jade files so that we have the + // contents ready to inject if needed + matchingFiles.map((f) => { + mod += `exports.${path.basename(f, '.jade')} = require('./${f}')\n` + }) + + // now we add the script that matches link clicks to templates + mod += ` + const links = querySelectorAll('a') + links.map((l) => { + l.onclick = (e) => { + e.preventDefault() + if (l.href.match(our files)) { + document.innerHTML = template name + } else { + // proceed as usual + } + } + }) + ` + + // then we write it all as a temporary file to root + fs.writeFileSync(this.tempFile, mod) + + // finally, we add that file as an entry to webpack so that it shows up + addFilesAsWebpackEntries([this.tempFile], this.opts, compilation) + done() + }) + + compiler.plugin('compilation', (compilation) => { + compilation.plugin('optimize-chunk-assets', (chunks, done) => { + fs.unlinkSync(this.tempFile) + removeAssets(compilation, [this.tempFile], this.opts, done) + }) + }) + } + +} From 40dd740c21545d52b1c741b33a071766e7f4dbd5 Mon Sep 17 00:00:00 2001 From: Jeff Escalante Date: Wed, 11 May 2016 18:55:00 -0400 Subject: [PATCH 2/7] update template require path --- lib/plugins/experimental_iso_plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plugins/experimental_iso_plugin.js b/lib/plugins/experimental_iso_plugin.js index 14afeb2..3dd8b6c 100644 --- a/lib/plugins/experimental_iso_plugin.js +++ b/lib/plugins/experimental_iso_plugin.js @@ -35,7 +35,7 @@ module.exports = class ExperimentalIsoPlugin { // first, we require in all the matching jade files so that we have the // contents ready to inject if needed matchingFiles.map((f) => { - mod += `exports.${path.basename(f, '.jade')} = require('./${f}')\n` + mod += `exports.${path.basename(f, '.jade')} = require('../${f}')\n` }) // now we add the script that matches link clicks to templates From 9e7f483768486f1121446697c9c3aebc7e6e04b3 Mon Sep 17 00:00:00 2001 From: Jeff Escalante Date: Thu, 12 May 2016 14:42:20 -0400 Subject: [PATCH 3/7] working --- lib/plugins/experimental_iso_plugin.js | 66 +++++++++++++++++++------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/lib/plugins/experimental_iso_plugin.js b/lib/plugins/experimental_iso_plugin.js index 3dd8b6c..c354692 100644 --- a/lib/plugins/experimental_iso_plugin.js +++ b/lib/plugins/experimental_iso_plugin.js @@ -1,7 +1,11 @@ const mm = require('micromatch') const path = require('path') const fs = require('fs') -const {addFilesAsWebpackEntries, removeAssets} = require('./plugin_utils') +const { + addFilesAsWebpackEntries, + removeAssets, + getOutputPath +} = require('./plugin_utils') module.exports = class ExperimentalIsoPlugin { @@ -13,7 +17,8 @@ module.exports = class ExperimentalIsoPlugin { */ constructor (opts) { this.opts = opts - this.files = 'views/*.jade' + this.files = 'views/**/*.jade' + // tempfile written to node_modules so the require path is easy this.tempFile = path.join(this.opts.root, 'node_modules/iso.js') } @@ -22,38 +27,62 @@ module.exports = class ExperimentalIsoPlugin { compiler.plugin('make', (compilation, done) => { jadeFiles = compiler.options.spike.files.jade - // get paths relative to root - const filesRelative = jadeFiles.map((f) => { - return f.replace(this.opts.root + '/', '') - }) + // filter in files matching the user-defined matcher - const matchingFiles = mm.match(filesRelative, this.files) + const matchingFiles = jadeFiles.filter((f) => { + return mm.isMatch(f.replace(`${this.opts.root}/`, ''), this.files) + }) // now we are going to build the link injector script let mod = '' // first, we require in all the matching jade files so that we have the // contents ready to inject if needed - matchingFiles.map((f) => { - mod += `exports.${path.basename(f, '.jade')} = require('../${f}')\n` + matchingFiles.forEach((f) => { + mod += `exports['${getOutputPath(f, this.opts).replace(/\.jade/, '')}'] = require('../${f.replace(`${this.opts.root}/`, '')}')\n` }) // now we add the script that matches link clicks to templates + // TODO: make this a little cleaner, ensure it's being compiled by babel mod += ` - const links = querySelectorAll('a') - links.map((l) => { - l.onclick = (e) => { + const links = document.querySelectorAll('a') + + window.onpopstate = function (e) { + console.log(e.target.location.pathname) + matchedTpl = getTemplate(e.target.location.pathname) + if (matchedTpl) { + document.write(matchedTpl) + document.close() + } else { + console.error('flagrant error! call in the devs!') + } + } + + for (let i = 0; i < links.length; i++) { + const el = links[i] + el.onclick = (e) => { e.preventDefault() - if (l.href.match(our files)) { - document.innerHTML = template name + const parser = document.createElement('a') + parser.href = el.href + matchedTpl = getTemplate(el.pathname) + if (matchedTpl) { + document.write(matchedTpl) + document.close() + history.pushState({}, '', el.href) } else { - // proceed as usual + window.location = el.href } } - }) - ` + } - // then we write it all as a temporary file to root + function getTemplate(href) { + let hrefPath = href + if (href[href.length-1] === '/') { hrefPath = href + 'index.html' } + hrefPath = hrefPath.substring(1).replace(/.html$/, '') + return exports[hrefPath] + } + ` + // then we write it all as a temporary file fs.writeFileSync(this.tempFile, mod) // finally, we add that file as an entry to webpack so that it shows up @@ -63,6 +92,7 @@ module.exports = class ExperimentalIsoPlugin { compiler.plugin('compilation', (compilation) => { compilation.plugin('optimize-chunk-assets', (chunks, done) => { + // once everything has been compiled, we remove the temp file fs.unlinkSync(this.tempFile) removeAssets(compilation, [this.tempFile], this.opts, done) }) From 66245384ac78ea85cb2e532e2d6b4a33c51785bb Mon Sep 17 00:00:00 2001 From: Jeff Escalante Date: Thu, 12 May 2016 14:45:18 -0400 Subject: [PATCH 4/7] take options from main config --- lib/config.js | 1 + lib/plugins/experimental_iso_plugin.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/config.js b/lib/config.js index bc89139..c69efb7 100644 --- a/lib/config.js +++ b/lib/config.js @@ -59,6 +59,7 @@ module.exports = class Config { babel: Joi.object().default({}), cleanUrls: Joi.bool().default(true), jade: Joi.object().default({}), + iso: [Joi.boolean(), Joi.string()], dumpDirs: Joi.array().default(['views', 'assets']), locals: Joi.object().default({}), ignore: Joi.array().default([]), diff --git a/lib/plugins/experimental_iso_plugin.js b/lib/plugins/experimental_iso_plugin.js index c354692..2015a1d 100644 --- a/lib/plugins/experimental_iso_plugin.js +++ b/lib/plugins/experimental_iso_plugin.js @@ -17,7 +17,8 @@ module.exports = class ExperimentalIsoPlugin { */ constructor (opts) { this.opts = opts - this.files = 'views/**/*.jade' + this.files = opts.iso + if (opts.iso === true) this.files = '**/*.jade' // tempfile written to node_modules so the require path is easy this.tempFile = path.join(this.opts.root, 'node_modules/iso.js') } From d282b97f4a7a8204dfc8448f130bf6b567405456 Mon Sep 17 00:00:00 2001 From: Jeff Escalante Date: Thu, 12 May 2016 15:39:04 -0400 Subject: [PATCH 5/7] remove es6 from tempfile --- lib/plugins/experimental_iso_plugin.js | 62 +++++++++++++------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/lib/plugins/experimental_iso_plugin.js b/lib/plugins/experimental_iso_plugin.js index 2015a1d..d3e664c 100644 --- a/lib/plugins/experimental_iso_plugin.js +++ b/lib/plugins/experimental_iso_plugin.js @@ -46,41 +46,43 @@ module.exports = class ExperimentalIsoPlugin { // now we add the script that matches link clicks to templates // TODO: make this a little cleaner, ensure it's being compiled by babel mod += ` - const links = document.querySelectorAll('a') + if (window.history && window.onpopstate) { + var links = document.querySelectorAll('a') - window.onpopstate = function (e) { - console.log(e.target.location.pathname) - matchedTpl = getTemplate(e.target.location.pathname) - if (matchedTpl) { - document.write(matchedTpl) - document.close() - } else { - console.error('flagrant error! call in the devs!') - } - } + window.onpopstate = function (e) { + console.log(e.target.location.pathname) + matchedTpl = getTemplate(e.target.location.pathname) + if (matchedTpl) { + document.write(matchedTpl) + document.close() + } else { + window.location = t.target.location + } + } - for (let i = 0; i < links.length; i++) { - const el = links[i] - el.onclick = (e) => { - e.preventDefault() - const parser = document.createElement('a') - parser.href = el.href - matchedTpl = getTemplate(el.pathname) - if (matchedTpl) { - document.write(matchedTpl) - document.close() - history.pushState({}, '', el.href) - } else { - window.location = el.href + for (let i = 0; i < links.length; i++) { + var el = links[i] + el.onclick = function (e) { + e.preventDefault() + const parser = document.createElement('a') + parser.href = el.href + matchedTpl = getTemplate(el.pathname) + if (matchedTpl) { + document.write(matchedTpl) + document.close() + history.pushState({}, '', el.href) + } else { + window.location = el.href + } } } - } - function getTemplate(href) { - let hrefPath = href - if (href[href.length-1] === '/') { hrefPath = href + 'index.html' } - hrefPath = hrefPath.substring(1).replace(/.html$/, '') - return exports[hrefPath] + function getTemplate(href) { + let hrefPath = href + if (href[href.length-1] === '/') { hrefPath = href + 'index.html' } + hrefPath = hrefPath.substring(1).replace(/.html$/, '') + return exports[hrefPath] + } } ` // then we write it all as a temporary file From 7699f1b754dce925b9ba4f0002ff6e730ab23a43 Mon Sep 17 00:00:00 2001 From: Jeff Escalante Date: Thu, 19 May 2016 12:18:44 -0400 Subject: [PATCH 6/7] bring up to date with latest master --- lib/config.js | 3 ++- lib/plugins/experimental_iso_plugin.js | 31 +++++++++++--------------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/lib/config.js b/lib/config.js index c69efb7..c00b09e 100644 --- a/lib/config.js +++ b/lib/config.js @@ -216,7 +216,8 @@ module.exports = class Config { dumpDirs: opts.dumpDirs, ignore: opts.ignore, vendor: opts.vendor, - matchers: opts.matchers + matchers: opts.matchers, + iso: opts.iso } this.babel = opts.babel diff --git a/lib/plugins/experimental_iso_plugin.js b/lib/plugins/experimental_iso_plugin.js index d3e664c..b8aeb6e 100644 --- a/lib/plugins/experimental_iso_plugin.js +++ b/lib/plugins/experimental_iso_plugin.js @@ -1,11 +1,6 @@ const mm = require('micromatch') const path = require('path') const fs = require('fs') -const { - addFilesAsWebpackEntries, - removeAssets, - getOutputPath -} = require('./plugin_utils') module.exports = class ExperimentalIsoPlugin { @@ -15,23 +10,23 @@ module.exports = class ExperimentalIsoPlugin { * @param {String} opts.root - project root * @param {Array} opts.dumpDirs - directories to dump to public */ - constructor (opts) { - this.opts = opts - this.files = opts.iso - if (opts.iso === true) this.files = '**/*.jade' + constructor (util) { + this.util = util + this.files = util.conf.spike.iso + if (this.files === true) this.files = '**/*.jade' // tempfile written to node_modules so the require path is easy - this.tempFile = path.join(this.opts.root, 'node_modules/iso.js') + this.tempFile = path.join(this.util.conf.context, 'node_modules/iso.js') } apply (compiler) { - let jadeFiles + if (!this.files) return compiler.plugin('make', (compilation, done) => { - jadeFiles = compiler.options.spike.files.jade + const jadeFiles = compiler.options.spike.files.jade // filter in files matching the user-defined matcher const matchingFiles = jadeFiles.filter((f) => { - return mm.isMatch(f.replace(`${this.opts.root}/`, ''), this.files) + return mm.isMatch(f.replace(`${this.util.conf.context}/`, ''), this.files) }) // now we are going to build the link injector script @@ -40,17 +35,16 @@ module.exports = class ExperimentalIsoPlugin { // first, we require in all the matching jade files so that we have the // contents ready to inject if needed matchingFiles.forEach((f) => { - mod += `exports['${getOutputPath(f, this.opts).replace(/\.jade/, '')}'] = require('../${f.replace(`${this.opts.root}/`, '')}')\n` + mod += `exports['${this.util.getOutputPath(f).replace(/\.jade/, '')}'] = require('../${f.replace(`${this.util.conf.context}/`, '')}')\n` }) // now we add the script that matches link clicks to templates // TODO: make this a little cleaner, ensure it's being compiled by babel mod += ` - if (window.history && window.onpopstate) { + if (window.history) { var links = document.querySelectorAll('a') window.onpopstate = function (e) { - console.log(e.target.location.pathname) matchedTpl = getTemplate(e.target.location.pathname) if (matchedTpl) { document.write(matchedTpl) @@ -89,7 +83,7 @@ module.exports = class ExperimentalIsoPlugin { fs.writeFileSync(this.tempFile, mod) // finally, we add that file as an entry to webpack so that it shows up - addFilesAsWebpackEntries([this.tempFile], this.opts, compilation) + this.util.addFilesAsWebpackEntries(compilation, [this.tempFile]) done() }) @@ -97,7 +91,8 @@ module.exports = class ExperimentalIsoPlugin { compilation.plugin('optimize-chunk-assets', (chunks, done) => { // once everything has been compiled, we remove the temp file fs.unlinkSync(this.tempFile) - removeAssets(compilation, [this.tempFile], this.opts, done) + this.util.removeAssets(compilation, [this.tempFile]) + done() }) }) } From 4d93f321945e97a640cb860653ed4642fe20ec7c Mon Sep 17 00:00:00 2001 From: Jeff Escalante Date: Thu, 19 May 2016 19:44:20 -0400 Subject: [PATCH 7/7] name change --- lib/config.js | 8 ++++---- .../{experimental_iso_plugin.js => pushstate_plugin.js} | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) rename lib/plugins/{experimental_iso_plugin.js => pushstate_plugin.js} (96%) diff --git a/lib/config.js b/lib/config.js index c00b09e..779f952 100644 --- a/lib/config.js +++ b/lib/config.js @@ -4,7 +4,7 @@ const JadePlugin = require('./plugins/jade_plugin') const CSSPlugin = require('./plugins/css_plugin') const StaticPlugin = require('./plugins/static_plugin') const FsPlugin = require('./plugins/fs_plugin') -const ExperimentalIsoPlugin = require('./plugins/experimental_iso_plugin') +const PushStatePlugin = require('./plugins/pushstate_plugin') const micromatch = require('micromatch') const union = require('lodash.union') const postcssImport = require('postcss-import') @@ -59,7 +59,7 @@ module.exports = class Config { babel: Joi.object().default({}), cleanUrls: Joi.bool().default(true), jade: Joi.object().default({}), - iso: [Joi.boolean(), Joi.string()], + pushState: [Joi.boolean(), Joi.string()], dumpDirs: Joi.array().default(['views', 'assets']), locals: Joi.object().default({}), ignore: Joi.array().default([]), @@ -217,7 +217,7 @@ module.exports = class Config { ignore: opts.ignore, vendor: opts.vendor, matchers: opts.matchers, - iso: opts.iso + pushState: opts.pushState } this.babel = opts.babel @@ -231,7 +231,7 @@ module.exports = class Config { new JadePlugin(util), new CSSPlugin(util), new StaticPlugin(util), - new ExperimentalIsoPlugin(util), + new PushStatePlugin(util), new BrowserSyncPlugin(opts.server, { callback: (_, bs) => { if (bs.utils.devIp.length) { this.project.emit('info', `External IP: http://${bs.utils.devIp[0]}:${this.spike.server.port}`) diff --git a/lib/plugins/experimental_iso_plugin.js b/lib/plugins/pushstate_plugin.js similarity index 96% rename from lib/plugins/experimental_iso_plugin.js rename to lib/plugins/pushstate_plugin.js index b8aeb6e..26431c1 100644 --- a/lib/plugins/experimental_iso_plugin.js +++ b/lib/plugins/pushstate_plugin.js @@ -2,7 +2,7 @@ const mm = require('micromatch') const path = require('path') const fs = require('fs') -module.exports = class ExperimentalIsoPlugin { +module.exports = class PushStatePlugin { /** * @constructor @@ -12,10 +12,10 @@ module.exports = class ExperimentalIsoPlugin { */ constructor (util) { this.util = util - this.files = util.conf.spike.iso + this.files = util.conf.spike.pushState if (this.files === true) this.files = '**/*.jade' // tempfile written to node_modules so the require path is easy - this.tempFile = path.join(this.util.conf.context, 'node_modules/iso.js') + this.tempFile = path.join(this.util.conf.context, 'node_modules/spike-pushstate.js') } apply (compiler) {