Skip to content
This repository has been archived by the owner on Nov 21, 2018. It is now read-only.

#264 build process - adds various i18n helpers, html-based templates #276

Merged
merged 19 commits into from
Mar 17, 2015
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
dbf55ed
build: allow content/*.html content, scopes handlebars parser, adds i…
snostorm Mar 5, 2015
6095c6f
Watch: templates also watch for .html
snostorm Mar 5, 2015
2f0695e
template: handlebars helpers {{i18n [scope], key}}, {{hb [scope], key…
snostorm Mar 5, 2015
848351a
Adds proof-of-concept home.html (to replace index.html globally)
snostorm Mar 5, 2015
6d52787
templates: adds {{link REFERENCE}} helper, example (home.short_descri…
snostorm Mar 5, 2015
c9cf070
templates: adds {{link REFERENCE}} helper, switches home phrases out
snostorm Mar 5, 2015
8c9a676
home template: i18n changelog link
snostorm Mar 5, 2015
c5cc168
Adds cn/home.html example, adds warnings about replicating experiment…
snostorm Mar 5, 2015
6d6b6e5
Merge branch 'master' into 264_build_process_2
snostorm Mar 7, 2015
22def57
Replaces sample {cn,en}/home.html
snostorm Mar 10, 2015
1979fab
Adds source/{content,languages}.js
snostorm Mar 10, 2015
0624de5
Splits template.js -> util/content + new “content” gulp task
snostorm Mar 10, 2015
bd9d0ea
Merge remote-tracking branch 'origin/master' into 264_build_process_2
snostorm Mar 10, 2015
6b68646
.html-content template build improvements**
snostorm Mar 10, 2015
d285844
home.styl syntax fix
snostorm Mar 12, 2015
6846239
home.styl syntax fix
snostorm Mar 12, 2015
db5e444
Merge remote-tracking branch 'origin/master' into 264_build_process_2
snostorm Mar 15, 2015
f453c3a
bumps homepage content to latest master
snostorm Mar 15, 2015
74f7f44
build: style and arguments usage cleanup
Fishrock123 Mar 16, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion content/cn/template.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,21 @@
"org-link":"GitHub Org",
"irc-link":"IRC Chat",
"irc-logs-link":"Logs",
"gov-link":"项目管理"
"gov-link":"项目管理",
"verbose_version": "{{project.current_version}} 版本",
"downloads": {
"all": "其他"
},
"home": {
"download_links": "下载 {{> current_download_links}} 版本。",
"nightly_releases": "{{link '每日构建版本' 'https://iojs.org/download/nightly/'}} 可用于测试。",
"short_description": "{{link 'website'}} 是一个衍生自 {{link 'nodejs'}},并兼容 {{link 'npm'}} 的开发平台。",
"slogan": "将 {{link 'pages.es6'}} 带入 Node 社区!"
},
"links": {
"pages": {

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

"changelog": "更新日志",
"faq_verbose": "常见问题"
}
}
}
26 changes: 0 additions & 26 deletions content/en/index.md

This file was deleted.

21 changes: 21 additions & 0 deletions content/en/template.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,26 @@
"win64": "Win64",
"mac": "Mac",
"all": "Others"
},
"verbose_version": "Version {{project.current_version}}",
"home": {
"download_links": "Download for {{> current_download_links}}",
"faq_verbose": "{{link 'pages.faq_verbose'}}",
"nightly_releases": "{{link 'Nightly releases' 'https://iojs.org/download/nightly/'}} are available for testing.",
"short_description": "{{link 'website'}} is an {{link 'npm'}} compatible platform originally based on {{link 'nodejs'}}.",
"slogan": "Bringing {{link 'pages.es6'}} to the Node Community!",
"news_link": "{{link 'Weekly Update - March 6th' 'https://medium.com/node-js-javascript/io-js-week-of-march-6th-2f9344688277'}} <small>featuring core and community updates ({{link 'Medium' 'https://medium.com/node-js-javascript/io-js-week-of-march-6th-2f9344688277'}})</small>"
},
"links": {
"nodejs": "Node.js™",
"npm": "npm",
"website": "io.js",
"pages": {
"changelog": "Changelog",
"home": "Home",
"es6": "ES6",
"faq": "FAQ",
"faq_verbose": "Frequenty Asked Questions"
}
}
}
2 changes: 1 addition & 1 deletion gulp/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module.exports = {
},
templates: {
templateSrc: src + '/templates/**/*.html',
contentSrc: content + '/**/*.md',
contentSrc: content + '/**/*.{html,md}',
templateJSONsrc: content + '/**/template.json',
dest: dest
},
Expand Down
3 changes: 2 additions & 1 deletion gulp/tasks/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ var runSequence = require('run-sequence');

gulp.task('build', function(cb){
runSequence(
// 'clean',
'clean',
'content',
['stylus', 'templates'],
'minifyCss',
cb);
Expand Down
46 changes: 46 additions & 0 deletions gulp/tasks/content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
var path = require('path');
var gulp = require('gulp');
var clone = require('gulp-clone');
var buffer = require('vinyl-buffer');
var mergeStream = require('merge-stream');
var generateContentAndTemplates = require('../util/content').generateContentAndTemplates;
var through = require('through2');

gulp.task('content', function() {
var base, contentJSON, languagesJSON, matchHTML, templates, templateStreams;

base = path.resolve(__dirname, '..', '..');
contentJSON = require('../../source/content.js');
languagesJSON = require('../../source/languages.js');
matchHTML = /\.html$/;
templates = {};
templateStreams = mergeStream();

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.


Object.keys(contentJSON).filter(function(key) {
var article = contentJSON[key];
if (article.content && matchHTML.test(article.content)) {
var contentTemplate = `source/templates/${article.content}`;
if (templates[contentTemplate] == null) {
templates[contentTemplate] = gulp.src(contentTemplate, {base: 'source/templates'});
}
languagesJSON.forEach(function(lang) {
var newpath = path.resolve(base, 'content', lang.code, article.url);
var stream = templates[contentTemplate]
.pipe(clone())
.pipe(through.obj(function(file, _unused_, cb) {
file.base = 'content'
file.path = path.join(base, 'content', lang.code, article.url);
file._article = article;
this.push(file);
cb();
}));
templateStreams.add(stream);
});
}
});

return templateStreams
.pipe(buffer())
.pipe(through.obj(generateContentAndTemplates()))
.pipe(gulp.dest('public/'))
});
3 changes: 2 additions & 1 deletion gulp/tasks/develop.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ var runSequence = require('run-sequence');

gulp.task('develop', function(cb){
runSequence(
// 'clean',
'clean',
'content',
['stylus', 'templates'],
['watch', 'server'],
cb);
Expand Down
129 changes: 10 additions & 119 deletions gulp/tasks/templates.js
Original file line number Diff line number Diff line change
@@ -1,126 +1,17 @@
/*
* 1. because this is a gulp task. duh.
* 2. to convert markdown to html
* 3. handlebars is used to convert `{{ }}` placeholders
* in markdown, html, to output
* 4. we get an un-buffered stream we need 100% loaded in order
* 1. we get an un-buffered stream we need 100% loaded in order
* to properly process
* 5. the map function helps us "inject" our custom processing steps in to the
* 2. the through function helps us "inject" our custom processing steps in to the
* incoming file buffer
* 6. renames our files for output
* 7. brings in our own shared `utils`
* 3. renames our files for output
*/
var fs = require('fs');
var path = require('path');
var gulp = require('gulp'); /* 1 */
var md = require('markdown-it')({ html: true }); /* 2 */
var Handlebars = require('handlebars'); /* 3 */
var buffer = require('vinyl-buffer'); /* 4 */
var vinylMap = require('vinyl-map'); /* 5 */
var rename = require('gulp-rename'); /* 6 */
var utils = require('../util/template-utils.js'); /* 7 */
var gulp = require('gulp');


/*
generateContentAndTemplates()
=============
This function wraps some lookups and caching around otherwise repeated actions
within the run of the task returned.

In general, the purpose is to:
- take incoming Markdown files** and inject in dictionary variables
- render the post-processed Markdown in to HTML
- fetch the appropriate template (HTML)
- Inject in dictionary variables and feed the HTML **content** (from markdown)
in to the template.
- Return the final combined HTML through to the vinyl stream.

** later, we want to accept incoming HTML partials as well
(not all pages will be Markdown based)

Returns: a gulp-friendly pipe task (function)
*/
function generateContentAndTemplates() {
var base, projectJSON, i18nJSON, hbsTemplates;

/*
* cache variables and lookups used on subsequent runs of the pipe task:
*
* 1. `base` directory of project
* 2. `contentBase` is the root directory where the task is getting its content,
* this is helpful later for processing out which i18n we're looking at
* 3. `projectJSON` is global, re-used across all languages
* 4. `i18nJSON` caches the template JSON for each language (avoids duplicated work)
* 5. `hbsTemplates` caches the handlebars FUNCTION for each template to save overhead
*/
base = path.resolve(__dirname, '..', '..'); /* 1 */
contentBase = path.resolve(base, 'content'); /* 2 */
projectJSON = require('../../source/project.js'); /* 3 */
i18nJSON = {}; /* 4 */
hbsTemplates = {}; /* 5 */

// we returned a wrapped function to help us cache some work (above)
return function(contentBuffer, file) {
var fileName, contentRaw, lang, templateJSON, contentHandlebarsCompiled,
contentMarkdownCompiled, template, contentTemplateCompiled;

fileName = path.parse(file).name
contentRaw = contentBuffer.toString();

// determine the language based off of the current path
lang = path.relative(contentBase, path.dirname(file)).split(path.sep)[0];

if (i18nJSON[lang] == null) {
i18nJSON[lang] = utils.loadTemplateJSON(lang);
}

// load the current dictionary for the selected lang
templateJSON = {
i18n: i18nJSON[lang],
lang: lang,
build: {
markdownPage: fileName,
pageStylesheet: fileName
},
page: {
languages: projectJSON.languages.map(function(lang) {
return {
code: lang.code,
name: lang.name,
url: `/${lang.code}/${fileName}.html`
}
})
},
project: projectJSON
}

// initial Handlebars compile, Markdown content, before parsing
// (otherwise the `{{ }}` can be escaped)
contentHandlebarsCompiled = Handlebars.compile(contentRaw)(templateJSON);

// Turn `.md` in to `.html`
contentMarkdownCompiled = md.render(contentHandlebarsCompiled)

// this is hard-coded right now, but planned to be dynamic:
template = 'main.html';

// fetch the final template function we need (if not already cached)
if (hbsTemplates[template] == null) {
var templateBody = fs.readFileSync(path.join(base, 'source', 'templates', template), {encoding: 'utf8'});
hbsTemplates[template] = Handlebars.compile(templateBody);
}

// Adds the inner-content already processed to the templateJSON
// as the dictionaries may be re-used between both levels:
templateJSON.content = contentMarkdownCompiled;

// Compile a version of the template with the content inside:
contentTemplateCompiled = hbsTemplates[template](templateJSON)

// Return as a Buffer for additional processing:
return new Buffer(contentTemplateCompiled);
}
};
var buffer = require('vinyl-buffer'); /* 1 */
var through = require('through2'); /* 2 */
var rename = require('gulp-rename'); /* 3 */
var generateContentAndTemplates = require('../util/content').generateContentAndTemplates;

/*
* processMarkdown will take markdown files (from content) and apply any
Expand Down Expand Up @@ -151,13 +42,13 @@ var processMarkdown = function(eventOrStream, filePath) {

return stream
.pipe(buffer())
.pipe(vinylMap(generateContentAndTemplates()))
.pipe(through.obj(generateContentAndTemplates()))
.pipe(rename({extname: '.html'}))
.pipe(gulp.dest('public/'))
}

gulp.task('templates', function() {
var stream = gulp.src('content/**/*.md');
var stream = gulp.src('content/**/*.{md,html}');
return processMarkdown(stream);
});

Expand Down
Loading