Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

document build.js #396

Merged
2 commits merged into from
Dec 1, 2015
Merged
Changes from all commits
Commits
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
54 changes: 46 additions & 8 deletions build.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#!/usr/bin/env node
#! /usr/bin/env node

'use strict'

// BUILD.JS: This file is responsible for building static HTML pages and a
// server for local development.

const Metalsmith = require('metalsmith')
const autoprefixer = require('autoprefixer-stylus')
const collections = require('metalsmith-collections')
Expand All @@ -23,20 +26,23 @@ const loadVersions = require('./scripts/load-versions')
const latestVersion = require('./scripts/helpers/latestversion')
const eventGeo = require('./scripts/event-geo.js')

/** Build **/

// load template.json for given language, but use default language as fallback
// for properties which are not present in the given language
// Set the default language, also functions as a fallback for properties which
// are not defined in the given language.
const DEFAULT_LANG = 'en'

// Set up the Markdown renderer that we'll use for our Metalsmith build process,
// with the necessary adjustments that we need to make in order to have Prism
// work.
const renderer = new marked.Renderer()
renderer.heading = anchorMarkdownHeadings

const markedOptions = {
langPrefix: 'language-',
renderer: renderer
}

// This function imports a given language file and uses the default language set
// in DEFAULT_LANG as a fallback to prevent any strings that aren't filled out
// from appearing as blank.
function i18nJSON (lang) {
var defaultJSON = require(`./locale/${DEFAULT_LANG}/site.json`)
var templateJSON = require(`./locale/${lang}/site.json`)
Expand All @@ -55,17 +61,24 @@ function i18nJSON (lang) {
return finalJSON
}

// This is the function where the actual magic happens. This contains the main
// Metalsmith build cycle used for building a locale subsite, such as the
// english one.
function buildlocale (source, locale) {
console.time('[metalsmith] build/' + locale + ' finished')
const siteJSON = path.join(__dirname, 'locale', locale, 'site.json')
const metalsmith = Metalsmith(__dirname)
metalsmith
// Sets global metadata imported from the locale's respective site.json.
.metadata({
site: require(siteJSON),
project: source.project,
i18n: i18nJSON(locale)
})
// Sets the build source as the locale folder.
.source(path.join(__dirname, 'locale', locale))
// Defines the blog post/guide collections used to internally group them for
// easier future handling and feed generation.
.use(collections({
blog: {
pattern: 'blog/**/*.md',
Expand Down Expand Up @@ -115,15 +128,20 @@ function buildlocale (source, locale) {
}))
.use(markdown(markedOptions))
.use(prism())
// Deletes Stylus partials since they'll be included in the main CSS file
// anyways.
.use(filterStylusPartials())
.use(stylus({
compress: true,
paths: [path.join(__dirname, 'layouts', 'css')],
use: [autoprefixer()]
}))
// Set pretty permalinks, we don't want .html suffixes everywhere.
.use(permalinks({
relative: false
}))
// Generates the feed XML files from their respective collections which were
// defined earlier on.
.use(feed({
collection: 'blog',
destination: 'feed/blog.xml',
Expand All @@ -149,6 +167,9 @@ function buildlocale (source, locale) {
destination: 'feed/tsc-minutes.xml',
title: 'Node.js Technical Steering Committee meetings'
}))
// Finally, this compiles the rest of the layouts present in ./layouts.
// They're language-agnostic, but have to be regenerated for every locale
// anyways.
.use(layouts({
engine: 'handlebars',
pattern: '**/*.html',
Expand All @@ -162,14 +183,20 @@ function buildlocale (source, locale) {
apidocslink: require('./scripts/helpers/apidocslink.js')
}
}))
// Pipes the generated files into their respective subdirectory in the build
// directory.
.destination(path.join(__dirname, 'build', locale))

// This actually executes the build and stops the internal timer after
// completion.
metalsmith.build(function (err) {
if (err) { throw err }
console.timeEnd('[metalsmith] build/' + locale + ' finished')
})
}

// This function copies the rest of the static assets to their subfolder in the
// build directory.
function copystatic () {
console.time('[metalsmith] build/static finished')
fs.mkdir(path.join(__dirname, 'build'), function () {
Expand All @@ -183,8 +210,12 @@ function copystatic () {
})
}

// This is where the build is orchestrated from, as indicated by the function
// name. It brings together all build steps and dependencies and executes them.
function fullbuild () {
// Copies static files.
copystatic()
// Loads all node/io.js versions.
loadVersions(function (err, versions) {
if (err) { throw err }
const source = {
Expand All @@ -202,6 +233,7 @@ function fullbuild () {
}
}

// Executes the build cycle for every locale.
fs.readdir(path.join(__dirname, 'locale'), function (e, locales) {
locales.filter(junk.not).forEach(function (locale) {
buildlocale(source, locale)
Expand All @@ -210,8 +242,10 @@ function fullbuild () {
})
}

// The server function, where the site is exposed through a static file server
// locally.
function server () {
/** Static file server **/
// Initializes the server and mounts it in the generated build directory.
const st = require('st')
const http = require('http')
const mount = st({
Expand All @@ -225,7 +259,8 @@ function server () {
function () { console.log('http://localhost:8080/en/') }
)

/** File Watches for Re-Builds **/
// Watches for file changes in the locale, layout and static directories, and
// rebuilds the modified one.
const chokidar = require('chokidar')
const opts = {
persistent: true,
Expand All @@ -242,6 +277,7 @@ function server () {
const layouts = chokidar.watch(path.join(__dirname, 'layouts'), opts)
const staticf = chokidar.watch(path.join(__dirname, 'static'), opts)

// Gets the locale name by path.
function getlocale (p) {
const pre = path.join(__dirname, 'locale')
return p.slice(pre.length + 1, p.indexOf('/', pre.length + 1))
Expand All @@ -261,8 +297,10 @@ function server () {
staticf.on('add', function (p) { staticf.add(p); copystatic() })
}

// Starts the build.
fullbuild()

// If the command-line option was provided, starts the static server.
if (process.argv[2] === 'serve') {
server()
}