-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
makehtml.cmd.js
195 lines (178 loc) · 5.56 KB
/
makehtml.cmd.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
var yargs = require('yargs'),
fs = require('fs'),
Messenger = require('./messenger.js'),
showdown = require('../../dist/showdown'),
showdownOptions = showdown.getDefaultOptions(false);
yargs.reset()
.usage('Usage: showdown makehtml [options]')
.example('showdown makehtml -i', 'Reads from stdin and outputs to stdout')
.example('showdown makehtml -i foo.md -o bar.html', 'Reads \'foo.md\' and writes to \'bar.html\'')
.example('showdown makehtml -i --flavor="github"', 'Parses stdin using GFM style')
.version()
.alias('v', 'version')
.config('c')
.alias('c', 'config')
.help('h')
.alias('h', 'help')
.option('i', {
alias : 'input',
describe: 'Input source. Usually a md file. If omitted or empty, reads from stdin',
type: 'string'
})
.option('o', {
alias : 'output',
describe: 'Output target. Usually a html file. If omitted or empty, writes to stdout',
type: 'string',
default: false
})
.option('u', {
alias : 'encoding',
describe: 'Input encoding',
type: 'string'
})
.option('a', {
alias : 'append',
describe: 'Append data to output instead of overwriting',
type: 'string',
default: false
})
.option('e', {
alias : 'extensions',
describe: 'Load the specified extensions. Should be valid paths to node compatible extensions',
type: 'array'
})
.option('p', {
alias : 'flavor',
describe: 'Run with a predetermined flavor of options. Default is vanilla',
type: 'string'
})
.option('q', {
alias: 'quiet',
description: 'Quiet mode. Only print errors',
type: 'boolean',
default: false
})
.option('m', {
alias: 'mute',
description: 'Mute mode. Does not print anything',
type: 'boolean',
default: false
});
// load showdown default options
for (var opt in showdownOptions) {
if (showdownOptions.hasOwnProperty(opt)) {
if (showdownOptions[opt].defaultValue === false) {
showdownOptions[opt].default = null;
} else {
showdownOptions[opt].default = showdownOptions[opt].defaultValue;
}
yargs.option(opt, showdownOptions[opt]);
}
}
function run() {
'use strict';
var argv = yargs.argv,
readMode = (!argv.i || argv.i === '') ? 'stdin' : 'file',
writeMode = (!argv.o || argv.o === '') ? 'stdout' : 'file',
msgMode = (writeMode === 'file') ? 'stdout' : 'stderr',
/**
* MSG object
* @type {Messenger}
*/
messenger = new Messenger(msgMode, argv.q, argv.m),
read = (readMode === 'stdin') ? readFromStdIn : readFromFile,
write = (writeMode === 'stdout') ? writeToStdOut : writeToFile,
enc = argv.encoding || 'utf8',
flavor = argv.p,
append = argv.a || false,
options = parseOptions(flavor),
converter = new showdown.Converter(options),
md, html;
// Load extensions
if (argv.e) {
messenger.printMsg('Loading extensions');
for (var i = 0; i < argv.e.length; ++i) {
try {
var ext = require(argv.e[i]);
converter.addExtension(ext, argv.e[i]);
} catch (e) {
messenger.printError('Could not load extension ' + argv.e[i] + '. Reason:');
messenger.errorExit(e);
}
}
}
messenger.printMsg('...');
// read the input
messenger.printMsg('Reading data from ' + readMode + '...');
md = read(enc);
// process the input
messenger.printMsg('Parsing markdown...');
html = converter.makeHtml(md);
// write the output
messenger.printMsg('Writing data to ' + writeMode + '...');
write(html, append);
messenger.okExit();
function parseOptions(flavor) {
var options = {},
flavorOpts = showdown.getFlavorOptions(flavor) || {};
// if flavor is not undefined, let's tell the user we're loading that preset
if (flavor) {
messenger.printMsg('Loading ' + flavor + ' flavor.');
}
for (var opt in argv) {
if (argv.hasOwnProperty(opt)) {
// first we load the default options
if (showdownOptions.hasOwnProperty(opt) && showdownOptions[opt].default !== null) {
options[opt] = showdownOptions[opt].default;
}
// we now override defaults with flavor, if a flavor was indeed passed
if (flavorOpts.hasOwnProperty(opt)) {
options[opt] = flavorOpts[opt];
}
// lastly we override with explicit passed options
// being careful not to pass CLI specific options, such as -v, -h or --extensions
if (showdownOptions.hasOwnProperty(opt)) {
if (argv[opt] === true) {
messenger.printMsg('Enabling option ' + opt);
options[opt] = argv[opt];
} else if (argv[opt] === false) {
options[opt] = argv[opt];
}
}
}
}
return options;
}
function readFromStdIn() {
try {
var size = fs.fstatSync(process.stdin.fd).size;
return size > 0 ? fs.readSync(process.stdin.fd, size)[0] : '';
} catch (e) {
var err = new Error('Could not read from stdin, reason: ' + e.message);
messenger.errorExit(err);
}
}
function readFromFile(encoding) {
try {
return fs.readFileSync(argv.i, encoding);
} catch (err) {
messenger.errorExit(err);
}
}
function writeToStdOut(html) {
return process.stdout.write(html);
}
function writeToFile(html, append) {
// If a flag is passed, it means we should append instead of overwriting.
// Only works with files, obviously
var write = (append) ? fs.appendFileSync : fs.writeFileSync;
try {
write(argv.o, html);
} catch (err) {
messenger.errorExit(err);
}
}
}
module.exports = exports = {
run: run
};