|
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