Repository navigation
Expand file tree
/
Copy pathcli.js
More file actions
108 lines (96 loc) · 3.34 KB
/
Copy pathcli.js
File metadata and controls
108 lines (96 loc) · 3.34 KB
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
#!/usr/bin/env node
import { parseArgs } from 'node:util'
import { access, readFile } from 'node:fs/promises'
import { relative, resolve } from 'node:path'
import { pathToFileURL } from 'node:url'
import pkg from './package.json' with { type: 'json' }
import { run, log, SitemapError } from './index.js'
const HELP = `Usage: sscli [options]
Generate sitemaps for static sites from the filesystem.
Options:
-b, --base <url> base URL of the site (required)
-d, --dist <dir> directory to scan, and where sitemaps
are written (default: .)
-m, --match <glob> glob to match; repeatable
(default: **/*.html)
-i, --ignore <glob> glob to ignore; repeatable
(default: 404.html)
-f, --format <fmt> xml, txt or both (default: both;
xml with --stdout)
--urls <style> clean, slash or raw (default: clean)
--no-lastmod omit lastmod dates
--no-robots don't check html for noindex meta
-o, --stdout print to stdout instead of files
-v, --verbose log progress
-V, --version print version
-h, --help print this help
Config: package.json "sscli" key or sscli.config.js, read
from the current directory. Flags override config.`
/** @type {(msg: string) => never} */
const fail = (msg) => {
console.error(`sscli: ${msg}\nTry 'sscli --help' for usage.`)
process.exit(1)
}
/** @param {string} file */
const exists = (file) =>
access(file).then(
() => true,
() => false
)
/** @returns {Promise<{ file?: string, config: import('./index.js').Options }>} */
async function loadConfig() {
const js = resolve('sscli.config.js')
if (await exists(js)) {
return { file: js, config: (await import(pathToFileURL(js).href)).default }
}
const json = resolve('package.json')
if (await exists(json)) {
const { sscli } = JSON.parse(await readFile(json, 'utf8'))
if (sscli) return { file: json, config: sscli }
}
return { config: {} }
}
const { values } = (() => {
try {
return parseArgs({
allowNegative: true,
options: {
base: { type: 'string', short: 'b' },
dist: { type: 'string', short: 'd' },
match: { type: 'string', short: 'm', multiple: true },
ignore: { type: 'string', short: 'i', multiple: true },
format: { type: 'string', short: 'f' },
urls: { type: 'string' },
lastmod: { type: 'boolean' },
robots: { type: 'boolean' },
stdout: { type: 'boolean', short: 'o' },
verbose: { type: 'boolean', short: 'v' },
version: { type: 'boolean', short: 'V' },
help: { type: 'boolean', short: 'h' }
}
})
} catch (err) {
const e = /** @type {NodeJS.ErrnoException} */ (err)
if (!e.code?.startsWith('ERR_PARSE_ARGS_')) throw err
fail(e.message.split('. ')[0])
}
})()
if (values.help) {
console.log(HELP)
process.exit()
}
if (values.version) {
console.log(pkg.version)
process.exit()
}
const { file, config } = await loadConfig()
const opts = { ...config, ...values }
if (opts.verbose && file) log(`found config in ${relative(process.cwd(), file)}`)
if (!opts.base) fail('base URL is required: use --base, or set "base" in config')
try {
await run(opts)
} catch (err) {
if (err instanceof SitemapError) fail(err.message)
console.error(err)
process.exit(1)
}