Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable static routes filtering by route component config #101

Open
wants to merge 11 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,61 @@ You can combine sitemap and sitemap index configurations.
}
```

### Enable static routes filtering by route component config

Default route component with property `sitemap: true` will mark corresponding route to be included in sitemap.
Routes without this setting will be ignored.

```js
// nuxt.config.js

{
modules: [
'@nuxtjs/sitemap'
],
sitemap_filter: true,
sitemap: {
// custom configuration
}
}
```

```js
// route component
const Component = {
sitemap: true,
template: '<div>Hello!</div>'
}

// vue-router config
const router = new VueRouter({
routes: [
{ path: '/hello', component: Component },
]
})
```

Single File Components are supported (experimental, tested with Nuxt.js).

```js
// @/components/Hello.vue
<template>
<div>Hello!</div>
</template>
<script>
export default {
sitemap: true
}
</script>

// vue-router config
const router = new VueRouter({
routes: [
{ path: '/hello', component: '@/components/Hello.vue' },
]
})
```

## Sitemap Options

### `routes` (optional) - array | function
Expand Down
2 changes: 1 addition & 1 deletion lib/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module.exports = function module(moduleOptions) {
// Init static routes
nuxtInstance.extendRoutes(routes => {
// Create a cache for static routes
globalCache.staticRoutes = getStaticRoutes(routes)
globalCache.staticRoutes = getStaticRoutes.call(nuxtInstance, routes)

// On run cmd "build"
if (!nuxtInstance.options.dev) {
Expand Down
55 changes: 54 additions & 1 deletion lib/routes.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const fs = require('fs')
const { Minimatch } = require('minimatch')

/**
Expand All @@ -23,8 +24,12 @@ function excludeRoutes(patterns, routes) {
* @returns {string[]}
*/
function getStaticRoutes(router) {
const nuxtInstance = this

// Get all static routes and ignore dynamic routes
return flattenRoutes(router).filter(({ url }) => !url.includes(':') && !url.includes('*'))
return flattenRoutes(router)
.filter(({ url }) => !url.includes(':') && !url.includes('*'))
.filter(nuxtInstance.options.sitemap_filter === true ? _filter(nuxtInstance.options.alias) : route => route)
}

/**
Expand All @@ -50,4 +55,52 @@ function flattenRoutes(router, path = '', routes = []) {
return routes
}

function _filter(aliases) {
const prop = 'sitemap'
const value = true
const aliasesKeys = Object.keys(aliases || {}).join('|')
const reAliasReplacer = aliasesKeys && new RegExp(`^(${aliasesKeys})(.)`, 'g')
const aliasReplacer = (_s, alias, char) => aliases[alias] + ((char !== '/' && char !== '\\' && '/') || '') + char
const normalizeComponentPath = pathName =>
(reAliasReplacer && pathName && pathName.replace(reAliasReplacer, aliasReplacer)) || pathName

const extractComponentData = (text, ...exp) => {
return exp
.filter(re => re)
.reduce((out, re) => {
if (out) {
out = out.match(re)
return (out && out[1]) || void 0
}
}, text)
}

const re0 = /\.vue$/
const re1 = /<script[^>]*>([\s\S]*?)<\/script>/
const re2 = /export\s+default\s+({[\s\S]*?})[^}{]*$/
const re3 = new RegExp(prop + '\\s*:\\s*([^,\\s}]+)')

const filterByComponentConfig = component => {
if (component) {
if (typeof component === 'string') {
const componentPath = normalizeComponentPath(component)

if (componentPath) {
try {
return (
extractComponentData(fs.readFileSync(componentPath, 'utf8'), re0.test(componentPath) && re1, re2, re3) ===
value + ''
)
} catch (e) {}
}
} else if (typeof component === 'object') {
return (component.default || component)[prop] === value
}
}
return false
}

return ({ component }) => filterByComponentConfig(component)
}

module.exports = { excludeRoutes, getStaticRoutes }