/
module.js
123 lines (99 loc) · 3.06 KB
/
module.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
115
116
117
118
119
120
121
122
123
const { resolve } = require('path')
const { existsSync, readFileSync, writeFileSync } = require('fs')
module.exports = function (moduleOptions) {
const { rootDir, srcDir, dir: { static: staticDir }, generate: { dir: generateDir } } = this.options
const options = getOptions.call(this, moduleOptions)
const fileName = 'robots.txt'
let staticRules = []
// read static robots.txt
this.nuxt.hook('build:before', async () => {
const staticFilePath = resolve(srcDir, staticDir, fileName)
if (existsSync(staticFilePath)) {
const content = readFileSync(staticFilePath).toString()
staticRules = await getRules.call(this, parseFile(content))
}
})
// generate robots.txt in dist
this.nuxt.hook('generate:done', async () => {
const generateFilePath = resolve(rootDir, generateDir, fileName)
const rules = await getRules.call(this, options)
writeFileSync(generateFilePath, render([...staticRules, ...rules]))
})
// render robots.txt via SSR
this.nuxt.hook('render:setupMiddleware', () => {
const moduleContainer = this
this.nuxt.server.useMiddleware({
path: fileName,
async handler (req, res) {
const rules = await getRules.call(moduleContainer, options, req)
res.setHeader('Content-Type', 'text/plain')
res.end(render([...staticRules, ...rules]))
}
})
})
}
function getOptions (moduleOptions) {
const defaults = {
UserAgent: '*',
Disallow: ''
}
let options = null
if (Array.isArray(moduleOptions)) {
options = moduleOptions
} else if (Array.isArray(this.options.robots)) {
options = this.options.robots
} else {
options = {
...defaults,
...this.options.robots,
...moduleOptions
}
}
return options
}
async function getRules (options, req = null) {
const correspondances = {
UserAgent: 'User-agent',
CrawlDelay: 'Crawl-delay',
Disallow: 'Disallow',
Allow: 'Allow',
Host: 'Host',
Sitemap: 'Sitemap',
CleanParam: 'Clean-param',
'User-agent': 'User-agent',
'Crawl-delay': 'Crawl-delay',
'Clean-param': 'Clean-param'
}
const rules = []
const items = Array.isArray(options) ? options : [options]
for (const item of items) {
const keys = Object.keys(correspondances).filter(key => typeof item[key] !== 'undefined')
for (const key of keys) {
let values = typeof item[key] === 'function' ? await item[key].call(this, req) : item[key]
values = (Array.isArray(values)) ? values : [values]
for (const value of values) {
rules.push({
key: correspondances[key],
value: typeof value === 'function' ? await value.call(this, req) : value
})
}
}
}
return rules
}
function render (rules) {
return rules.map(rule => `${rule.key}: ${String(rule.value).trim()}`).join('\n')
}
function parseFile (content) {
const rules = []
content.split('\n').forEach((item) => {
const ar = item.split(':')
if (ar[0]) {
rules.push({
[ar[0]]: ar[1]
})
}
})
return rules
}
module.exports.meta = require('../package.json')