diff --git a/content/cn/template.json b/content/cn/template.json index fb6368b..bf41a6d 100644 --- a/content/cn/template.json +++ b/content/cn/template.json @@ -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": { + "changelog": "更新日志", + "faq_verbose": "常见问题" + } + } } diff --git a/content/en/index.md b/content/en/index.md deleted file mode 100644 index f74319b..0000000 --- a/content/en/index.md +++ /dev/null @@ -1,26 +0,0 @@ -# JavaScript I/O - -Bringing [ES6](es6.html) to the Node Community! - -[io.js](https://github.com/iojs/io.js) is an [npm](https://www.npmjs.org/) compatible platform originally based on [node.js](https://nodejs.org/)™. - -[![io.js](../images/1.0.0.png)](https://iojs.org/dist/v{{project.current_version}}/) - -[Version {{project.current_version}}](https://iojs.org/dist/v{{project.current_version}}/) - -Download for -[Linux](https://iojs.org/dist/v{{project.current_version}}/iojs-v{{project.current_version}}-linux-x64.tar.xz), -[Win32](https://iojs.org/dist/v{{project.current_version}}/iojs-v{{project.current_version}}-x86.msi), -[Win64](https://iojs.org/dist/v{{project.current_version}}/iojs-v{{project.current_version}}-x64.msi), -[Mac](https://iojs.org/dist/v{{project.current_version}}/iojs-v{{project.current_version}}.pkg) or -[others](https://iojs.org/dist/v{{project.current_version}}/). - - -[Changelog](https://github.com/iojs/io.js/blob/v1.x/CHANGELOG.md) - -[Weekly Update - March 13th][1] featuring core and community updates ([Medium][1]) -

[Nightly releases](https://iojs.org/download/nightly/) are available for testing. - -[Frequently Asked Questions](faq.html) - -[1]: https://medium.com/node-js-javascript/io-js-week-of-march-13th-e3024cc66802 diff --git a/content/en/template.json b/content/en/template.json index 6d5e0dc..2070d1c 100644 --- a/content/en/template.json +++ b/content/en/template.json @@ -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 13th' 'https://medium.com/node-js-javascript/io-js-week-of-march-13th-e3024cc66802'}} featuring core and community updates ({{link 'Medium' 'https://medium.com/node-js-javascript/io-js-week-of-march-13th-e3024cc66802'}})" + }, + "links": { + "nodejs": "Node.js™", + "npm": "npm", + "website": "io.js", + "pages": { + "changelog": "Changelog", + "home": "Home", + "es6": "ES6", + "faq": "FAQ", + "faq_verbose": "Frequenty Asked Questions" + } } } diff --git a/gulp/config.js b/gulp/config.js index 77f4fc8..46dd9a0 100644 --- a/gulp/config.js +++ b/gulp/config.js @@ -12,7 +12,7 @@ module.exports = { }, templates: { templateSrc: src + '/templates/**/*.html', - contentSrc: content + '/**/*.md', + contentSrc: content + '/**/*.{html,md}', templateJSONsrc: content + '/**/template.json', dest: dest }, diff --git a/gulp/tasks/build.js b/gulp/tasks/build.js index 812304a..408aa02 100644 --- a/gulp/tasks/build.js +++ b/gulp/tasks/build.js @@ -3,7 +3,8 @@ var runSequence = require('run-sequence'); gulp.task('build', function(cb){ runSequence( - // 'clean', + 'clean', + 'content', ['stylus', 'templates'], 'minifyCss', cb); diff --git a/gulp/tasks/content.js b/gulp/tasks/content.js new file mode 100644 index 0000000..ce7de5b --- /dev/null +++ b/gulp/tasks/content.js @@ -0,0 +1,44 @@ +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 = path.resolve(__dirname, '..', '..'); + var contentJSON = require('../../source/content.js'); + var languagesJSON = require('../../source/languages.js'); + var matchHTML = /\.html$/; + var templates = {}; + var templateStreams = mergeStream(); + + 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/')) +}); diff --git a/gulp/tasks/develop.js b/gulp/tasks/develop.js index fa26dd3..2c4d407 100644 --- a/gulp/tasks/develop.js +++ b/gulp/tasks/develop.js @@ -3,7 +3,8 @@ var runSequence = require('run-sequence'); gulp.task('develop', function(cb){ runSequence( - // 'clean', + 'clean', + 'content', ['stylus', 'templates'], ['watch', 'server'], cb); diff --git a/gulp/tasks/templates.js b/gulp/tasks/templates.js index d2387e4..7ac987d 100644 --- a/gulp/tasks/templates.js +++ b/gulp/tasks/templates.js @@ -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 @@ -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); }); diff --git a/gulp/util/content.js b/gulp/util/content.js new file mode 100644 index 0000000..cf62c1d --- /dev/null +++ b/gulp/util/content.js @@ -0,0 +1,189 @@ +/* + * 2. to convert markdown to html + * 3. handlebars is used to convert `{{ }}` placeholders + * in markdown, html, to output + * 4. brings in our own shared `utils` + */ +var fs = require('fs'); +var path = require('path'); +var md = require('markdown-it')({ html: true }); /* 2 */ +var Handlebars = require('handlebars'); /* 3 */ +var utils = require('../util/template-utils.js'); /* 4 */ + +require('events').EventEmitter.prototype._maxListeners = 100; + +function traverse(obj, str) { + return str.split(".").reduce(function(o, x) { return o[x] }, obj); +} + +/* + 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() { + /* + * 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 + * 5. `LocalHandlebars` is a sandboxed version of Handlebars, avoids injecting + helpers and partials at a global scale. + */ + var base = path.resolve(__dirname, '..', '..'); /* 1 */ + var contentBase = path.resolve(base, 'content'); /* 2 */ + var projectJSON = require('../../source/project.js'); /* 3 */ + var i18nJSON = {}; /* 4 */ + var hbsTemplates = {}; /* 5 */ + var LocalHandlebars = Handlebars.create() /* 6 */ + + LocalHandlebars.registerPartial('current_download_links', `{{#project.current_version_downloads}}{{i18n "downloads" key}}{{/project.current_version_downloads}}`) + + LocalHandlebars.registerHelper('i18n', function() { + var env, key; + + // function(key, env) + if (arguments.length === 2) { + key = arguments[0]; + env = arguments[1]; + } + // function(scope, key, env) + if (arguments.length === 3) { + key = arguments[0] + '.' + arguments[1]; + env = arguments[2]; + } + + var data = env.data.root; + var result = traverse(data.i18n, key); + + return new Handlebars.SafeString(result); + }); + + LocalHandlebars.registerHelper('hb', function() { + var env, key; + + // function(key, env) + if (arguments.length === 2) { + key = arguments[0]; + env = arguments[1]; + } + // function(scope, key, env) + if (arguments.length === 3) { + key = arguments[0] + '.' + arguments[1]; + env = arguments[2]; + } + + var data = env.data.root; + var result = traverse(data.i18n, key); + + result = LocalHandlebars.compile(result)(env.data.root); + + return new Handlebars.SafeString(result); + }); + + LocalHandlebars.registerHelper('link', function(text, url, env) { + var key = text; + + if (arguments.length == 2) { + env = url; + text = traverse(env.data.root.i18n.links, key); + url = traverse(env.data.root.project.links, key); + } + text = Handlebars.Utils.escapeExpression(text); + url = Handlebars.Utils.escapeExpression(url); + + var result = '' + text + ''; + + return new Handlebars.SafeString(result); + }); + + // we returned a wrapped function to help us cache some work (above) + return function(vinylFile, _unused_, cb) { + var file = vinylFile.path; + var fileName = path.parse(file).name + var fileType = path.parse(file).ext === ".html" ? "html" : "markdown" + var contentRaw = vinylFile.contents.toString(); + + // determine the language based off of the current path + var 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 + var templateJSON = { + article: vinylFile._article, + 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) + var contentHandlebarsCompiled = LocalHandlebars.compile(contentRaw)(templateJSON); + + // When required, turn `.md` in to `.html` + if (fileType === "markdown") { + var contentMarkdownCompiled = md.render(contentHandlebarsCompiled); + } else { + var contentMarkdownCompiled = contentHandlebarsCompiled; + } + + // this is hard-coded right now, but planned to be dynamic: + var 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] = LocalHandlebars.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: + var contentTemplateCompiled = hbsTemplates[template](templateJSON) + + // Return as a Buffer for additional processing: + vinylFile.contents = new Buffer(contentTemplateCompiled); + this.push(vinylFile); + cb(); + } +}; + +module.exports = { + generateContentAndTemplates: generateContentAndTemplates +} diff --git a/package.json b/package.json index 3b1909c..21b417d 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,9 @@ "express": "^4.11.2", "gulp": "^3.8.10", "gulp-changed": "^1.1.0", + "gulp-clone": "^1.0.0", + "gulp-compile-handlebars": "^0.4.4", + "gulp-connect": "^2.2.0", "gulp-filesize": "0.0.6", "gulp-htmlmin": "^1.0.0", "gulp-imagemin": "^2.1.0", @@ -58,9 +61,11 @@ "handlebars": "^3.0.0", "lodash": "^2.4.1", "markdown-it": "^3.0.4", + "merge-stream": "^0.1.7", + "moment-timezone": "^0.3.0", "require-dir": "^0.1.0", "run-sequence": "^1.0.2", - "vinyl-buffer": "^1.0.0", - "vinyl-map": "^1.0.1" + "through2": "^0.6.3", + "vinyl-buffer": "^1.0.0" } } diff --git a/source/content.js b/source/content.js new file mode 100644 index 0000000..44bd5e8 --- /dev/null +++ b/source/content.js @@ -0,0 +1,13 @@ +module.exports = { + "home": { + "url": "index.html", + "content": "home.html", + "stylesheets": ["/home.css"] + }, + "es6": { + "url": "es6.html" + }, + "faq": { + "url": "faq.html" + } +} diff --git a/source/languages.js b/source/languages.js new file mode 100644 index 0000000..a845ead --- /dev/null +++ b/source/languages.js @@ -0,0 +1,22 @@ +module.exports = [ + {"code": "cn", "name": "简体中文", "name-en": "Chinese (Simple)"}, + {"code": "de", "name": "Deutsch", "name-en": "German"}, + {"code": "el", "name": "Ελληνικά", "name-en": "Greek"}, + {"code": "en", "name": "English", "name-en": "English"}, + {"code": "es", "name": "Español", "name-en": "Spanish"}, + {"code": "fa", "name": "فارسی", "name-en": "Persian", "rtl": true}, + {"code": "fi", "name": "Suomi", "name-en": "Finnish"}, + {"code": "fr", "name": "Français", "name-en": "French"}, + {"code": "he", "name": "עברית", "name-en": "Hebrew", "rtl": true}, + {"code": "id", "name": "Bahasa Indonesia", "name-en": "Indonesian"}, + {"code": "it", "name": "Italiano", "name-en": "Italian"}, + {"code": "ja", "name": "日本語", "name-en": "Japanese"}, + {"code": "ko", "name": "한국어", "name-en": "Korean"}, + {"code": "no", "name": "Norsk", "name-en": "Norwegian"}, + {"code": "pt_BR", "name": "Português (BR)", "name-en": "Portuguese (Brazil)"}, + {"code": "pt_PT", "name": "Português (PT)", "name-en": "Portuguese (Portugal)"}, + {"code": "ru", "name": "Русский", "name-en": "Russian"}, + {"code": "tr", "name": "Türkçe", "name-en": "Turkish"}, + {"code": "uk", "name": "Українська", "name-en": "Ukrainian"}, + {"code": "zh_TW", "name": "正體中文(台灣)", "name-en": "Chinese Traditional (Taiwan)"} +] diff --git a/source/project.js b/source/project.js index d1ac026..01d33ce 100644 --- a/source/project.js +++ b/source/project.js @@ -1,37 +1,20 @@ // temporary merge to help avoid some merge confusion when landed: var project = require('./project.json'); -/* +project.languages = require('./languages.js'); -// This will replace `./project.json` - -project = { - "current_version": "1.4.3", - "current_v8": "4.1.0.21" -} - -project.languages = [ - {"code": "cn", "name": "简体中文", "name-en": "Chinese (Simple)"}, - {"code": "de", "name": "Deutsch", "name-en": "German"}, - {"code": "el", "name": "Ελληνικά", "name-en": "Greek"}, - {"code": "en", "name": "English", "name-en": "English"}, - {"code": "es", "name": "Español", "name-en": "Spanish"}, - {"code": "fi", "name": "Suomi", "name-en": "Finnish"}, - {"code": "fr", "name": "Français", "name-en": "French"}, - {"code": "he", "name": "עברית", "name-en": "Hebrew", "rtl": true}, - {"code": "id", "name": "Bahasa Indonesia", "name-en": "Indonesian"}, - {"code": "it", "name": "Italiano", "name-en": "Italian"}, - {"code": "ja", "name": "日本語", "name-en": "Japanese"}, - {"code": "ko", "name": "한국어", "name-en": "Korean"}, - {"code": "no", "name": "Norsk", "name-en": "Norwegian"}, - {"code": "pt_BR", "name": "Português (BR)", "name-en": "Portuguese (Brazil)"}, - {"code": "pt_PT", "name": "Português (PT)", "name-en": "Portuguese (Portugal)"}, - {"code": "ru", "name": "Русский", "name-en": "Russian"}, - {"code": "tr", "name": "Türkçe", "name-en": "Turkish"}, - {"code": "uk", "name": "Українська", "name-en": "Ukrainian"}, - {"code": "zh_TW", "name": "正體中文(台灣)", "name-en": "Chinese Traditional (Taiwan)"} -] -*/ +project.links = { + nodejs: 'https://nodejs.org/', + npm: 'https://www.npmjs.org/', + website: 'https://iojs.org/', + pages: { + changelog: 'https://github.com/iojs/io.js/blob/v1.x/CHANGELOG.md', + home: './index.html', + es6: './es6.html', + faq: './faq.html', + faq_verbose: './faq.html' + } +}; var baseURL = `https://iojs.org/dist`; project.current_version_downloads = [ diff --git a/source/project.json b/source/project.json index f282d56..1d1d9ab 100644 --- a/source/project.json +++ b/source/project.json @@ -1,26 +1,4 @@ { "current_version": "1.5.1", - "current_v8": "4.1.0.21", - "languages": [ - {"code": "cn", "name": "简体中文", "name-en": "Chinese (Simple)"}, - {"code": "de", "name": "Deutsch", "name-en": "German"}, - {"code": "el", "name": "Ελληνικά", "name-en": "Greek"}, - {"code": "en", "name": "English", "name-en": "English"}, - {"code": "es", "name": "Español", "name-en": "Spanish"}, - {"code": "fa", "name": "فارسی", "name-en": "Persian", "rtl": true}, - {"code": "fi", "name": "Suomi", "name-en": "Finnish"}, - {"code": "fr", "name": "Français", "name-en": "French"}, - {"code": "he", "name": "עברית", "name-en": "Hebrew", "rtl": true}, - {"code": "id", "name": "Bahasa Indonesia", "name-en": "Indonesian"}, - {"code": "it", "name": "Italiano", "name-en": "Italian"}, - {"code": "ja", "name": "日本語", "name-en": "Japanese"}, - {"code": "ko", "name": "한국어", "name-en": "Korean"}, - {"code": "no", "name": "Norsk", "name-en": "Norwegian"}, - {"code": "pt_BR", "name": "Português (BR)", "name-en": "Portuguese (Brazil)"}, - {"code": "pt_PT", "name": "Português (PT)", "name-en": "Portuguese (Portugal)"}, - {"code": "ru", "name": "Русский", "name-en": "Russian"}, - {"code": "tr", "name": "Türkçe", "name-en": "Turkish"}, - {"code": "uk", "name": "Українська", "name-en": "Ukrainian"}, - {"code": "zh_TW", "name": "正體中文(台灣)", "name-en": "Chinese Traditional (Taiwan)"} - ] + "current_v8": "4.1.0.21" } diff --git a/source/styles/home.styl b/source/styles/home.styl new file mode 100644 index 0000000..7a91963 --- /dev/null +++ b/source/styles/home.styl @@ -0,0 +1,57 @@ +.home-slogan + text-align center + +.home-description + text-align center + margin-bottom 40px + +.home-download + background #eee + display flex + justify-content space-between + align-items center + + a + text-decoration none + +.home-logo + padding 20px 40px 20px 20px + img + height 120px + +.home-download-details + flex 1 + p + margin 0 + padding 0 + + .home-download-version + display block + font-size 1.4rem + font-weight 700 + color black + border-radius 0 4px 0 0 + margin-bottom 20px + + .home-download-list + color rgba(0, 0, 0, 0.5) + font-size 0.9rem + padding-top 0 + padding-bottom 0 + height 28px + max-height 28px + + a:after + content ', ' + + a:nth-last-child(2):after + content ' & ' + color rgba(0, 0, 0, 0.5) + + a:last-child:after + content '' + +.home-secondary-links + margin-top 40px + p + text-align center diff --git a/source/templates/home.html b/source/templates/home.html new file mode 100644 index 0000000..95f06b5 --- /dev/null +++ b/source/templates/home.html @@ -0,0 +1,33 @@ +

JavaScript I/O

+ +

+ {{hb 'home.slogan'}} +

+ +

+ {{hb 'home.short_description'}} +

+ +
+ +
+

+ {{hb 'verbose_version'}} +

+

+ {{hb 'home.download_links'}} +

+

{{link 'pages.changelog'}}

+
+
+ +{{#if i18n.home.news_link}} + +{{/if}} + + diff --git a/source/templates/main.html b/source/templates/main.html index 5a4a218..066e511 100644 --- a/source/templates/main.html +++ b/source/templates/main.html @@ -11,7 +11,13 @@ + {{#if article.stylesheets}} + {{#article.stylesheets}} + + {{/article.stylesheets}} + {{else}} + {{/if}}