1 | #!/usr/bin/env node
|
2 |
|
3 | /* eslint-disable no-console */
|
4 |
|
5 | /**
|
6 | * Dependencies.
|
7 | */
|
8 |
|
9 | const chalk = require('chalk')
|
10 | const exists = require('fs').existsSync
|
11 | const Metalsmith = require('..')
|
12 | const program = require('commander')
|
13 | const resolve = require('path').resolve
|
14 |
|
15 | /**
|
16 | * Usage.
|
17 | */
|
18 |
|
19 | program
|
20 | .version(require('../package.json').version)
|
21 | .option('-c, --config <path>', 'configuration file location', 'metalsmith.json')
|
22 |
|
23 | /**
|
24 | * Examples.
|
25 | */
|
26 |
|
27 | program.on('--help', function(){
|
28 | console.log(' Examples:')
|
29 | console.log()
|
30 | console.log(' # build from metalsmith.json:')
|
31 | console.log(' $ metalsmith')
|
32 | console.log()
|
33 | console.log(' # build from lib/config.json:')
|
34 | console.log(' $ metalsmith --config lib/config.json')
|
35 | console.log()
|
36 | })
|
37 |
|
38 | /**
|
39 | * Parse.
|
40 | */
|
41 |
|
42 | program.parse(process.argv)
|
43 |
|
44 | /**
|
45 | * Config.
|
46 | */
|
47 |
|
48 | const dir = process.cwd()
|
49 | const config = program.config
|
50 | const path = resolve(dir, config)
|
51 | if (!exists(path)) fatal('could not find a ' + config + ' configuration file.')
|
52 |
|
53 | let json
|
54 | try {
|
55 | json = require(path)
|
56 | } catch (e) {
|
57 | fatal('it seems like ' + config + ' is malformed.')
|
58 | }
|
59 |
|
60 | /**
|
61 | * Metalsmith.
|
62 | */
|
63 |
|
64 | const metalsmith = new Metalsmith(dir)
|
65 | if (json.source) metalsmith.source(json.source)
|
66 | if (json.destination) metalsmith.destination(json.destination)
|
67 | if (json.concurrency) metalsmith.concurrency(json.concurrency)
|
68 | if (json.metadata) metalsmith.metadata(json.metadata)
|
69 | if (json.clean != null) metalsmith.clean(json.clean)
|
70 | if (json.frontmatter != null) metalsmith.frontmatter(json.frontmatter)
|
71 | if (json.ignore != null) metalsmith.ignore(json.ignore)
|
72 |
|
73 | /**
|
74 | * Plugins.
|
75 | */
|
76 |
|
77 | normalize(json.plugins).forEach(function(plugin){
|
78 | for (const name in plugin) {
|
79 | const opts = plugin[name]
|
80 | let mod
|
81 |
|
82 | try {
|
83 | const local = resolve(dir, name)
|
84 | const npm = resolve(dir, 'node_modules', name)
|
85 |
|
86 | if (exists(local) || exists(local + '.js')) {
|
87 | mod = require(local)
|
88 | } else if (exists(npm)) {
|
89 | mod = require(npm)
|
90 | } else {
|
91 | mod = require(name)
|
92 | }
|
93 | } catch (e) {
|
94 | fatal('failed to require plugin "' + name + '".')
|
95 | }
|
96 |
|
97 | try {
|
98 | metalsmith.use(mod(opts))
|
99 | } catch (e) {
|
100 | fatal('error using plugin "' + name + '"...', e.message + '\n\n' + e.stack)
|
101 | }
|
102 | }
|
103 | })
|
104 |
|
105 | /**
|
106 | * Build.
|
107 | */
|
108 |
|
109 | metalsmith.build(function(err){
|
110 | if (err) return fatal(err.message, err.stack)
|
111 | log('successfully built to ' + metalsmith.destination())
|
112 | })
|
113 |
|
114 | /**
|
115 | * Log an error and then exit the process.
|
116 | *
|
117 | * @param {String} msg
|
118 | * @param {String} [stack] Optional stack trace to print.
|
119 | */
|
120 |
|
121 | function fatal(msg, stack){
|
122 | console.error()
|
123 | console.error(chalk.red(' Metalsmith') + chalk.gray(' · ') + msg)
|
124 | if (stack) {
|
125 | console.error()
|
126 | console.error(chalk.gray(stack))
|
127 | }
|
128 | console.error()
|
129 | // eslint-disable-next-line no-process-exit
|
130 | process.exit(1)
|
131 | }
|
132 |
|
133 | /**
|
134 | * Log a `message`.
|
135 | *
|
136 | * @param {String} message
|
137 | */
|
138 |
|
139 | function log(message){
|
140 | console.log()
|
141 | console.log(chalk.gray(' Metalsmith · ') + message)
|
142 | console.log()
|
143 | }
|
144 |
|
145 | /**
|
146 | * Normalize an `obj` of plugins.
|
147 | *
|
148 | * @param {Array or Object} obj
|
149 | * @return {Array}
|
150 | */
|
151 |
|
152 | function normalize(obj){
|
153 | if (obj instanceof Array) return obj
|
154 | const ret = []
|
155 |
|
156 | for (const key in obj) {
|
157 | const plugin = {}
|
158 | plugin[key] = obj[key]
|
159 | ret.push(plugin)
|
160 | }
|
161 |
|
162 | return ret
|
163 | }
|