-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathmake_sitemap.js
114 lines (95 loc) · 3.39 KB
/
make_sitemap.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
const fs = require('fs')
const path = require('path')
const util = require('util')
const globby = require('globby')
const mkdirp = require('mkdirp')
const { createSitemap } = require('sitemap')
const ensureTrailingSlash = (url) => (url.endsWith('/') ? url : `${url}/`)
const getPaths = async ({ distPath, exclude = [], cwd = '.' }) => {
const relPath = getRelPath(distPath, cwd)
const htmlFiles = relPath === '' ? '**/**.html' : `${relPath}/**/**.html`
const excludeFiles = exclude.map((excludedPath) => `!${getRelPath(excludedPath, cwd).replace(/^!/, '')}`)
const lookup = [htmlFiles, ...excludeFiles]
const paths = await globby(lookup, { cwd })
return paths
}
// Globbing patterns cannot use backslashes, but Windows use some. It cannot use
// Windows drives.
// Note: this does not apply to `globby` `cwd` option.
const getRelPath = function (filePath, cwd) {
const relPath = path.isAbsolute(filePath) ? path.relative(cwd, filePath) : filePath
return relPath.replace(/\\/g, '/')
}
const prettifyUrl = ({ url, trailingSlash }) => {
const prettyUrl = url.replace(/\/?index\.html$/, '').replace(/\.html$/, '')
if (!trailingSlash) {
return prettyUrl
}
return ensureTrailingSlash(prettyUrl)
}
const getUrlFromFile = ({ file, distPath, prettyURLs, trailingSlash }) => {
const url = path.relative(distPath, file)
if (!prettyURLs) {
return url
}
const prettyUrl = prettifyUrl({ url, trailingSlash })
return prettyUrl
}
const getUrlsFromPaths = ({ paths, distPath, prettyURLs, trailingSlash, changeFreq, priority, cwd, urlPrefix }) => {
const urls = paths.map((file) => {
const url = getUrlFromFile({ file, distPath, prettyURLs, trailingSlash })
return {
url: (urlPrefix ? urlPrefix + url : url).replace('//', '/'),
changefreq: changeFreq,
priority,
lastmodrealtime: true,
lastmodfile: cwd === undefined ? file : path.resolve(cwd, file),
}
})
return urls
}
const DEFAULT_CHANGE_FREQ = 'weekly'
const DEFAULT_PRIORITY = 0.8
// 600 sec cache period
const DEFAULT_CACHE_TIME = 600000
// Creates a sitemap object given the input configuration with URLs and generates XML
const createSitemapInfo = async function ({ homepage, urls, failBuild }) {
try {
const hostname = ensureTrailingSlash(homepage)
const sitemap = createSitemap({ hostname, cacheTime: DEFAULT_CACHE_TIME, urls })
await util.promisify(sitemap.toXML.bind(sitemap))()
const xml = sitemap.toString()
return { sitemap, xml }
} catch (error) {
return failBuild('Could not generate XML sitemap', { error })
}
}
module.exports = async function makeSitemap(opts = {}) {
const {
distPath,
fileName,
homepage,
urlPrefix,
exclude,
prettyURLs,
trailingSlash,
failBuild,
cwd,
changeFreq = DEFAULT_CHANGE_FREQ,
priority = DEFAULT_PRIORITY,
} = opts
const paths = await getPaths({ distPath, exclude, cwd })
const urls = getUrlsFromPaths({ paths, distPath, prettyURLs, trailingSlash, changeFreq, priority, cwd, urlPrefix })
const { sitemap, xml } = await createSitemapInfo({ homepage, urls, failBuild })
// write sitemap to file
const sitemapFileName = fileName || 'sitemap.xml'
const sitemapFile = path.resolve(distPath, sitemapFileName)
await mkdirp(path.dirname(sitemapFile))
// Write sitemap
await util.promisify(fs.writeFile)(sitemapFile, xml)
// Return info
return {
sitemapPath: sitemapFileName,
sitemap,
}
}