UNPKG

3.29 kBPlain TextView Raw
1#!/usr/bin/env node
2
3/* eslint-disable no-console */
4
5/**
6 * Dependencies.
7 */
8
9const chalk = require('chalk')
10const exists = require('fs').existsSync
11const Metalsmith = require('..')
12const program = require('commander')
13const resolve = require('path').resolve
14
15/**
16 * Usage.
17 */
18
19program
20 .version(require('../package.json').version)
21 .option('-c, --config <path>', 'configuration file location', 'metalsmith.json')
22
23/**
24 * Examples.
25 */
26
27program.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
42program.parse(process.argv)
43
44/**
45 * Config.
46 */
47
48const dir = process.cwd()
49const config = program.config
50const path = resolve(dir, config)
51if (!exists(path)) fatal('could not find a ' + config + ' configuration file.')
52
53let json
54try {
55 json = require(path)
56} catch (e) {
57 fatal('it seems like ' + config + ' is malformed.')
58}
59
60/**
61 * Metalsmith.
62 */
63
64const metalsmith = new Metalsmith(dir)
65if (json.source) metalsmith.source(json.source)
66if (json.destination) metalsmith.destination(json.destination)
67if (json.concurrency) metalsmith.concurrency(json.concurrency)
68if (json.metadata) metalsmith.metadata(json.metadata)
69if (json.clean != null) metalsmith.clean(json.clean)
70if (json.frontmatter != null) metalsmith.frontmatter(json.frontmatter)
71if (json.ignore != null) metalsmith.ignore(json.ignore)
72
73/**
74 * Plugins.
75 */
76
77normalize(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
109metalsmith.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
121function 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
139function 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
152function 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}