Created
June 19, 2019 07:46
-
-
Save panoply/88a49a95633b342672d43df88252cbe8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { src, dest, watch, series, parallel, lastRun } = require('gulp') | |
const pipeline = require('stream').pipeline | |
const fs = require('fs') | |
const sass = require('gulp-sass') | |
const changed = require('gulp-changed') | |
const imagemin = require('gulp-imagemin') | |
const flatten = require('gulp-flatten') | |
const gulpif = require('gulp-if') | |
const cssnano = require('gulp-cssnano') | |
const rename = require('gulp-rename') | |
const svgsprite = require('gulp-svg-sprite') | |
const htmlmin = require('gulp-htmlmin') | |
const { rollup } = require('rollup') | |
const { uglify } = require('rollup-plugin-uglify') | |
const includepaths = require('rollup-plugin-includepaths') | |
const buble = require('rollup-plugin-buble') | |
const babel = require('rollup-plugin-babel') | |
const noderesolve = require('rollup-plugin-node-resolve') | |
const depinject = require('rollup-plugin-dep-inject') | |
const commonjs = require('rollup-plugin-commonjs') | |
const minimist = require('minimist') | |
const shopifysync = require('shopify-sync') | |
const del = require('del') | |
const bs = require('browser-sync').create() | |
const gulplogs = require('./build/logs/gulp-errors') | |
const rolluplogs = require('./build/logs/rollup-errors') | |
const print = require('./build/plugins/print') | |
const paths = require('./build/plugins/paths') | |
const icons = require('./build/plugins/icons') | |
/* -------------------------------------------- */ | |
/* CONFIGURATION */ | |
/* -------------------------------------------- */ | |
const input = 'source' | |
const output = 'theme' | |
const config = { | |
scripts: { | |
src: `${input}/scripts/bundle.js`, | |
dist: `${output}/assets/bundle.js`, | |
watch: `${input}/scripts/**/*.js`, | |
external: [ | |
'mithril', | |
'turbolinks', | |
'glider-js', | |
'stickybits' | |
], | |
globals: { | |
mithril: 'm', | |
turbolinks: 'Turbolinks', | |
'glider-js': 'Glider', | |
stickybits: 'stickybits' | |
} | |
}, | |
styles: { | |
src: `${input}/styles/stylesheet.scss`, | |
dest: `${output}/assets/`, | |
watch: `${input}/styles/**/*.scss`, | |
include: [ | |
'node_modules/', | |
'node_modules/bootstrap/scss/' | |
] | |
}, | |
images: { | |
src: `${input}/images/**/**`, | |
dest: `${output}/assets/` | |
}, | |
icons: { | |
src: { | |
inline: `${input}/icons/inline/*.svg`, | |
sprite: `${input}/icons/sprite/*.svg` | |
}, | |
dest: `${output}/snippets`, | |
watch: `${input}/icons/**/*.svg` | |
}, | |
schema: { | |
src: `${input}/schema/**/*.json`, | |
dest: `${output}` | |
}, | |
views: { | |
src: `${input}/views/**/*.liquid`, | |
dest: `${output}`, | |
paths: { | |
prepend: { | |
layout: [ | |
'theme.liquid' | |
] | |
}, | |
skip: { | |
sections: [ | |
'collection', | |
'index', | |
'layout', | |
'page', | |
'product' | |
] | |
} | |
} | |
} | |
} | |
/* -------------------------------------------- */ | |
/* MINIMIST */ | |
/* -------------------------------------------- */ | |
const cli = minimist(process.argv.slice(2), { | |
boolean: [ | |
'prod', | |
'dev', | |
'force' | |
], | |
alias: { | |
prod: 'production', | |
dev: 'development' | |
} | |
}) | |
cli.dev = !cli.prod | |
/* -------------------------------------------- */ | |
/* SERVE */ | |
/* -------------------------------------------- */ | |
function Serve () { | |
let domain, theme | |
const { targets } = JSON.parse(fs.readFileSync('.shopifysync')) | |
targets.map(target => { | |
if (target.target_name === 'development') { | |
domain = target.primary_domain | |
theme = target.theme_id | |
} | |
}) | |
return bs.init({ | |
proxy: `${domain}/?preview_theme_id=${theme}`, | |
logPrefix: print({ | |
timestamp: true | |
}), | |
files: [ | |
`${output}/assets/**` | |
], | |
serveStatic: [ | |
`${output}/assets` | |
], | |
notify: true, | |
open: false, | |
https: { | |
key: './build/localhost.key', | |
cert: './build/localhost.crt' | |
}, | |
reloadOnRestart: true, | |
ui: { | |
port: 4000 | |
}, | |
snippetOptions: { | |
rule: { | |
match: /<script/, | |
fn: (snippet, match) => snippet + match | |
} | |
}, | |
rewriteRules: [ | |
{ | |
match: /(<link href=)(.*?)\/\/(cdn.shopify.com)(.*?)(stylesheet.css)/, | |
fn: () => '<link href="/stylesheet.css' | |
}, | |
{ | |
match: /(?:<script src="\/\/cdn.shopify.com.*?\/assets\/.*?.js)/, | |
fn: () => '<script src="/bundle.js' | |
} | |
] | |
}) | |
} | |
/* -------------------------------------------- */ | |
/* SHOPIFY SYNC */ | |
/* -------------------------------------------- */ | |
function Sync () { | |
return shopifysync('watch', | |
{ | |
target: cli.prod ? 'production' : 'development', | |
ignore: [ | |
'theme/assets/stylesheet.css.map', | |
'theme/assets/bundle.js.map' | |
] | |
}, | |
function () { | |
return bs.reload() | |
}) | |
} | |
/* -------------------------------------------- */ | |
/* ICONS */ | |
/* -------------------------------------------- */ | |
function Icons (done) { | |
const task = config.icons | |
function sprite () { | |
return pipeline([ | |
src(task.src.sprite, { | |
since: lastRun(sprite) | |
}), | |
icons({ | |
task: 'sprite', | |
class: 'icon', | |
classPrefix: 'icon-' | |
}, | |
{ | |
plugins: [ | |
{ | |
removeUnknownsAndDefaults: { | |
keepDataAttrs: false | |
} | |
} | |
] | |
}), | |
svgsprite({ | |
svg: { | |
xmlDeclaration: false, | |
doctypeDeclaration: false, | |
namespaceIDs: false, | |
dimensionAttributes: false, | |
rootAttributes: { | |
id: 'icons', | |
class: 'd-none' | |
}, | |
transform: [ | |
function (svg) { | |
let attr = 'data-turbolinks-permanent' | |
let match = `id="icons"` | |
let string = `${match} ${attr}` | |
let regex = new RegExp(match, 'gi') | |
svg = svg.replace(regex, string) | |
return svg | |
} | |
] | |
}, | |
mode: { | |
shape: { | |
dimension: { | |
precision: 2, | |
attributes: false | |
} | |
}, | |
symbol: { | |
inline: true, | |
dest: '.', | |
sprite: 'icons.liquid', | |
example: false | |
} | |
} | |
}), | |
changed(task.dest, { | |
hasChanged: changed.compareContents | |
}), | |
print(), | |
dest(task.dest) | |
], | |
gulplogs) | |
} | |
function inline () { | |
return pipeline([ | |
src([ | |
task.src.inline, | |
task.src.sprite | |
], { | |
since: lastRun(inline) | |
}), | |
icons({ | |
class: 'icon', | |
classPrefix: 'icon-' | |
}, | |
{ | |
plugins: [ | |
{ | |
removeUnknownsAndDefaults: { | |
keepDataAttrs: false | |
} | |
}, | |
{ | |
addClassesToSVGElement: { | |
className: 'icon' | |
} | |
} | |
] | |
}), | |
rename({ | |
prefix: 'icon.', | |
extname: '.liquid' | |
}), | |
changed(task.dest, { | |
hasChanged: changed.compareContents | |
}), | |
print(), | |
dest(task.dest) | |
], | |
gulplogs) | |
} | |
series(sprite, inline)(done) | |
} | |
/* -------------------------------------------- */ | |
/* IMAGES */ | |
/* -------------------------------------------- */ | |
function Images () { | |
const task = config.images | |
return pipeline([ | |
src(task.src, { | |
since: lastRun(Images) | |
}), | |
flatten(), | |
changed(task.src), | |
imagemin(), | |
changed(task.dest, { | |
hasChanged: changed.compareContents | |
}), | |
dest(task.dest) | |
], | |
gulplogs) | |
} | |
/* -------------------------------------------- */ | |
/* SCRIPTS */ | |
/* -------------------------------------------- */ | |
async function Scripts () { | |
const task = config.scripts | |
const bundle = await rollup({ | |
input: task.src, | |
external: cli.dev ? task.external : [], | |
plugins: [ | |
cli.dev && | |
depinject({ | |
index: `${output}/layout/theme.liquid`, | |
attr: 'defer' | |
}), | |
includepaths({ | |
paths: [ | |
`${input}/scripts/` | |
] | |
}), | |
noderesolve(), | |
commonjs(), | |
babel({ | |
exclude: 'node_modules/**' | |
}), | |
buble({ | |
transforms: { | |
forOf: false | |
} | |
}), | |
cli.prod && uglify() | |
] | |
}).catch(rolluplogs) | |
await bundle | |
.write({ | |
file: task.dist, | |
format: 'iife', | |
name: 'App', | |
globals: cli.dev ? task.globals : {}, | |
sourcemap: cli.dev | |
}) | |
.then(({ output }) => { | |
output.map(({ fileName }) => { | |
return print({ | |
filename: fileName, | |
through2: false | |
}) | |
}) | |
}) | |
} | |
/* -------------------------------------------- */ | |
/* STYLES */ | |
/* -------------------------------------------- */ | |
function Styles () { | |
const task = config.styles | |
return pipeline([ | |
src(task.src, { | |
sourcemaps: true | |
}), | |
sass({ | |
outputStyle: 'compact', | |
includePaths: task.include | |
}), | |
gulpif(cli.prod, | |
cssnano({ | |
autoprefixer: { | |
add: true, | |
browsers: [] | |
} | |
})), | |
dest(task.dest, { | |
sourcemaps: '.' | |
}), | |
print(), | |
gulpif(cli.dev, bs.stream()) | |
], | |
gulplogs) | |
} | |
/* -------------------------------------------- */ | |
/* SCHEMA */ | |
/* -------------------------------------------- */ | |
function Schema () { | |
const task = config.schema | |
return pipeline([ | |
src(task.src, { | |
since: lastRun(Schema) | |
}), | |
changed(task.dest, { | |
hasChanged: changed.compareContents | |
}), | |
print(), | |
dest(task.dest) | |
], | |
gulplogs) | |
} | |
/* -------------------------------------------- */ | |
/* VIEWS */ | |
/* -------------------------------------------- */ | |
function Views () { | |
const task = config.views | |
return pipeline([ | |
src(task.src, { | |
since: lastRun(Views), | |
sourcemaps: true | |
}), | |
paths(task.paths), | |
gulpif(cli.prod, | |
htmlmin({ | |
minifyJS: true, | |
collapseWhitespace: true, | |
processScripts: 'text/template', | |
removeComments: true | |
})), | |
changed(task.dest, { | |
hasChanged: changed.compareContents | |
}), | |
print(), | |
dest(task.dest) | |
], | |
gulplogs).on('end', bs.reload) | |
} | |
/* -------------------------------------------- */ | |
/* EXPORT */ | |
/* -------------------------------------------- */ | |
function Export () { | |
return pipeline([ | |
src(`${output}/**/**`), | |
zip(cli.prod ? 'production.zip' : 'development.zip'), | |
dest('export') | |
], | |
gulplogs) | |
} | |
/* -------------------------------------------- */ | |
/* CLEAN */ | |
/* -------------------------------------------- */ | |
function Clean () { | |
return del(`${output}/**/**`) | |
} | |
/* -------------------------------------------- */ | |
/* WATCH */ | |
/* -------------------------------------------- */ | |
function Watch () { | |
watch(config.styles.watch, Styles) | |
watch(config.schema.src, Schema) | |
watch(config.views.src, Views) | |
watch(config.images.src, Images) | |
watch(config.scripts.watch, Scripts) | |
watch(config.icons.watch, Icons) | |
} | |
/* -------------------------------------------- */ | |
/* EXPORT */ | |
/* -------------------------------------------- */ | |
exports.views = Export | |
exports.views = Views | |
exports.styles = Styles | |
exports.scripts = Scripts | |
exports.schema = Schema | |
exports.images = Images | |
exports.icons = Icons | |
exports.sync = Sync | |
exports.serve = Serve | |
exports.watch = Watch | |
exports.default = parallel(Watch, Serve, Sync) | |
exports.build = series( | |
Clean, | |
Styles, | |
Scripts, | |
Schema, | |
Views, | |
Images, | |
Icons, | |
Export | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment