-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathmarkdown2bootstrap.js
executable file
·122 lines (103 loc) · 3.88 KB
/
markdown2bootstrap.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
#!/usr/bin/env node
/*jshint node:true, es5:true */
var argv = require('optimist').
usage('Usage: $0 [options] <doc.md ...>').
demand(1).
boolean('n').
describe('n', 'Turn off numbered sections').
boolean('h').
describe('h', 'Turn on bootstrap page header.').
describe('outputdir', 'Directory to put the converted files in.').
default('outputdir', '.').
argv,
pagedown = require('pagedown'),
converter = new pagedown.Converter(),
path = require('path'),
fs = require('fs'),
top_part = fs.readFileSync(__dirname + "/parts/top.html").toString(),
bottom_part = fs.readFileSync(__dirname + "/parts/bottom.html").toString(),
levels, toc, nextId;
function findTag(md, tag, obj) {
var re = new RegExp("^<!-- " + tag + ": (.+) -->", "m"), match = md.match(re);
if (!obj) { return; }
if (match) {
obj[tag] = match[1];
}
}
// Configure section and toc generation
converter.hooks.set("postConversion", function(text) {
return text.replace(/<(h(\d))>/g, function(match, p1, p2, offset, str) {
var i, levelStr = "";
levels[p1] = levels[p1] || 0;
// Figure out section number
if (!argv.n) {
// reset lower levels
for (i = Number(p2) + 1; levels["h"+i]; i++) {
levels["h"+i] = 0;
}
// grab higher levels
for (i = Number(p2) - 1; levels["h"+i]; i--) {
levelStr = levels["h"+i] + "." + levelStr;
}
levels[p1] = levels[p1] + 1;
levelStr = levelStr + levels[p1] + ". ";
}
// Add toc entry
toc.push({
levelStr: levelStr,
id: ++nextId,
title: str.slice(offset+4, str.slice(offset).indexOf("</h")+offset)
});
return "<h" + p2 + ' id="' + nextId + '">' + levelStr;
}).
replace(/<pre>/g, '<pre class="prettyprint">').
replace(/".*mailto%3a(.*)"/, function(match, p1) {
return "\"mailto:" + p1 + "\"";
});
});
// Create output directory
argv.outputdir = path.resolve(process.cwd(), argv.outputdir);
if (!fs.existsSync(argv.outputdir)) {
fs.mkdirSync(argv.outputdir);
}
argv._.forEach(function(md_path) {
var tags = { title: "TITLE HERE", subtitle: "SUBTITLE HERE" },
md, output, tocHtml = "",
output_path = path.join(argv.outputdir, path.basename(md_path));
// Determine output filename
if (/\.md$/.test(output_path)) {
output_path = output_path.slice(0, -3);
}
output_path += '.html';
// Read markdown in
md = fs.readFileSync(md_path).toString();
// Find title and subtitle tags in document
findTag(md, "title", tags);
findTag(md, "subtitle", tags);
levels = {}; nextId = 0; toc = [];
output = converter.makeHtml(md);
// Add table of contents
tocHtml += '<div class="span3 bs-docs-sidebar"><ul class="nav nav-list bs-docs-sidenav" data-spy="affix">';
toc.forEach(function(entry) {
tocHtml += '<li><a href="#' + entry.id + '">' + entry.levelStr + entry.title + '</a></li>';
});
tocHtml += '</ul></div><div class="span9">';
// Bootstrap-fy
output =
top_part.replace(/\{\{header\}\}/, function() {
if (argv.h) {
return '<header class="jumbotron subhead" id="overview">' +
'<div class="container">' +
'<h1>' + tags.title + '</h1>' +
'<p class="lead">' + tags.subtitle + '</p>' +
'</div></header>';
} else {
return "";
}
}).replace(/\{\{title\}\}/, tags.title === "TITLE HERE" ? "" : tags.title) +
tocHtml +
output +
bottom_part;
fs.writeFileSync(output_path, output);
console.log("Converted " + md_path + " to " + path.relative(process.cwd(), output_path));
});