Skip to content

Instantly share code, notes, and snippets.

@bradfrost
Created December 4, 2018 15:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bradfrost/401712e220bb853a0e7d6fa841457542 to your computer and use it in GitHub Desktop.
Save bradfrost/401712e220bb853a0e7d6fa841457542 to your computer and use it in GitHub Desktop.
Sample Gulpfile for Pattern Lab Node
/******************************************************
* PATTERN LAB NODE
* EDITION-NODE-GULP
* The gulp wrapper around patternlab-node core, providing tasks to interact with the core library and move supporting frontend assets.
******************************************************/
var gulp = require('gulp'),
path = require('path'),
browserSync = require('browser-sync').create(),
sass = require('gulp-sass'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
svgSprite = require('gulp-svg-sprites'),
argv = require('minimist')(process.argv.slice(2)),
chalk = require('chalk'),
autoprefixer = require('gulp-autoprefixer'),
cleanCSS = require('gulp-clean-css');
/**
* Normalize all paths to be plain, paths with no leading './',
* relative to the process root, and with backslashes converted to
* forward slashes. Should work regardless of how the path was
* written. Accepts any number of parameters, and passes them along to
* path.resolve().
*
* This is intended to avoid all known limitations of gulp.watch().
*
* @param {...string} pathFragment - A directory, filename, or glob.
*/
function normalizePath() {
return path
.relative(
process.cwd(),
path.resolve.apply(this, arguments)
)
.replace(/\\/g, "/");
}
// Not all tasks need to use streams
// A gulpfile is just another node program and you can use any package available on npm
gulp.task('clean', function() {
// You can use multiple globbing patterns as you would with `gulp.src`
return del(['build']);
});
/******************************************************
* SASS
******************************************************/
gulp.task('pl-sass', function(){
return gulp.src(path.resolve(paths().source.css, '**/*.scss'))
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest(path.resolve(paths().source.css)));
});
/******************************************************
* AUTOPREFIXER
******************************************************/
gulp.task('prefix', () =>
gulp.src('./public/css/style.css')
.pipe(autoprefixer({
browsers: ['last 2 versions'],
cascade: false,
grid: true
}))
.pipe(gulp.dest('./public/css/'))
);
/******************************************************
* SVG SPRITE
******************************************************/
gulp.task('svg-sprite', function () {
return gulp.src('source/icons/*.svg')
.pipe(svgSprite({
mode: 'defs',
preview: false,
svg: {
defs: 'icons.svg'
}
}))
.pipe(gulp.dest('public'));
});
/******************************************************
* CONCATENATE AND MINIFY
******************************************************/
gulp.task('concat-and-minify', function(done) {
// main app js file
gulp.src('./source/js/*.js')
.pipe(uglify())
.pipe(concat("production.min.js"))
.pipe(gulp.dest('./public/js/'));
done();
});
/******************************************************
* MINIFY CSS
******************************************************/
gulp.task('minify-css', function() {
return gulp.src('./public/css/style.css')
.pipe(cleanCSS({compatibility: 'ie8'}))
.pipe(gulp.dest('./public/css/'));
});
/******************************************************
* COPY TASKS - stream assets from source to destination
******************************************************/
// JS copy
gulp.task('pl-copy:js', function () {
return gulp.src('**/*.js', {cwd: normalizePath(paths().source.js)} )
.pipe(gulp.dest(normalizePath(paths().public.js)));
});
// Images copy
gulp.task('pl-copy:img', function () {
return gulp.src('**/*.*',{cwd: normalizePath(paths().source.images)} )
.pipe(gulp.dest(normalizePath(paths().public.images)));
});
// Favicon copy
gulp.task('pl-copy:favicon', function () {
return gulp.src('favicon.ico', {cwd: normalizePath(paths().source.root)} )
.pipe(gulp.dest(normalizePath(paths().public.root)));
});
// Fonts copy
gulp.task('pl-copy:font', function () {
return gulp.src('*', {cwd: normalizePath(paths().source.fonts)})
.pipe(gulp.dest(normalizePath(paths().public.fonts)));
});
// CSS Copy
gulp.task('pl-copy:css', function () {
return gulp.src(normalizePath(paths().source.css) + '/*.css')
.pipe(gulp.dest(normalizePath(paths().public.css)))
.pipe(browserSync.stream());
});
// Styleguide Copy everything but css
gulp.task('pl-copy:styleguide', function () {
return gulp.src(normalizePath(paths().source.styleguide) + '/**/!(*.css)')
.pipe(gulp.dest(normalizePath(paths().public.root)))
.pipe(browserSync.stream());
});
// Styleguide Copy and flatten css
gulp.task('pl-copy:styleguide-css', function () {
return gulp.src(normalizePath(paths().source.styleguide) + '/**/*.css')
.pipe(gulp.dest(function (file) {
//flatten anything inside the styleguide into a single output dir per http://stackoverflow.com/a/34317320/1790362
file.path = path.join(file.base, path.basename(file.path));
return normalizePath(path.join(paths().public.styleguide, '/css'));
}))
.pipe(browserSync.stream());
});
/******************************************************
* PATTERN LAB CONFIGURATION - API with core library
******************************************************/
//read all paths from our namespaced config file
var config = require('./patternlab-config.json'),
patternlab = require('patternlab-node')(config);
function paths() {
return config.paths;
}
function getConfiguredCleanOption() {
return config.cleanPublic;
}
/**
* Performs the actual build step. Accomodates both async and sync
* versions of Pattern Lab.
* @param {function} done - Gulp done callback
*/
function build(done) {
const buildResult = patternlab.build(() => {}, getConfiguredCleanOption());
// handle async version of Pattern Lab
if (buildResult instanceof Promise) {
return buildResult.then(done);
}
// handle sync version of Pattern Lab
done();
return null;
}
gulp.task('pl-assets', gulp.series(
'pl-copy:img',
'pl-copy:favicon',
'svg-sprite',
'pl-copy:font',
gulp.series('pl-sass', 'pl-copy:css', 'prefix', function(done){done();}), //CSS tasks
'pl-copy:styleguide',
'pl-copy:styleguide-css',
'concat-and-minify'
));
gulp.task('patternlab:version', function (done) {
patternlab.version();
done();
});
gulp.task('patternlab:help', function (done) {
patternlab.help();
done();
});
gulp.task('patternlab:patternsonly', function (done) {
patternlab.patternsonly(done, getConfiguredCleanOption());
});
gulp.task('patternlab:liststarterkits', function (done) {
patternlab.liststarterkits();
done();
});
gulp.task('patternlab:loadstarterkit', function (done) {
patternlab.loadstarterkit(argv.kit, argv.clean);
done();
});
gulp.task('patternlab:build', gulp.series('pl-assets', 'svg-sprite', build));
gulp.task('patternlab:installplugin', function (done) {
patternlab.installplugin(argv.plugin);
done();
});
/******************************************************
* SERVER AND WATCH TASKS
******************************************************/
// watch task utility functions
function getSupportedTemplateExtensions() {
var engines = require('./node_modules/patternlab-node/core/lib/pattern_engines');
return engines.getSupportedFileExtensions();
}
function getTemplateWatches() {
return getSupportedTemplateExtensions().map(function (dotExtension) {
return normalizePath(paths().source.patterns, '**', '*' + dotExtension);
});
}
/**
* Reloads BrowserSync.
* Note: Exits more reliably when used with a done callback.
*/
function reload(done) {
browserSync.reload();
done();
}
/**
* Reloads BrowserSync, with CSS injection.
* Note: Exits more reliably when used with a done callback.
*/
function reloadCSS(done) {
browserSync.reload('*.css');
done();
}
function watch() {
const watchers = [
{
name: 'CSS',
paths: [normalizePath(paths().source.css, '**', '*.scss')],
config: { awaitWriteFinish: true },
tasks: gulp.series('pl-sass','pl-copy:css', reloadCSS)
},
{
name: 'Pattern Scaffolding CSS',
paths: [normalizePath(paths().source.css, 'pattern-scaffolding.css')],
config: { awaitWriteFinish: true },
tasks: gulp.series('pl-copy:css', reloadCSS)
},
{
name: 'Icons',
paths: [normalizePath(paths().source.icons, '**', '*.svg')],
config: { awaitWriteFinish: true },
tasks: gulp.series('svg-sprite')
},
{
name: 'JavaScript',
paths: [normalizePath(paths().source.js, '**', '*.js')],
config: { awaitWriteFinish: true },
tasks: gulp.series('concat-and-minify')
},
{
name: 'Styleguide Files',
paths: [normalizePath(paths().source.styleguide, '**', '*')],
config: { awaitWriteFinish: true },
tasks: gulp.series('pl-copy:styleguide', 'pl-copy:styleguide-css', reloadCSS)
},
{
name: 'Source Files',
paths: [
normalizePath(paths().source.patterns, '**', '*.json'),
normalizePath(paths().source.patterns, '**', '*.md'),
normalizePath(paths().source.data, '**', '*.json'),
normalizePath(paths().source.css, '**/*.scss'),
normalizePath(paths().source.fonts, '**', '*'),
normalizePath(paths().source.images, '**', '*'),
normalizePath(paths().source.icons, '**', '*'),
normalizePath(paths().source.js, '**', '*'),
normalizePath(paths().source.meta, '**', '*'),
normalizePath(paths().source.annotations, '**', '*')
].concat(getTemplateWatches()),
config: { awaitWriteFinish: true },
tasks: gulp.series(build, reload)
}
];
watchers.forEach(watcher => {
console.log('\n' + chalk.bold('Watching ' + watcher.name + ':'));
watcher.paths.forEach(p => console.log(' ' + p));
gulp.watch(watcher.paths, watcher.config, watcher.tasks);
});
console.log();
}
gulp.task('patternlab:connect', gulp.series(function (done) {
browserSync.init({
server: {
baseDir: normalizePath(paths().public.root)
},
snippetOptions: {
// Ignore all HTML files within the templates folder
blacklist: ['/index.html', '/', '/?*']
},
notify: {
styles: [
'display: none',
'padding: 15px',
'font-family: sans-serif',
'position: fixed',
'font-size: 1em',
'z-index: 9999',
'bottom: 0px',
'right: 0px',
'border-top-left-radius: 5px',
'background-color: #1B2032',
'opacity: 0.4',
'margin: 0',
'color: white',
'text-align: center'
]
}
}, function () {
done();
});
}));
/******************************************************
* EXPORT TO PRODUCTION
******************************************************/
// This is the task that exports the results from Pattern Lab
// into the Jekyll style guide that lives outside of this repository
gulp.task('copy:export-to-production', function (done) {
// Export css directory to style guide css directory
gulp.src('public/css/**/*')
.pipe(gulp.dest('../wp/app/public/wp-content/themes/v8'));
// Export js directory to style guide js directory
gulp.src('public/js/**/*')
.pipe(gulp.dest('../wp/app/public/wp-content/themes/v8/js'));
// Export images directory to style guide images directory
gulp.src('public/images/**/*')
.pipe(gulp.dest('../wp/app/public/wp-content/themes/v8/images'));
done();
});
/******************************************************
* COMPOUND TASKS
******************************************************/
gulp.task('default', gulp.series('patternlab:build'));
gulp.task('patternlab:watch', gulp.series('patternlab:build', 'svg-sprite', watch));
gulp.task('patternlab:serve', gulp.series('patternlab:build', 'svg-sprite', 'minify-css', 'patternlab:connect', watch));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment