From 12b5f7538a93c85fcb6d93b9a2930b26f2e71df6 Mon Sep 17 00:00:00 2001 From: David Bailey <4248177+davidbailey00@users.noreply.github.com> Date: Wed, 4 Sep 2019 14:30:41 +0100 Subject: [PATCH] feat(gatsby-plugin-offline): Allow precaching custom pages (#16877) * Allow precaching custom pages rather than just the offline shell * Document this and add tests --- packages/gatsby-plugin-offline/.gitignore | 1 + packages/gatsby-plugin-offline/README.md | 17 +- packages/gatsby-plugin-offline/package.json | 4 +- .../__snapshots__/gatsby-node.js.snap | 18 ++ .../__tests__/fixtures/public/dir1/index.html | 2 + .../__tests__/fixtures/public/dir1/page1.html | 2 + .../__tests__/fixtures/public/dir1/page2.html | 2 + .../__tests__/fixtures/public/dir1/script.js | 2 + .../__tests__/fixtures/public/dir1/style.css | 2 + .../__tests__/fixtures/public/dir2/index.html | 2 + .../__tests__/fixtures/public/dir2/page1.html | 2 + .../__tests__/fixtures/public/dir2/page2.html | 2 + .../__tests__/fixtures/public/dir2/script.js | 2 + .../__tests__/fixtures/public/dir2/style.css | 2 + .../{ => fixtures/public}/index.html | 0 .../fixtures/public/no-index-html/style.css | 2 + .../src/__tests__/fixtures/public/script.js | 2 + .../src/__tests__/fixtures/public/style.css | 2 + .../src/__tests__/fixtures/public/test.html | 2 + .../src/__tests__/gatsby-node.js | 88 +++++--- .../src/__tests__/get-resources-from-html.js | 4 +- .../gatsby-plugin-offline/src/gatsby-node.js | 80 ++++++-- .../src/get-resources-from-html.js | 11 +- yarn.lock | 188 +++++++++++++++++- 24 files changed, 373 insertions(+), 66 deletions(-) create mode 100644 packages/gatsby-plugin-offline/src/__tests__/__snapshots__/gatsby-node.js.snap create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/index.html create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/page1.html create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/page2.html create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/script.js create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/style.css create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/index.html create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/page1.html create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/page2.html create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/script.js create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/style.css rename packages/gatsby-plugin-offline/src/__tests__/{ => fixtures/public}/index.html (100%) create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/no-index-html/style.css create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/script.js create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/style.css create mode 100644 packages/gatsby-plugin-offline/src/__tests__/fixtures/public/test.html diff --git a/packages/gatsby-plugin-offline/.gitignore b/packages/gatsby-plugin-offline/.gitignore index 8c9686624a187..f68bfbec361dc 100644 --- a/packages/gatsby-plugin-offline/.gitignore +++ b/packages/gatsby-plugin-offline/.gitignore @@ -1,3 +1,4 @@ /*.js !index.js +!src/__tests__/fixtures/public yarn.lock diff --git a/packages/gatsby-plugin-offline/README.md b/packages/gatsby-plugin-offline/README.md index 96a84b8455036..7a66e2fda3f31 100644 --- a/packages/gatsby-plugin-offline/README.md +++ b/packages/gatsby-plugin-offline/README.md @@ -21,7 +21,22 @@ plugins: [`gatsby-plugin-offline`] ## Available options -As of `gatsby-plugin-offline` 3.0.0, the following options are available: +In `gatsby-plugin-offline` 3.x, the following options are available: + +- `precachePages` lets you specify pages whose resources should be precached by the service worker, using an array of globs. For example: + + ```javascript:title=gatsby-config.js + plugins: [ + { + resolve: `gatsby-plugin-offline`, + options: { + precachePages: [`/about-us/`, `/projects/*`], + }, + }, + ] + ``` + + Note: while essential resources of specified pages will be precached, such as JavaScript and CSS, non-essential resources such as fonts and images will not be included. Instead, these will be cached at runtime when a user visits a given page that includes these resources. - `appendScript` lets you specify a file to be appended at the end of the generated service worker (`sw.js`). For example: diff --git a/packages/gatsby-plugin-offline/package.json b/packages/gatsby-plugin-offline/package.json index fb4133d57dfe7..a5de6a51546c9 100644 --- a/packages/gatsby-plugin-offline/package.json +++ b/packages/gatsby-plugin-offline/package.json @@ -9,6 +9,7 @@ "dependencies": { "@babel/runtime": "^7.5.5", "cheerio": "^1.0.0-rc.3", + "glob": "^7.1.4", "idb-keyval": "^3.2.0", "lodash": "^4.17.15", "slash": "^3.0.0", @@ -19,7 +20,8 @@ "@babel/core": "^7.5.5", "babel-preset-gatsby-package": "^0.2.3", "cpx": "^1.5.0", - "cross-env": "^5.2.1" + "cross-env": "^5.2.1", + "rewire": "^4.0.1" }, "homepage": "https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-plugin-offline#readme", "keywords": [ diff --git a/packages/gatsby-plugin-offline/src/__tests__/__snapshots__/gatsby-node.js.snap b/packages/gatsby-plugin-offline/src/__tests__/__snapshots__/gatsby-node.js.snap new file mode 100644 index 0000000000000..9641c7bbc8cd8 --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/__snapshots__/gatsby-node.js.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`getPrecachePages correctly matches pages 1`] = ` +Array [ + "/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/index.html", + "/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/index.html", + "/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/index.html", + "/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/test.html", +] +`; + +exports[`getPrecachePages correctly matches pages 2`] = ` +Array [ + "/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/index.html", + "/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/page1.html", + "/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/page2.html", +] +`; diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/index.html b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/index.html new file mode 100644 index 0000000000000..87ffb0754608e --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/index.html @@ -0,0 +1,2 @@ + diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/page1.html b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/page1.html new file mode 100644 index 0000000000000..87ffb0754608e --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/page1.html @@ -0,0 +1,2 @@ + diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/page2.html b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/page2.html new file mode 100644 index 0000000000000..87ffb0754608e --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/page2.html @@ -0,0 +1,2 @@ + diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/script.js b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/script.js new file mode 100644 index 0000000000000..edefae6509614 --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/script.js @@ -0,0 +1,2 @@ +// This is a script. How exciting! +// Content of this file is irrelevant; it is used for testing `getPrecachePages` diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/style.css b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/style.css new file mode 100644 index 0000000000000..abab82612b75f --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir1/style.css @@ -0,0 +1,2 @@ +/* This is a stylesheet. How exciting! + Content of this file is irrelevant; it is used for testing `getPrecachePages` */ diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/index.html b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/index.html new file mode 100644 index 0000000000000..87ffb0754608e --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/index.html @@ -0,0 +1,2 @@ + diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/page1.html b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/page1.html new file mode 100644 index 0000000000000..87ffb0754608e --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/page1.html @@ -0,0 +1,2 @@ + diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/page2.html b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/page2.html new file mode 100644 index 0000000000000..87ffb0754608e --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/page2.html @@ -0,0 +1,2 @@ + diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/script.js b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/script.js new file mode 100644 index 0000000000000..edefae6509614 --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/script.js @@ -0,0 +1,2 @@ +// This is a script. How exciting! +// Content of this file is irrelevant; it is used for testing `getPrecachePages` diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/style.css b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/style.css new file mode 100644 index 0000000000000..abab82612b75f --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/dir2/style.css @@ -0,0 +1,2 @@ +/* This is a stylesheet. How exciting! + Content of this file is irrelevant; it is used for testing `getPrecachePages` */ diff --git a/packages/gatsby-plugin-offline/src/__tests__/index.html b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/index.html similarity index 100% rename from packages/gatsby-plugin-offline/src/__tests__/index.html rename to packages/gatsby-plugin-offline/src/__tests__/fixtures/public/index.html diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/no-index-html/style.css b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/no-index-html/style.css new file mode 100644 index 0000000000000..abab82612b75f --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/no-index-html/style.css @@ -0,0 +1,2 @@ +/* This is a stylesheet. How exciting! + Content of this file is irrelevant; it is used for testing `getPrecachePages` */ diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/script.js b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/script.js new file mode 100644 index 0000000000000..edefae6509614 --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/script.js @@ -0,0 +1,2 @@ +// This is a script. How exciting! +// Content of this file is irrelevant; it is used for testing `getPrecachePages` diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/style.css b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/style.css new file mode 100644 index 0000000000000..abab82612b75f --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/style.css @@ -0,0 +1,2 @@ +/* This is a stylesheet. How exciting! + Content of this file is irrelevant; it is used for testing `getPrecachePages` */ diff --git a/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/test.html b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/test.html new file mode 100644 index 0000000000000..87ffb0754608e --- /dev/null +++ b/packages/gatsby-plugin-offline/src/__tests__/fixtures/public/test.html @@ -0,0 +1,2 @@ + diff --git a/packages/gatsby-plugin-offline/src/__tests__/gatsby-node.js b/packages/gatsby-plugin-offline/src/__tests__/gatsby-node.js index 263722001f4e6..35601edcb6a8a 100644 --- a/packages/gatsby-plugin-offline/src/__tests__/gatsby-node.js +++ b/packages/gatsby-plugin-offline/src/__tests__/gatsby-node.js @@ -1,20 +1,26 @@ -const { onPostBuild } = require(`../gatsby-node`) +const rewire = require(`rewire`) const fs = require(`fs`) +const path = require(`path`) -jest.mock(`fs`) -jest.mock(`../get-resources-from-html`, () => () => []) +describe(`getPrecachePages`, () => { + const gatsbyNode = rewire(`../gatsby-node`) + const getPrecachePages = gatsbyNode.__get__(`getPrecachePages`) -let swText = `` + it(`correctly matches pages`, () => { + const base = `${__dirname}/fixtures/public` -jest.mock(`workbox-build`, () => { - return { - generateSW() { - return Promise.resolve({ count: 1, size: 1, warnings: [] }) - }, - } + const allPages = getPrecachePages([`**/*`], base) + expect(allPages.map(page => path.normalize(page))).toMatchSnapshot() + + const dir1Pages = getPrecachePages([`/dir1/*`], base) + expect(dir1Pages.map(page => path.normalize(page))).toMatchSnapshot() + }) }) describe(`onPostBuild`, () => { + let swText = `` + const gatsbyNode = rewire(`../gatsby-node`) + const componentChunkName = `chunkName` const chunks = [`chunk1`, `chunk2`] @@ -26,31 +32,53 @@ describe(`onPostBuild`, () => { } // Mock out filesystem functions - fs.readFileSync.mockImplementation(file => { - if (file === `${process.cwd()}/public/webpack.stats.json`) { - return JSON.stringify(stats) - } else if (file === `public/sw.js`) { - return swText - } else if (file.match(/\/sw-append\.js/)) { - return `` - } else { - return jest.requireActual(`fs`).readFileSync(file) - } - }) + const mockFs = { + ...fs, - fs.appendFileSync.mockImplementation((file, text) => { - swText += text - }) + readFileSync(file) { + if (file === `${process.cwd()}/public/webpack.stats.json`) { + return JSON.stringify(stats) + } else if (file === `public/sw.js`) { + return swText + } else if (file.match(/\/sw-append\.js/)) { + return `` + } else { + return fs.readFileSync(file) + } + }, - fs.createReadStream.mockImplementation(() => { - return { pipe() {} } - }) + appendFileSync(file, text) { + swText += text + }, + + createReadStream() { + return { pipe() {} } + }, + + createWriteStream() {}, + } + + const mockWorkboxBuild = { + generateSW() { + return Promise.resolve({ count: 1, size: 1, warnings: [] }) + }, + } - fs.createWriteStream.mockImplementation(() => {}) + gatsbyNode.__set__(`fs`, mockFs) + gatsbyNode.__set__(`getResourcesFromHTML`, () => []) + gatsbyNode.__set__(`workboxBuild`, mockWorkboxBuild) + gatsbyNode.__set__(`console`, { log() {} }) it(`appends to sw.js`, async () => { - await onPostBuild( - { pathPrefix: `` }, + await gatsbyNode.onPostBuild( + { + pathPrefix: ``, + reporter: { + info(message) { + console.log(message) + }, + }, + }, { appendScript: `${__dirname}/fixtures/custom-sw-code.js` } ) diff --git a/packages/gatsby-plugin-offline/src/__tests__/get-resources-from-html.js b/packages/gatsby-plugin-offline/src/__tests__/get-resources-from-html.js index 1443286f0a09b..deb7ed3232f6b 100644 --- a/packages/gatsby-plugin-offline/src/__tests__/get-resources-from-html.js +++ b/packages/gatsby-plugin-offline/src/__tests__/get-resources-from-html.js @@ -1,9 +1,9 @@ const path = require(`path`) const getResourcesFromHTML = require(`../get-resources-from-html`) -const htmlPath = path.resolve(`${__dirname}/index.html`) +const htmlPath = path.resolve(`${__dirname}/fixtures/public/index.html`) it(`it extracts resources correctly`, () => { - const resources = getResourcesFromHTML(htmlPath) + const resources = getResourcesFromHTML(htmlPath, ``) expect(resources).toMatchSnapshot() }) diff --git a/packages/gatsby-plugin-offline/src/gatsby-node.js b/packages/gatsby-plugin-offline/src/gatsby-node.js index 25ebf0d23b8d9..f4b92e3e9a5d7 100644 --- a/packages/gatsby-plugin-offline/src/gatsby-node.js +++ b/packages/gatsby-plugin-offline/src/gatsby-node.js @@ -1,10 +1,12 @@ -const fs = require(`fs`) -const workboxBuild = require(`workbox-build`) +// use `let` to workaround https://github.com/jhnns/rewire/issues/144 +let fs = require(`fs`) +let workboxBuild = require(`workbox-build`) const path = require(`path`) const slash = require(`slash`) +const glob = require(`glob`) const _ = require(`lodash`) -const getResourcesFromHTML = require(`./get-resources-from-html`) +let getResourcesFromHTML = require(`./get-resources-from-html`) exports.createPages = ({ actions }) => { if (process.env.NODE_ENV === `production`) { @@ -28,15 +30,44 @@ const readStats = () => { } } -const getAssetsForChunks = chunks => { +function getAssetsForChunks(chunks) { const files = _.flatten( chunks.map(chunk => readStats().assetsByChunkName[chunk]) ) return _.compact(files) } -exports.onPostBuild = (args, pluginOptions) => { - const { pathPrefix } = args +function getPrecachePages(globs, base) { + const precachePages = [] + + globs.forEach(page => { + const matches = glob.sync(base + page) + matches.forEach(path => { + const isDirectory = fs.lstatSync(path).isDirectory() + let precachePath + + if (isDirectory && fs.existsSync(`${path}/index.html`)) { + precachePath = `${path}/index.html` + } else if (path.endsWith(`.html`)) { + precachePath = path + } else { + return + } + + if (precachePages.indexOf(precachePath) === -1) { + precachePages.push(precachePath) + } + }) + }) + + return precachePages +} + +exports.onPostBuild = ( + args, + { precachePages: precachePagesGlobs = [], appendScript = null, workboxConfig } +) => { + const { pathPrefix, reporter } = args const rootDir = `public` // Get exact asset filenames for app and offline app shell chunks @@ -47,16 +78,25 @@ exports.onPostBuild = (args, pluginOptions) => { ]) const appFile = files.find(file => file.startsWith(`app-`)) - // Remove the custom prefix (if any) so Workbox can find the files. - // This is added back at runtime (see modifyUrlPrefix) in order to serve - // from the correct location. - const omitPrefix = path => path.slice(pathPrefix.length) + function flat(arr) { + return Array.prototype.flat ? arr.flat() : [].concat(...arr) + } - const criticalFilePaths = getResourcesFromHTML( - `${process.cwd()}/${rootDir}/offline-plugin-app-shell-fallback/index.html` - ).map(omitPrefix) + const offlineShellPath = `${process.cwd()}/${rootDir}/offline-plugin-app-shell-fallback/index.html` + const precachePages = [ + offlineShellPath, + ...getPrecachePages( + precachePagesGlobs, + `${process.cwd()}/${rootDir}` + ).filter(page => page !== offlineShellPath), + ] + + const criticalFilePaths = _.uniq( + flat(precachePages.map(page => getResourcesFromHTML(page, pathPrefix))) + ) const globPatterns = files.concat([ + // criticalFilePaths doesn't include HTML pages (we only need this one) `offline-plugin-app-shell-fallback/index.html`, ...criticalFilePaths, ]) @@ -108,7 +148,7 @@ exports.onPostBuild = (args, pluginOptions) => { const combinedOptions = { ...options, - ...pluginOptions.workboxConfig, + ...workboxConfig, } const idbKeyvalFile = `idb-keyval-iife.min.js` @@ -129,18 +169,22 @@ exports.onPostBuild = (args, pluginOptions) => { fs.appendFileSync(`public/sw.js`, `\n` + swAppend) - if (pluginOptions.appendScript) { + if (appendScript !== null) { let userAppend try { - userAppend = fs.readFileSync(pluginOptions.appendScript, `utf8`) + userAppend = fs.readFileSync(appendScript, `utf8`) } catch (e) { throw new Error(`Couldn't find the specified offline inject script`) } fs.appendFileSync(`public/sw.js`, `\n` + userAppend) } - console.log( - `Generated ${swDest}, which will precache ${count} files, totaling ${size} bytes.` + reporter.info( + `Generated ${swDest}, which will precache ${count} files, totaling ${size} bytes.\n` + + `The following pages will be precached:\n` + + precachePages + .map(path => path.replace(`${process.cwd()}/public`, ``)) + .join(`\n`) ) }) } diff --git a/packages/gatsby-plugin-offline/src/get-resources-from-html.js b/packages/gatsby-plugin-offline/src/get-resources-from-html.js index d2ca422185ac3..86a105eb32eaa 100644 --- a/packages/gatsby-plugin-offline/src/get-resources-from-html.js +++ b/packages/gatsby-plugin-offline/src/get-resources-from-html.js @@ -3,7 +3,7 @@ const path = require(`path`) const fs = require(`fs`) const _ = require(`lodash`) -module.exports = htmlPath => { +module.exports = (htmlPath, pathPrefix) => { // load index.html to pull scripts/links necessary for proper offline reload let html try { @@ -41,10 +41,15 @@ module.exports = htmlPath => { // Don't cache XML files, or external resources (beginning with // or http) const blackListRegex = /(\.xml$|^\/\/|^http)/ - if (!blackListRegex.test(url)) { + // check resource URLs from header tags start with the correct prefix + // (these are not page URLs) + if (!blackListRegex.test(url) && url.startsWith(pathPrefix)) { criticalFilePaths.push(url.replace(/^\//, ``)) } }) - return _.uniq(criticalFilePaths) + // Remove the custom prefix (if any) so Workbox can find the files. + // This is added back at runtime (see modifyUrlPrefix in gatsby-node.js) in + // order to serve from the correct location. + return _.uniq(criticalFilePaths).map(url => url.slice(pathPrefix.length)) } diff --git a/yarn.lock b/yarn.lock index 9446f390c306b..3eae92feb1862 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3001,6 +3001,13 @@ acorn-globals@^4.1.0, acorn-globals@^4.3.0, acorn-globals@^4.3.2: acorn "^6.0.1" acorn-walk "^6.0.1" +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= + dependencies: + acorn "^3.0.4" + acorn-jsx@^5.0.0, acorn-jsx@^5.0.1: version "5.0.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" @@ -3010,7 +3017,12 @@ acorn-walk@^6.0.1: version "6.1.1" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.1.tgz#d363b66f5fac5f018ff9c3a1e7b6f8e310cc3913" -acorn@^5.0.0, acorn@^5.2.1, acorn@^5.5.3: +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= + +acorn@^5.0.0, acorn@^5.2.1, acorn@^5.5.0, acorn@^5.5.3: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" @@ -3084,12 +3096,17 @@ ajv-errors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59" +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= + ajv-keywords@^3.1.0, ajv-keywords@^3.2.0, ajv-keywords@^3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== -ajv@^5.1.0, ajv@^5.3.0: +ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" dependencies: @@ -3662,7 +3679,7 @@ axobject-query@^2.0.2: dependencies: ast-types-flow "0.0.7" -babel-code-frame@6.26.0, babel-code-frame@^6.26.0: +babel-code-frame@6.26.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -4674,6 +4691,13 @@ caller-callsite@^2.0.0: dependencies: callsites "^2.0.0" +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= + dependencies: + callsites "^0.2.0" + caller-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" @@ -4684,6 +4708,11 @@ callsite@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= + callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" @@ -4973,6 +5002,11 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== + clap@^1.0.9: version "1.2.3" resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" @@ -5815,7 +5849,7 @@ cross-fetch@2.2.2: node-fetch "2.1.2" whatwg-fetch "2.0.4" -cross-spawn@5.1.0, cross-spawn@^5.0.1: +cross-spawn@5.1.0, cross-spawn@^5.0.1, cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" dependencies: @@ -7356,6 +7390,14 @@ eslint-plugin-react@^7.14.3: prop-types "^15.7.2" resolve "^1.10.1" +eslint-scope@^3.7.1: + version "3.7.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" + integrity sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-scope@^4.0.0, eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" @@ -7374,6 +7416,50 @@ eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" +eslint@^4.19.1: + version "4.19.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" + integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== + dependencies: + ajv "^5.3.0" + babel-code-frame "^6.22.0" + chalk "^2.1.0" + concat-stream "^1.6.0" + cross-spawn "^5.1.0" + debug "^3.1.0" + doctrine "^2.1.0" + eslint-scope "^3.7.1" + eslint-visitor-keys "^1.0.0" + espree "^3.5.4" + esquery "^1.0.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.0.1" + ignore "^3.3.3" + imurmurhash "^0.1.4" + inquirer "^3.0.6" + is-resolvable "^1.0.0" + js-yaml "^3.9.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^7.0.0" + progress "^2.0.0" + regexpp "^1.0.1" + require-uncached "^1.0.3" + semver "^5.3.0" + strip-ansi "^4.0.0" + strip-json-comments "~2.0.1" + table "4.0.2" + text-table "~0.2.0" + eslint@^5.16.0: version "5.16.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" @@ -7415,6 +7501,14 @@ eslint@^5.16.0: table "^5.2.3" text-table "^0.2.0" +espree@^3.5.4: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" + integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== + dependencies: + acorn "^5.5.0" + acorn-jsx "^3.0.0" + espree@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" @@ -7444,7 +7538,7 @@ espurify@^2.0.1: resolved "https://registry.yarnpkg.com/espurify/-/espurify-2.0.1.tgz#c25b3bb613863daa142edcca052370a1a459f41d" integrity sha512-7w/dUrReI/QbJFHRwfomTlkQOXaB1NuCrBRn5Y26HXn5gvh18/19AgLbayVrNxXQfkckvgrJloWyvZDuJ7dhEA== -esquery@^1.0.1: +esquery@^1.0.0, esquery@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" dependencies: @@ -7962,6 +8056,14 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + file-entry-cache@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" @@ -8180,6 +8282,16 @@ flagged-respawn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7" +flat-cache@^1.2.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" + integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== + dependencies: + circular-json "^0.3.1" + graceful-fs "^4.1.2" + rimraf "~2.6.2" + write "^0.2.1" + flat-cache@^2.0.0, flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -8842,6 +8954,11 @@ globals-docs@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/globals-docs/-/globals-docs-2.4.0.tgz#f2c647544eb6161c7c38452808e16e693c2dafbb" +globals@^11.0.1: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + globals@^11.1.0, globals@^11.7.0: version "11.7.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673" @@ -9901,7 +10018,7 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" -ignore@^3.3.5: +ignore@^3.3.3, ignore@^3.3.5: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" @@ -10113,7 +10230,7 @@ inline-style-prefixer@^5.1.0: dependencies: css-in-js-utils "^2.0.0" -inquirer@3.3.0, inquirer@^3.3.0: +inquirer@3.3.0, inquirer@^3.0.6, inquirer@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" dependencies: @@ -11435,7 +11552,7 @@ js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@3.13.1, js-yaml@^3.10.0, js-yaml@^3.11.0, js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.5.2, js-yaml@^3.8.1, js-yaml@^3.9.0: +js-yaml@3.13.1, js-yaml@^3.10.0, js-yaml@^3.11.0, js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.5.2, js-yaml@^3.8.1, js-yaml@^3.9.0, js-yaml@^3.9.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" dependencies: @@ -14765,6 +14882,11 @@ plop@^1.9.1: node-plop "=0.9.0" v8flags "^2.0.10" +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== + pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" @@ -16090,6 +16212,11 @@ regexp-tree@^0.1.6: resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.10.tgz#d837816a039c7af8a8d64d7a7c3cf6a1d93450bc" integrity sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ== +regexpp@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" + integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== + regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" @@ -16524,6 +16651,14 @@ require-package-name@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9" +require-uncached@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + require_optional@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e" @@ -16548,6 +16683,11 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1: expand-tilde "^2.0.0" global-modules "^1.0.0" +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= + resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" @@ -16669,6 +16809,13 @@ reusify@^1.0.0: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rewire@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/rewire/-/rewire-4.0.1.tgz#ba1100d400a9da759fe599fc6e0233f0879ed6da" + integrity sha512-+7RQ/BYwTieHVXetpKhT11UbfF6v1kGhKFrtZN7UDL2PybMsSt/rpLWeEUGF5Ndsl1D5BxiCB14VDJyoX+noYw== + dependencies: + eslint "^4.19.1" + rfc6902@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/rfc6902/-/rfc6902-3.0.2.tgz#b0edcf918d38d089b433764973dd6a195bcaed4e" @@ -16689,7 +16836,7 @@ rimraf@2, rimraf@^2.2.8, rimraf@^2.5.0, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2. dependencies: glob "^7.1.3" -rimraf@2.6.3: +rimraf@2.6.3, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" dependencies: @@ -17232,7 +17379,7 @@ slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" -slice-ansi@^1.0.0: +slice-ansi@1.0.0, slice-ansi@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" dependencies: @@ -18141,6 +18288,18 @@ synchronous-promise@^2.0.6: version "2.0.9" resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.9.tgz#b83db98e9e7ae826bf9c8261fd8ac859126c780a" +table@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" + integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== + dependencies: + ajv "^5.2.3" + ajv-keywords "^2.1.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" + table@^5.2.3, table@^5.4.1: version "5.4.4" resolved "https://registry.yarnpkg.com/table/-/table-5.4.4.tgz#6e0f88fdae3692793d1077fd172a4667afe986a6" @@ -18291,7 +18450,7 @@ text-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-2.0.0.tgz#43eabd1b495482fae4a2bf65e5f56c29f69220f6" integrity sha512-F91ZqLgvi1E0PdvmxMgp+gcf6q8fMH7mhdwWfzXnl1k+GbpQDmi8l7DzLC5JTASKbwpY3TfxajAUzAXcv2NmsQ== -text-table@0.2.0, text-table@^0.2.0: +text-table@0.2.0, text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -20062,6 +20221,13 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= + dependencies: + mkdirp "^0.5.1" + ws@^5.2.0: version "5.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"