Skip to content

Commit

Permalink
fix: add router base to each links
Browse files Browse the repository at this point in the history
fix #88
  • Loading branch information
NicoPennec committed Nov 7, 2019
1 parent d209b76 commit 9f378f3
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 26 deletions.
30 changes: 21 additions & 9 deletions lib/builder.js
@@ -1,4 +1,5 @@
const { hostname } = require('os')
const { join } = require('path')
const { URL } = require('url')

const isHTTPS = require('is-https')
Expand All @@ -9,17 +10,18 @@ const sm = require('sitemap')
*
* @param {Object} options
* @param {Array} routes
* @param {String} base
* @param {Request} req
* @returns {Sitemap} sitemap instance
*/
function createSitemap(options, routes, req = null) {
function createSitemap(options, routes, base = null, req = null) {
const sitemapConfig = {}

// Set cacheTime
sitemapConfig.cacheTime = options.cacheTime || 0

// Set sitemap hostname
sitemapConfig.hostname = getHostname(options, req)
sitemapConfig.hostname = getHostname(options, req, base)

// Set XML namespaces
sitemapConfig.xmlNs = options.xmlNs
Expand All @@ -46,6 +48,12 @@ function createSitemap(options, routes, req = null) {
})
}

// Normalize to absolute path each route URL
routes = routes.map(route => ({
...route,
url: join('.', route.url)
}))

// Set urls and ensure they are unique
sitemapConfig.urls = [...new Set(routes)]

Expand All @@ -57,17 +65,19 @@ function createSitemap(options, routes, req = null) {
* Initialize a fresh sitemapindex instance
*
* @param {Object} options
* @param {String} base
* @param {Request} req
* @returns {string}
*/
function createSitemapIndex(options, req = null) {
function createSitemapIndex(options, base = null, req = null) {
const sitemapIndexConfig = {}

// Set urls
const defaultHostname = getHostname(options, req)
const defaultHostname = getHostname(options, req, base)
sitemapIndexConfig.urls = options.sitemaps.map(options => {
const path = options.gzip ? `${options.path}.gz` : options.path
const hostname = options.hostname || defaultHostname
// Normalize to absolute path
const path = join('.', options.gzip ? `${options.path}.gz` : options.path)
const hostname = options.hostname ? getHostname(options, req, base) : defaultHostname
const url = new URL(path, hostname)
return url.href
})
Expand All @@ -90,11 +100,13 @@ function createSitemapIndex(options, req = null) {
*
* @param {Object} options
* @param {Request} req
* @param {string} base
* @returns {string}
*/
function getHostname(options, req) {
return (
options.hostname || (req && `${isHTTPS(req) ? 'https' : 'http'}://${req.headers.host}`) || `http://${hostname()}`
function getHostname(options, req, base) {
return join(
options.hostname || (req && `${isHTTPS(req) ? 'https' : 'http'}://${req.headers.host}`) || `http://${hostname()}`,
base
)
}

Expand Down
6 changes: 4 additions & 2 deletions lib/generator.js
Expand Up @@ -46,7 +46,8 @@ async function generateSitemap(options, globalCache, nuxtInstance) {

// Generate sitemap.xml
const routes = await cache.routes.get('routes')
const sitemap = await createSitemap(options, routes)
const base = nuxtInstance.options.router.base
const sitemap = await createSitemap(options, routes, base)
const xmlFilePath = path.join(nuxtInstance.options.generate.dir, options.path)
fs.outputFileSync(xmlFilePath, sitemap.toXML())
consola.success('Generated', getPathname(nuxtInstance.options.generate.dir, xmlFilePath))
Expand All @@ -73,7 +74,8 @@ async function generateSitemapIndex(options, globalCache, nuxtInstance) {
options = setDefaultSitemapIndexOptions(options)

// Generate sitemapindex.xml
const xml = createSitemapIndex(options)
const base = nuxtInstance.options.router.base
const xml = createSitemapIndex(options, base)
const xmlFilePath = path.join(nuxtInstance.options.generate.dir, options.path)
fs.outputFileSync(xmlFilePath, xml)
consola.success('Generated', getPathname(nuxtInstance.options.generate.dir, xmlFilePath))
Expand Down
12 changes: 8 additions & 4 deletions lib/middleware.js
Expand Up @@ -39,6 +39,8 @@ function registerSitemaps(options, globalCache, nuxtInstance, depth = 0) {
* @param {Nuxt} nuxtInstance
*/
function registerSitemap(options, globalCache, nuxtInstance) {
const base = nuxtInstance.options.router.base

// Init options
options = setDefaultSitemapOptions(options, nuxtInstance)

Expand All @@ -64,7 +66,7 @@ function registerSitemap(options, globalCache, nuxtInstance) {
try {
// Init sitemap
const routes = await cache.routes.get('routes')
const gzip = await createSitemap(options, routes, req).toGzip()
const gzip = await createSitemap(options, routes, base, req).toGzip()
// Send http response
res.setHeader('Content-Type', 'application/x-gzip')
res.setHeader('Content-Encoding', 'gzip')
Expand All @@ -89,7 +91,7 @@ function registerSitemap(options, globalCache, nuxtInstance) {
try {
// Init sitemap
const routes = await cache.routes.get('routes')
const xml = await createSitemap(options, routes, req).toXML()
const xml = await createSitemap(options, routes, base, req).toXML()
// Send http response
res.setHeader('Content-Type', 'application/xml')
res.end(xml)
Expand All @@ -110,6 +112,8 @@ function registerSitemap(options, globalCache, nuxtInstance) {
* @param {number} depth
*/
function registerSitemapIndex(options, globalCache, nuxtInstance, depth = 0) {
const base = nuxtInstance.options.router.base

// Init options
options = setDefaultSitemapIndexOptions(options)

Expand All @@ -118,7 +122,7 @@ function registerSitemapIndex(options, globalCache, nuxtInstance, depth = 0) {
nuxtInstance.addServerMiddleware({
path: options.pathGzip,
handler(req, res, next) {
const sitemapIndex = createSitemapIndex(options, req)
const sitemapIndex = createSitemapIndex(options, base, req)
const gzip = gzipSync(sitemapIndex)
res.setHeader('Content-Type', 'application/x-gzip')
res.setHeader('Content-Encoding', 'gzip')
Expand All @@ -131,7 +135,7 @@ function registerSitemapIndex(options, globalCache, nuxtInstance, depth = 0) {
nuxtInstance.addServerMiddleware({
path: options.path,
handler(req, res, next) {
const sitemapIndex = createSitemapIndex(options, req)
const sitemapIndex = createSitemapIndex(options, base, req)
res.setHeader('Content-Type', 'application/xml')
res.end(sitemapIndex)
}
Expand Down
2 changes: 2 additions & 0 deletions test/__snapshots__/module.test.js.snap
@@ -1,5 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`sitemap - advanced configuration external options custom base from router.base 1`] = `"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?><urlset xmlns=\\"http://www.sitemaps.org/schemas/sitemap/0.9\\" xmlns:news=\\"http://www.google.com/schemas/sitemap-news/0.9\\" xmlns:xhtml=\\"http://www.w3.org/1999/xhtml\\" xmlns:mobile=\\"http://www.google.com/schemas/sitemap-mobile/1.0\\" xmlns:image=\\"http://www.google.com/schemas/sitemap-image/1.1\\" xmlns:video=\\"http://www.google.com/schemas/sitemap-video/1.1\\"><url><loc>https://example.com/base/child</loc></url><url><loc>https://example.com/base/exclude</loc></url><url><loc>https://example.com/base/filtered</loc></url><url><loc>https://example.com/base/parent/child/subchild</loc></url><url><loc>https://example.com/base/parent/child</loc></url><url><loc>https://example.com/base/parent</loc></url><url><loc>https://example.com/base/sub</loc></url><url><loc>https://example.com/base/sub/sub</loc></url><url><loc>https://example.com/base/</loc></url></urlset>"`;
exports[`sitemap - generate mode sitemap.xml 1`] = `"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?><urlset xmlns=\\"http://www.sitemaps.org/schemas/sitemap/0.9\\" xmlns:news=\\"http://www.google.com/schemas/sitemap-news/0.9\\" xmlns:xhtml=\\"http://www.w3.org/1999/xhtml\\" xmlns:mobile=\\"http://www.google.com/schemas/sitemap-mobile/1.0\\" xmlns:image=\\"http://www.google.com/schemas/sitemap-image/1.1\\" xmlns:video=\\"http://www.google.com/schemas/sitemap-video/1.1\\"><url><loc>https://example.com/child</loc></url><url><loc>https://example.com/filtered</loc></url><url><loc>https://example.com/parent/child/subchild</loc></url><url><loc>https://example.com/parent/child</loc></url><url><loc>https://example.com/parent</loc></url><url><loc>https://example.com/sub</loc></url><url><loc>https://example.com/sub/sub</loc></url><url><loc>https://example.com/</loc></url></urlset>"`;
exports[`sitemap - minimal configuration sitemap.xml 1`] = `"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?><urlset xmlns=\\"http://www.sitemaps.org/schemas/sitemap/0.9\\" xmlns:news=\\"http://www.google.com/schemas/sitemap-news/0.9\\" xmlns:xhtml=\\"http://www.w3.org/1999/xhtml\\" xmlns:mobile=\\"http://www.google.com/schemas/sitemap-mobile/1.0\\" xmlns:image=\\"http://www.google.com/schemas/sitemap-image/1.1\\" xmlns:video=\\"http://www.google.com/schemas/sitemap-video/1.1\\"><url><loc>https://example.com/child</loc></url><url><loc>https://example.com/exclude</loc></url><url><loc>https://example.com/filtered</loc></url><url><loc>https://example.com/parent/child/subchild</loc></url><url><loc>https://example.com/parent/child</loc></url><url><loc>https://example.com/parent</loc></url><url><loc>https://example.com/sub</loc></url><url><loc>https://example.com/sub/sub</loc></url><url><loc>https://example.com/</loc></url></urlset>"`;
Expand Down
88 changes: 77 additions & 11 deletions test/module.test.js
Expand Up @@ -91,14 +91,13 @@ describe('sitemap - minimal configuration', () => {

describe('sitemap - advanced configuration', () => {
let nuxt = null
let xml = null

afterEach(async () => {
await nuxt.close()
})

describe('custom options', () => {
let xml = null

beforeAll(async () => {
nuxt = await startServer({
...config,
Expand Down Expand Up @@ -210,28 +209,46 @@ describe('sitemap - advanced configuration', () => {
})

describe('external options', () => {
let xml = null

beforeAll(async () => {
test('default hostname from build.publicPath', async () => {
nuxt = await startServer({
...config,
build: {
publicPath: 'https://example.com'
},
}
})

xml = await get('/sitemap.xml')
expect(xml).toContain('<loc>https://example.com/</loc>')
})

test('default routes from generate.routes', async () => {
nuxt = await startServer({
...config,
generate: {
routes: ['test']
},
sitemap: {
hostname: 'https://example.com/'
}
})

xml = await get('/sitemap.xml')
expect(xml).toContain('<loc>https://example.com/test</loc>')
})

test('default hostname from build.publicPath', () => {
expect(xml).toContain('<loc>https://example.com/</loc>')
})
test('custom base from router.base', async () => {
nuxt = await startServer({
...config,
router: {
base: '/base'
},
sitemap: {
hostname: 'https://example.com/'
}
})

test('default routes from generate.routes', () => {
expect(xml).toContain('<loc>https://example.com/test</loc>')
xml = await get('/base/sitemap.xml')
expect(xml).toMatchSnapshot()
})
})
})
Expand Down Expand Up @@ -375,6 +392,55 @@ describe('sitemapindex - advanced configuration', () => {
})
})

describe('sitemapindex - custom router base', () => {
let nuxt = null

beforeAll(async () => {
nuxt = await startServer({
...config,
router: {
base: '/base'
},
sitemap: {
hostname: 'https://example.com/',
sitemaps: [
{
path: '/sitemap-foo.xml',
routes: ['foo/1', 'foo/2']
},
{
hostname: 'https://example.fr/',
path: '/sitemap-bar.xml',
routes: ['bar/1', 'bar/2']
}
]
}
})
})

test('sitemapindex.xml', async () => {
const xml = await get('/base/sitemapindex.xml')
expect(xml).toContain('<loc>https://example.com/base/sitemap-foo.xml</loc>')
expect(xml).toContain('<loc>https://example.fr/base/sitemap-bar.xml</loc>')
})

test('sitemap-foo.xml', async () => {
const xml = await get('/base/sitemap-foo.xml')
expect(xml).toContain('<loc>https://example.com/base/foo/1</loc>')
expect(xml).toContain('<loc>https://example.com/base/foo/2</loc>')
})

test('sitemap-bar.xml', async () => {
const xml = await get('/base/sitemap-bar.xml')
expect(xml).toContain('<loc>https://example.fr/base/bar/1</loc>')
expect(xml).toContain('<loc>https://example.fr/base/bar/2</loc>')
})

afterAll(async () => {
await nuxt.close()
})
})

// TODO: describe('sitemapindex - multiple configuration', () => { ... })

describe('sitemap - generate mode', () => {
Expand Down

0 comments on commit 9f378f3

Please sign in to comment.