This repository has been archived by the owner on May 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 23
/
index.js
186 lines (153 loc) · 5.44 KB
/
index.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
var fs = require('fs'),
fsp = require('fs-promise'),
marked = require('marked'),
path = require('path');
var isDoc = /\/*-{3}([\s\S]*?)-{3,}/;
var isMeta = /([A-z][\w-]*)[ \t]*:[ \t]*([\w\-\.\/][^\n]*)/g;
module.exports = require('postcss').plugin('mdcss', function (opts) {
// set options object
opts = Object(opts);
/* set options */
opts.index = opts.index || 'index.html'; // index file
opts.theme = opts.theme || require('mdcss-theme-github'); // theme or default
opts.destination = path.join(process.cwd(), opts.destination || 'styleguide'); // destination path
opts.assets = (opts.assets || []).map(function (src) {
return path.join(process.cwd(), src);
}); // additional assets path
opts.markdownFiles = opts.markdownFiles || 'markdown'; // location of markdown import files
if (typeof opts.theme !== 'function') throw Error('The theme failed to load'); // throw if theme is not a function
if (opts.theme.type === 'mdcss-theme') opts.theme = opts.theme(opts); // conditionally set theme as executed theme
// return plugin
return function (css, result) {
// set current css directory or current directory
var dir = css.source.input.file ? path.dirname(css.source.input.file) : process.cwd();
// set documentation list, hash, and unique identifier
var list = [];
var hash = {};
var uniq = 0;
// walk comments
css.walkComments(function (comment) {
// if comment is documentation
if (isDoc.test(comment.text)) {
// set documentation object
var doc = {};
// filter documentation meta
doc.content = comment.text.replace(isDoc, function (isDoc0, metas) {
// push meta to documentation
if (metas) metas.replace(isMeta, function (isMeta0, name, value) {
doc[name] = value.trim();
});
// remove meta from documentation content
return '';
}).trim();
// conditionally set the closest documentation name
if (doc.title && !doc.name) {
doc.name = doc.title;
}
// else if (doc.section && !doc.name) { doc.name = doc.section; }
// conditionally import external content
if (!doc.content) {
// get comment source path
var src = comment.source.input.file;
// if the comment source path exists
if (src) {
// get the closest matching directory for this comment
var localdir = src ? path.dirname(src) : dir,
mdbase = doc.import,
mdspec;
// if there's no import specified, look for a md file with the title name inside the section folder
if (!mdbase) {
var mdFiles = opts.markdownFiles,
mdSection = doc.section.replace(' ', '-').toLowerCase(),
mdName = doc.title.replace(' ', '-').toLowerCase();
mdbase = mdFiles + '\/' + mdSection + '\/' + mdName + '.md';
// mdbase = mdspec = path.basename(src, path.extname(src));
if (doc.name) {
mdspec += '.' + doc.name;
}
// mdbase += '.md';
// mdspec += '.md';
}
// try to read the closest matching documentation
try {
if (mdspec) {
doc.content = marked(fs.readFileSync(path.join(localdir, mdspec), 'utf8'));
} else throw new Error();
} catch (error1) {
try {
doc.content = marked(fs.readFileSync(path.join(localdir, mdbase), 'utf8'));
} catch (error2) {
doc.content = '';
comment.warn(result, 'Documentation import "' + mdbase + '" could not be read.');
}
}
}
}
doc.content = marked(doc.content, opts.marked);
// set documentation context
doc.context = comment;
// insure documentation has unique name
// console.log(doc.name);
var name = doc.name || 'section' + ++uniq;
var uniqname = name;
while (uniqname in hash) uniqname = name + --uniq;
// push documentation to hash
hash[uniqname] = doc;
}
});
// console.log(Object.keys(hash));
// walk hashes
Object.keys(hash).forEach(function (name) {
// set documentation
var doc = hash[name];
// if documentation has a parent section
if ('section' in doc) {
// get parent section
var title = doc.section;
var sname = titleToName(title);
var parent = hash[sname];
// if parent section does not exist
if (!parent) {
// create parent section
parent = hash[sname] = {
title: title,
name: sname
};
// add parent section to list
list.push(parent);
}
if (!parent.children) parent.children = [];
// make documentation a child of the parent section
parent.children.push(doc);
doc.parent = parent;
}
// otherwise make documentation a child of list
else list.push(doc);
});
// return theme executed with parsed list, destination
return opts.theme({
list: list,
opts: opts
}).then(function (docs) {
// empty the destination directory
return fsp.emptyDir(opts.destination)
// then copy the theme assets into the destination
.then(function () {
return fsp.copy(docs.assets, opts.destination);
})
// then copy the compiled template into the destination
.then(function () {
return fsp.outputFile(path.join(opts.destination, opts.index), docs.template);
})
// then copy any of the additional assets into the destination
.then(function () {
return Promise.all(opts.assets.map(function (src) {
return fsp.copy(src, path.join(opts.destination, path.basename(src)));
}));
});
});
};
});
function titleToName(title) {
return title.replace(/\s+/g, '-').replace(/[^A-z0-9_-]/g, '').toLowerCase();
}