|
1 |
| -var fs = require('fs'), |
2 |
| - path = require('path'), |
3 |
| - jade = require('jade'), |
4 |
| - md = require('node-markdown'), |
5 |
| - Class = require('neko').Class; |
6 |
| - |
7 |
| -var format = new require('fomatto').Formatter(); |
8 |
| - |
9 |
| - |
10 |
| -// Garden Generator ------------------------------------------------------------- |
11 |
| -// ------------------------------------------------------------------------------ |
12 |
| -var Garden = Class(function(options) { |
13 |
| - var languages = fs.readdirSync(options.dir); |
14 |
| - |
15 |
| - this.languages = {}; |
16 |
| - this.options = options; |
17 |
| - this.options.language = this.json([this.options.dir, 'language.json'].join('/')); |
18 |
| - |
19 |
| - var that = this; |
20 |
| - languages.forEach(function(lang) { |
21 |
| - if (fs.statSync(that.options.dir + '/' + lang).isDirectory()) { |
22 |
| - that.log('Parsing language "{}"...', lang); |
23 |
| - that.lang = { |
24 |
| - id: lang, |
25 |
| - navigation: [], |
26 |
| - index: [] |
27 |
| - }; |
28 |
| - |
29 |
| - if (that.loadIndex()) { |
30 |
| - that.languages[lang] = that.lang; |
31 |
| - that.log(' Done.'); |
32 |
| - |
33 |
| - } else { |
34 |
| - that.log(' Error: Could not find "index.json"!'); |
35 |
| - } |
36 |
| - } |
37 |
| - }); |
38 |
| - |
39 |
| - delete this.lang; |
40 |
| - this.log(''); |
41 |
| - this.generateAll(); |
42 |
| - |
43 |
| -}, { |
44 |
| - log: function() { |
45 |
| - console.log(format.apply(null, arguments)); |
46 |
| - }, |
47 |
| - |
48 |
| - loadIndex: function() { |
49 |
| - var that = this; |
50 |
| - this.lang.index = this.json([this.options.dir, |
51 |
| - this.lang.id, 'index.json'].join('/')); |
52 |
| - |
53 |
| - if (this.lang.index === null) { |
54 |
| - return false; |
55 |
| - } |
56 |
| - |
57 |
| - that.lang.title = that.lang.index.langTitle; |
58 |
| - this.lang.navigation = []; |
59 |
| - this.lang.index.sections.forEach(function(section, i) { |
60 |
| - that.loadSection(section); |
61 |
| - that.lang.navigation.push({ |
62 |
| - title: section.title, |
63 |
| - link: section.dir, |
64 |
| - articles: section.articles, |
65 |
| - parsed: section.parsed |
66 |
| - }); |
67 |
| - }); |
68 |
| - return true; |
69 |
| - }, |
70 |
| - |
71 |
| - loadSection: function(section) { |
72 |
| - var files = fs.readdirSync(this.folder(section.dir)); |
73 |
| - section.parsed = {}; |
74 |
| - section.link = section.dir; |
75 |
| - |
76 |
| - var that = this; |
77 |
| - section.articles = section.articles || []; |
78 |
| - section.articles.concat('index').forEach(function(article, e) { |
79 |
| - if (files.indexOf(article + '.md') !== -1) { |
80 |
| - var parsed = that.parseArticle(that.md(section.dir, article)); |
81 |
| - section.parsed[article] = parsed; |
82 |
| - if (section.articles.indexOf(article) !== -1) { |
83 |
| - section.articles[e] = { |
84 |
| - id: article, |
85 |
| - link: section.link + '.' + article, |
86 |
| - title: parsed.title, |
87 |
| - parsed: parsed |
88 |
| - }; |
89 |
| - } |
90 |
| - } |
91 |
| - }); |
92 |
| - }, |
93 |
| - |
94 |
| - parseArticle: function(text) { |
95 |
| - var title = text.substring(0, text.indexOf('\n')); |
96 |
| - text = text.substring(title.length); |
97 |
| - title = md.Markdown(title.replace(/\#/g, '').trim()); |
98 |
| - text = this.toMarkdown(text); |
99 |
| - |
100 |
| - var parts = text.split('<h3>'); |
101 |
| - var subs = []; |
102 |
| - for(var i = 0, l = parts.length; i < l; i++) { |
103 |
| - var sub = parts[i]; |
104 |
| - subs.push((i > 0 ? '<h3>' : '') + sub); |
105 |
| - } |
106 |
| - |
107 |
| - return { |
108 |
| - title: title.substring(3, title.length - 4), |
109 |
| - text: text, |
110 |
| - subs: subs |
111 |
| - }; |
112 |
| - }, |
113 |
| - |
114 |
| - toMarkdown: function(text) { |
115 |
| - text = md.Markdown(text).replace(/'/g,'''); |
116 |
| - text = text.replace(/<blockquote>/g, '<aside>'). |
117 |
| - replace(/<\/blockquote>/g, '</aside>'); |
118 |
| - |
119 |
| - return text.replace(/<aside>\s+<p><strong>ES5/g, |
120 |
| - '<aside class="es5"><p><strong>ES5'); |
121 |
| - }, |
122 |
| - |
123 |
| - json: function(file) { |
124 |
| - try { |
125 |
| - return JSON.parse(fs.readFileSync(file).toString()); |
126 |
| - |
127 |
| - } catch (err) { |
128 |
| - return null; |
129 |
| - } |
130 |
| - }, |
131 |
| - |
132 |
| - md: function(section, article) { |
133 |
| - var file = [this.folder(section), article].join('/') + '.md'; |
134 |
| - return fs.readFileSync(file).toString(); |
135 |
| - }, |
| 1 | +var fs = require("fs"); |
| 2 | +var _ = require("lodash"); |
| 3 | +var jade = require('jade'); |
| 4 | +var md = require("marked"); |
| 5 | + |
| 6 | +function main(opts) { |
| 7 | + loadLanguages(opts.languagesDir) |
| 8 | + .sort(function(a,b) { |
| 9 | + return a.id > b.id ? 1 : -1 |
| 10 | + }) |
| 11 | + .forEach(function(lang,_,languages) { |
| 12 | + outputLanguage(lang,languages,opts); |
| 13 | + }); |
| 14 | +} |
136 | 15 |
|
137 |
| - folder: function(section) { |
138 |
| - return [this.options.dir, this.lang.id, section].join('/'); |
139 |
| - }, |
| 16 | +function loadLanguages(path) { |
| 17 | + var index = readJson(path + "/language.json"); |
| 18 | + var availableListedLanguages = _.intersection(index.listed,fs.readdirSync(path)); |
| 19 | + return availableListedLanguages.reduce(function(all,lang) { |
| 20 | + var langPath = path + "/" + lang; |
| 21 | + if(!fs.statSync(langPath).isDirectory()) return all; |
| 22 | + var data = _.extend(loadLanguage(langPath),{id: lang}); |
| 23 | + return all.concat(data); |
| 24 | + },[]); |
| 25 | +} |
140 | 26 |
|
141 |
| - render: function(language, template, out) { |
142 |
| - var lang = this.languages[language]; |
143 |
| - if (lang) { |
144 |
| - this.log('Rendering "{}" to "{}"...', language, out); |
| 27 | +function loadLanguage(path) { |
| 28 | + var index = readJson(path + '/index.json'); |
| 29 | + var language = _.extend(index,{ |
| 30 | + sections: index.sections.map(function(section) { |
| 31 | + return _.extend(section,{ |
| 32 | + link: section.dir, |
| 33 | + isIntro: section.dir == "intro", |
| 34 | + articles: section.articles.map(function(article) { |
| 35 | + return _.extend({ |
| 36 | + link: section.dir + "." + article |
| 37 | + },loadArticle(path + "/" + section.dir + "/" + article + ".md")); |
| 38 | + }) |
| 39 | + }) |
| 40 | + }) |
| 41 | + }); |
| 42 | + language.navigation = language.sections; |
| 43 | + return language; |
| 44 | +} |
145 | 45 |
|
146 |
| - var languages = []; |
147 |
| - for(var i in this.languages) { |
148 |
| - if (this.languages.hasOwnProperty(i)) { |
149 |
| - if (this.options.language.listed.indexOf(i) !== -1) { |
150 |
| - languages.push(this.languages[i]); |
151 |
| - } |
152 |
| - } |
153 |
| - } |
| 46 | +function loadArticle(path) { |
| 47 | + var text = fs.readFileSync(path,"utf8"); |
| 48 | + var title = text.substring(0, text.indexOf('\n')); |
| 49 | + text = text.substring(title.length); |
| 50 | + title = md(title.replace(/\#/g, '').trim()); |
| 51 | + var titleText = title.substring(3, title.length - 5); |
| 52 | + text = processArticleBody(text); |
| 53 | + |
| 54 | + var parts = text.split('<h3>'); |
| 55 | + var subs = parts.map(function(sub,i) { |
| 56 | + return (i > 0 ? '<h3>' : '') + sub; |
| 57 | + }); |
| 58 | + |
| 59 | + return { |
| 60 | + title: titleText, |
| 61 | + text: text, |
| 62 | + subs: subs |
| 63 | + }; |
| 64 | +} |
154 | 65 |
|
155 |
| - var options = { |
156 |
| - pathPrefix: this.options.pathPrefix, |
157 |
| - baseLanguage: this.options.language.default, |
158 |
| - language: language, |
159 |
| - languages: languages, |
160 |
| - title: lang.index.title, |
161 |
| - description: lang.index.description, |
162 |
| - navigation: lang.navigation, |
163 |
| - sections: lang.index.sections, |
164 |
| - top: lang.navigation[0] |
165 |
| - }; |
| 66 | +function processArticleBody(text) { |
| 67 | + text = md(text).replace(/'/g,'''); |
| 68 | + text = text.replace(/<blockquote>/g, '<aside>'). |
| 69 | + replace(/<\/blockquote>/g, '</aside>'); |
166 | 70 |
|
167 |
| - var jadefile = fs.readFileSync(template); |
168 |
| - var jadetemplate = jade.compile (jadefile); |
169 |
| - var html = jadetemplate(options); |
170 |
| - fs.writeFileSync(out, html); |
171 |
| - this.log(' Done.'); |
172 |
| - } |
173 |
| - }, |
| 71 | + return text.replace(/<aside>\s+<p><strong>ES5/g, |
| 72 | + '<aside class="es5"><p><strong>ES5'); |
| 73 | +} |
174 | 74 |
|
175 |
| - generateAll: function() { |
176 |
| - for(var i in this.languages) { |
177 |
| - if (this.languages.hasOwnProperty(i)) { |
178 |
| - this.generate(i); |
179 |
| - } |
180 |
| - } |
181 |
| - }, |
| 75 | +function readJson(path) { |
| 76 | + return JSON.parse(fs.readFileSync(path,"utf-8")); |
| 77 | +} |
182 | 78 |
|
183 |
| - generate: function(lang) { |
184 |
| - var that = this; |
| 79 | +function outputLanguage(lang,languages,opts) { |
| 80 | + var langBase = lang.id == opts.baseLanguage ? "/" : "/" + lang.id; |
| 81 | + fs.mkdir(opts.outDir + langBase,function(err) { |
| 82 | + if(err && err.code != "EEXIST") { |
| 83 | + console.error("Couldn't make dir " + opts.outDir + ": " + err); |
| 84 | + process.exit(1); |
| 85 | + } |
| 86 | + var out = opts.outDir + langBase + "/index.html"; |
| 87 | + var perLangOpts = _.extend({out: out,languages: languages},opts); |
| 88 | + writeTemplate(perLangOpts,lang); |
| 89 | + }) |
| 90 | +} |
185 | 91 |
|
186 |
| - var dir = [this.options.out]; |
187 |
| - if (lang !== this.options.language.default) { |
188 |
| - dir.push(lang); |
189 |
| - } |
190 |
| - dir = dir.join('/'); |
| 92 | +function writeTemplate(options,language) { |
| 93 | + var templateData = _.extend({language: language.id},language,options); |
191 | 94 |
|
192 |
| - path.exists(dir, function(exists) { |
193 |
| - if (!exists) { |
194 |
| - fs.mkdirSync(dir, '777'); |
195 |
| - } |
196 |
| - that.render(lang, that.options.template, dir + '/index.html'); |
197 |
| - }); |
198 |
| - } |
199 |
| -}); |
| 95 | + var jadefile = fs.readFileSync(options.template); |
| 96 | + var jadetemplate = jade.compile(jadefile,{compileDebug: false,debug: false}); |
| 97 | + var html = jadetemplate(templateData); |
| 98 | + fs.writeFileSync(options.out, html); |
| 99 | +} |
200 | 100 |
|
201 |
| -exports.build = function (options) { |
202 |
| - options = options || {dir: 'doc', pathPrefix: 'JavaScript-Garden/', template: 'garden.jade', out: 'site'}; |
203 |
| - new Garden(options); |
| 101 | +exports.build = function (opts) { |
| 102 | + opts = _.defaults(opts || {},{ languagesDir: "doc", baseLanguage: "en", template: 'garden.jade', pathPrefix: 'JavaScript-Garden/', outDir: "site" }); |
| 103 | + return main(opts); |
204 | 104 | }
|
205 | 105 |
|
206 | 106 | exports.build();
|
0 commit comments