diff --git a/lib/constants.js b/lib/constants.js new file mode 100644 index 0000000..8c0d207 --- /dev/null +++ b/lib/constants.js @@ -0,0 +1,4 @@ +module.exports = { + COMPONENT_OPTIONS_BLOCK: 'script', + COMPONENT_OPTIONS_KEY: 'sitemap' +} diff --git a/lib/extractComponentOptions.js b/lib/extractComponentOptions.js new file mode 100644 index 0000000..66fe625 --- /dev/null +++ b/lib/extractComponentOptions.js @@ -0,0 +1,51 @@ +const { readFileSync } = require('fs') + +const acorn = require('acorn') +const dynamicImport = require('acorn-dynamic-import') +const inject = require('acorn-dynamic-import/lib/walk') +const walker = inject.default(require('acorn-walk')) +// Must not be an explicit dependency to avoid version mismatch issue. +// See https://github.com/nuxt-community/nuxt-i18n/issues/297 +const compiler = require('vue-template-compiler') +// const { COMPONENT_OPTIONS_BLOCK, COMPONENT_OPTIONS_KEY } = require('constants') + +function extractComponentOptions (path, blockName, key) { + let extractedData = key ? '' : {} + let Component = compiler.parseComponent(readFileSync(path).toString()) + const block = + Component[blockName] || + Component.customBlocks.find(block => block.type === blockName) + if (!block || block.content.length < 1) { + return extractedData + } + const parsed = acorn.Parser.extend(dynamicImport.default).parse( + block.content, + { + ecmaVersion: 10, + sourceType: 'module' + } + ) + walker.simple( + parsed, + { + Property (node) { + const data = block.content.substring(node.start, node.end) + try { + if (key) { + if (node.key.name === key) extractedData = eval(`({${data}})`)[key] // eslint-disable-line no-eval + } else Object.assign(extractedData, eval(`({${data}})`)) // eslint-disable-line no-eval + } catch (e) {} + } + }, + walker.base + ) + + return extractedData +} + +module.exports = extractComponentOptions +// .bind( +// this, +// COMPONENT_OPTIONS_BLOCK, +// COMPONENT_OPTIONS_KEY +// ) diff --git a/lib/module.js b/lib/module.js index 5559cb5..f9c0a8b 100644 --- a/lib/module.js +++ b/lib/module.js @@ -8,7 +8,8 @@ const AsyncCache = require('async-cache') const consola = require('consola') const { promisify } = require('util') const { hostname } = require('os') - +const extractComponentOptions = require('./extractComponentOptions') +const { COMPONENT_OPTIONS_BLOCK, COMPONENT_OPTIONS_KEY } = require('./constants') const defaultPublicPath = '/_nuxt/' module.exports = function module (moduleOptions) { @@ -54,13 +55,16 @@ module.exports = function module (moduleOptions) { this.extendRoutes(routes => { // Get all static routes and ignore dynamic routes let staticRoutes = flattenRoutes(routes) - .filter(r => !r.includes(':') && !r.includes('*')) + .filter(r => !r.url.includes(':') && !r.url.includes('*')) + .filter(route => { + return extractComponentOptions(route.component, COMPONENT_OPTIONS_BLOCK, COMPONENT_OPTIONS_KEY) !== false + }) // Exclude routes options.exclude.forEach(pattern => { const minimatch = new Minimatch(pattern) minimatch.negate = true - staticRoutes = staticRoutes.filter(route => minimatch.match(route)) + staticRoutes = staticRoutes.filter(route => minimatch.match(route.url)) }) // Create a cache for routes @@ -232,7 +236,7 @@ function flattenRoutes (router, path = '', routes = []) { flattenRoutes(r.children, path + r.path + '/', routes) } if (r.path !== '') { - routes.push(path + r.path) + routes.push({ ...r, url: path + r.path }) } }) return routes diff --git a/package.json b/package.json index 6fd07fb..3086fe4 100755 --- a/package.json +++ b/package.json @@ -46,6 +46,9 @@ "testEnvironment": "node" }, "dependencies": { + "acorn": "^6.1.1", + "acorn-dynamic-import": "^4.0.0", + "acorn-walk": "^6.1.1", "async-cache": "^1.1.0", "consola": "^2.6.1", "fs-extra": "^8.0.0", diff --git a/test/fixture/pages/excluded-via-component-options.vue b/test/fixture/pages/excluded-via-component-options.vue new file mode 100644 index 0000000..bcd2f71 --- /dev/null +++ b/test/fixture/pages/excluded-via-component-options.vue @@ -0,0 +1,10 @@ + + diff --git a/test/module.test.js b/test/module.test.js index 4c09919..d5a0e7d 100644 --- a/test/module.test.js +++ b/test/module.test.js @@ -51,6 +51,8 @@ describe('ssr', () => { // excluded routes html = await get('/exclude') expect(html).toContain('/exclude') + html = await get('/excluded-via-component-options') + expect(html).toContain('/excluded-via-component-options') // filtered routes html = await get('/filtered') @@ -79,6 +81,7 @@ describe('ssr', () => { // excluded routes expect(xml).not.toContain('http://localhost:3000/exclude') + expect(xml).not.toContain('http://localhost:3000/excluded-via-component-options') // filtered routes expect(xml).not.toContain('http://localhost:3000/filtered')