mkdocs-material/Gulpfile.babel.js

499 lines
13 KiB
JavaScript
Raw Normal View History

/*
2017-01-06 21:11:18 +03:00
* Copyright (c) 2016-2017 Martin Donath <martin.donath@squidfunk.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
2017-02-26 21:37:16 +03:00
import chalk from "chalk"
import gulp from "gulp"
import notifier from "node-notifier"
import plumber from "gulp-plumber"
import util from "gulp-util"
import yargs from "yargs"
/* ----------------------------------------------------------------------------
* Configuration and arguments
* ------------------------------------------------------------------------- */
2017-02-26 21:37:16 +03:00
/* General configuration */
const config = {
assets: {
src: "src/assets", /* Source directory for assets */
build: "material/assets" /* Target directory for assets */
},
lib: "lib", /* Libraries and tasks */
tests: {
visual: "tests/visual" /* Base directory for visual tests */
},
views: {
src: "src", /* Source directory for views */
build: "material" /* Target directory for views */
}
}
2017-02-26 21:37:16 +03:00
/* Commandline arguments */
2017-02-02 02:40:36 +03:00
let args = yargs
2017-02-26 21:37:16 +03:00
.locale("en")
.usage(`\n${chalk.yellow("Usage:")} yarn run <command> -- [options]`)
.wrap(84)
.updateStrings({
"Commands:": chalk.yellow("Commands:"),
"Examples:": chalk.yellow("Examples:")
})
/* Commands */
.command("build", chalk.grey("build assets and views"))
.command("clean", chalk.grey("clean build artifacts"))
.command("flow", chalk.grey("type check with flow"))
.command("help", chalk.grey("display this message"))
.command("lint", chalk.grey("lint sources"))
.command("start", chalk.grey("start development server"))
.command("test:visual:run", chalk.grey("run visual tests"))
.command("test:visual:session", chalk.grey("start test server"))
.command("test:visual:update", chalk.grey("update reference images"))
/* Options */
.group([
"help", "clean"
], chalk.yellow("Options:"))
.help("help", chalk.grey("display this message"))
.option("clean", {
describe: chalk.grey("clean artifacts before command"),
default: false,
global: true
})
/* Build options */
.group([
"lint", "optimize", "revision", "sourcemaps", "mkdocs"
], chalk.yellow("Build Options:"))
.option("lint", {
describe: chalk.grey("lint sources before build"),
default: true,
global: true
})
.option("optimize", {
describe: chalk.grey("optimize and minify assets"),
2017-03-12 19:58:34 +03:00
default: false,
2017-02-26 21:37:16 +03:00
global: true
})
.option("revision", {
describe: chalk.grey("revision assets for cache busting"),
default: false,
global: true
})
.option("sourcemaps", {
describe: chalk.grey("generate sourcemaps for assets"),
default: false,
global: true
})
.option("mkdocs", {
describe: chalk.grey("build documentation or start watchdog"),
default: true,
global: true
})
/* Test options */
.group([
"grep", "browser"
], chalk.yellow("Test Options:"))
.option("grep", {
describe: chalk.grey("only execute tests matching a regex"),
global: true
})
.option("browser", {
describe: chalk.grey("only execute tests for the given browser"),
global: true
})
/* Example commands */
.example("yarn run build")
.example("yarn run build -- --no-optimize")
.example("yarn run clean")
.example("yarn run flow")
.example("yarn run lint")
.example("yarn run start")
.example("yarn run test:visual:run")
.example("yarn run test:visual:run -- --no-clean")
.example("yarn run test:visual:run -- --grep nav")
.example("yarn run test:visual:run -- --browser ie11")
.example("yarn run test:visual:session")
.example("yarn run test:visual:update")
/* Document Environment variables */
.epilogue(
`${chalk.yellow("Environment:")}\n` +
` SAUCE=${chalk.grey("<true|false)>")}\n` +
` SAUCE_USERNAME=${chalk.grey("<username>")}\n` +
` SAUCE_ACCESS_KEY=${chalk.grey("<key>")}`
)
/* Apply to process.argv */
.argv
/* Only use the last seen value if boolean, so overrides are possible */
2017-02-02 02:40:36 +03:00
args = Object.keys(args).reduce((result, arg) => {
2017-02-25 19:25:47 +03:00
result[arg] = Array.isArray(args[arg]) && typeof args[arg][0] === "boolean"
? [].concat(args[arg]).pop()
: args[arg]
2017-02-02 02:40:36 +03:00
return result
}, {})
/* ----------------------------------------------------------------------------
* Overrides and helpers
* ------------------------------------------------------------------------- */
/*
* Override gulp.src() for nicer error handling.
*/
const src = gulp.src
2016-10-31 11:58:43 +03:00
gulp.src = (...glob) => {
return src.apply(gulp, glob)
.pipe(
plumber(function(error) {
util.log(util.colors.red(
`Error (${error.plugin}): ${error.message}`
))
/* Extract file where error happened, if existent */
const file = error.relativePath
? error.relativePath.split("/").pop()
: ""
/* Dispatch system-level notification */
notifier.notify({
title: `Error (${error.plugin}): ${file}`,
message: error.messageOriginal
})
// eslint-disable-next-line no-invalid-this
this.emit("end")
/* Throw error and abort, if not in watch mode */
if (args._[0] !== "watch")
throw error
}))
2016-10-31 11:58:43 +03:00
}
/*
* Helper function to load a task
2017-01-28 00:40:09 +03:00
*
* This function returns a callback that will require the task with the given
* name and execute the function that is returned by this task. It omits the
* need to load all tasks upfront, speeding up the build a gazillion times.
*/
2016-10-31 11:58:43 +03:00
const load = task => {
2017-01-28 00:40:09 +03:00
return done => {
return require(`./${config.lib}/tasks/${task}`)
.call(gulp, gulp, config, args)(done)
}
2016-10-31 11:58:43 +03:00
}
/* ----------------------------------------------------------------------------
* Images
* ------------------------------------------------------------------------- */
/*
* Copy favicon
*/
2017-01-28 00:40:09 +03:00
gulp.task("assets:images:build:ico", [
args.clean ? "assets:images:clean" : false
2017-01-28 00:40:09 +03:00
].filter(t => t),
load("assets/images/build/ico"))
/*
* Copy and minify vector graphics
*/
2017-01-28 00:40:09 +03:00
gulp.task("assets:images:build:svg", [
args.clean ? "assets:images:clean" : false
2017-01-28 00:40:09 +03:00
].filter(t => t),
load("assets/images/build/svg"))
/*
* Copy images
*/
2017-01-28 00:40:09 +03:00
gulp.task("assets:images:build", [
"assets:images:build:ico",
"assets:images:build:svg"
])
/*
* Clean images generated by build
*/
gulp.task("assets:images:clean",
load("assets/images/clean"))
/* ----------------------------------------------------------------------------
2016-12-15 17:55:40 +03:00
* JavaScript
* ------------------------------------------------------------------------- */
/*
* Build application logic
*
2017-02-26 13:55:47 +03:00
* When revisioning assets, the build must be serialized due to possible race
* conditions when two tasks try to write manifest.json simultaneously
*/
2017-01-28 00:40:09 +03:00
gulp.task("assets:javascripts:build:application", [
args.clean ? "assets:javascripts:clean" : false,
2017-02-26 13:55:47 +03:00
args.lint ? "assets:javascripts:lint" : false,
args.revision ? "assets:stylesheets:build" : false
2017-01-28 00:40:09 +03:00
].filter(t => t),
load("assets/javascripts/build/application"))
/*
* Build custom modernizr
*
2017-02-26 13:55:47 +03:00
* When revisioning assets, the build must be serialized due to possible race
* conditions when two tasks try to write manifest.json simultaneously
*/
gulp.task("assets:javascripts:build:modernizr", [
2017-01-28 00:40:09 +03:00
"assets:stylesheets:build",
args.clean ? "assets:javascripts:clean" : false,
2017-02-26 13:55:47 +03:00
args.lint ? "assets:javascripts:lint" : false,
args.revision ? "assets:javascripts:build:application" : false
2017-01-28 00:40:09 +03:00
].filter(t => t),
load("assets/javascripts/build/modernizr"))
/*
2017-02-21 01:26:51 +03:00
* Build application logic and Modernizr
*/
2017-01-28 00:40:09 +03:00
gulp.task("assets:javascripts:build", [
"assets:javascripts:build:application",
"assets:javascripts:build:modernizr"
])
/*
2016-12-15 17:55:40 +03:00
* Clean JavaScript generated by build
*/
gulp.task("assets:javascripts:clean",
load("assets/javascripts/clean"))
2017-02-21 01:26:51 +03:00
/*
* Annotate JavaScript
*/
gulp.task("assets:javascripts:annotate",
load("assets/javascripts/annotate"))
/*
2016-12-15 17:55:40 +03:00
* Lint JavaScript
*/
gulp.task("assets:javascripts:lint",
load("assets/javascripts/lint"))
/* ----------------------------------------------------------------------------
* Stylesheets
* ------------------------------------------------------------------------- */
/*
* Build stylesheets from SASS source
*/
2017-01-28 00:40:09 +03:00
gulp.task("assets:stylesheets:build", [
args.clean ? "assets:stylesheets:clean" : false,
args.lint ? "assets:stylesheets:lint" : false
2017-01-28 00:40:09 +03:00
].filter(t => t),
load("assets/stylesheets/build"))
/*
* Clean stylesheets generated by build
*/
gulp.task("assets:stylesheets:clean",
load("assets/stylesheets/clean"))
/*
* Lint SASS sources
*/
gulp.task("assets:stylesheets:lint",
load("assets/stylesheets/lint"))
/* ----------------------------------------------------------------------------
* Assets
* ------------------------------------------------------------------------- */
/*
* Build assets
*/
gulp.task("assets:build", [
"assets:images:build",
"assets:javascripts:build",
"assets:stylesheets:build"
])
/*
* Clean files generated by build
*/
gulp.task("assets:clean", [
"assets:images:clean",
"assets:javascripts:clean",
"assets:stylesheets:clean"
])
/* ----------------------------------------------------------------------------
* Views
* ------------------------------------------------------------------------- */
/*
* Minify views
*/
2017-01-28 00:40:09 +03:00
gulp.task("views:build", [
2017-02-26 13:55:47 +03:00
args.clean ? "views:clean" : false,
args.revision ? "assets:images:build" : false,
args.revision ? "assets:stylesheets:build" : false,
2017-02-26 13:55:47 +03:00
args.revision ? "assets:javascripts:build" : false
2017-01-28 00:40:09 +03:00
].filter(t => t),
load("views/build"))
/*
* Clean views
*/
gulp.task("views:clean",
load("views/clean"))
/* ----------------------------------------------------------------------------
* MkDocs
* ------------------------------------------------------------------------- */
/*
* Build documentation
*/
gulp.task("mkdocs:build", [
"assets:build",
"views:build",
"mkdocs:clean"
2017-02-26 13:55:47 +03:00
], load("mkdocs/build"))
/*
* Clean documentation build
*/
gulp.task("mkdocs:clean",
load("mkdocs/clean"))
/*
* Restart MkDocs server
*/
gulp.task("mkdocs:serve",
load("mkdocs/serve"))
2016-10-07 17:38:13 +03:00
/* ----------------------------------------------------------------------------
* Visual tests
2016-10-07 17:38:13 +03:00
* ------------------------------------------------------------------------- */
/*
* Generate visual tests
*/
2017-02-02 02:40:36 +03:00
gulp.task("tests:visual:generate", [
args.clean ? "tests:visual:clean" : false,
args.clean ? "assets:build" : false,
args.clean ? "views:build" : false
].filter(t => t),
load("tests/visual/generate"))
/*
* Run visual tests
*/
gulp.task("tests:visual:run", [
"tests:visual:generate"
], load("tests/visual/run"))
2016-10-07 17:38:13 +03:00
/*
* Update reference images for visual tests
*/
gulp.task("tests:visual:update",
load("tests/visual/update"))
/*
* Clean files generated by visual tests
2016-10-07 17:38:13 +03:00
*/
gulp.task("tests:visual:clean",
load("tests/visual/clean"))
2016-10-07 17:38:13 +03:00
/*
* Open a SauceConnect session for manual testing
2016-10-07 17:38:13 +03:00
*/
2017-02-10 18:01:38 +03:00
gulp.task("tests:visual:session", [
"tests:visual:generate"
], load("tests/visual/session"))
2016-10-07 17:38:13 +03:00
/* ----------------------------------------------------------------------------
* Interface
* ------------------------------------------------------------------------- */
/*
* Build assets and documentation
*/
gulp.task("build", [
"assets:build",
2017-01-28 00:40:09 +03:00
"views:build",
args.mkdocs ? "mkdocs:build" : false
2017-01-28 00:40:09 +03:00
].filter(f => f))
/*
* Clean assets and documentation
*/
gulp.task("clean", [
"assets:clean",
"views:clean",
"mkdocs:clean"
])
/*
* Watch for changes and rebuild assets on the fly
*/
gulp.task("watch", [
"assets:build",
"views:build"
], () => {
process.env.WATCH = true
2016-10-07 17:38:13 +03:00
/* Start MkDocs server */
if (args.mkdocs)
gulp.start("mkdocs:serve")
/* Rebuild stylesheets */
gulp.watch([
`${config.assets.src}/stylesheets/**/*.scss`
], ["assets:stylesheets:build"])
2016-12-15 17:55:40 +03:00
/* Rebuild JavaScript */
gulp.watch([
`${config.assets.src}/javascripts/**/*.{js,jsx}`
], ["assets:javascripts:build:application"])
/* Copy images */
gulp.watch([
`${config.assets.src}/images/**/*`
], ["assets:images:build"])
/* Minify views */
gulp.watch([
`${config.views.src}/**/*.html`
], ["views:build"])
})
2017-02-26 21:37:16 +03:00
/*
* Print help message
*/
gulp.task("help")
/*
* Build assets by default
*/
gulp.task("default", ["build"])