Created
March 18, 2026 12:41
-
-
Save nickludlam/ccd2f5449fe2f7315302170cfdcb29ec to your computer and use it in GitHub Desktop.
A gulpfile which gives live reload functionality while developing a ghost theme hosted inside a docker container
This file contains hidden or 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
| import fs from 'fs'; | |
| import { series, watch, src, dest, parallel } from 'gulp'; | |
| import pump from 'pump'; | |
| import path from 'path'; | |
| import merge from 'merge-stream'; | |
| // gulp plugins and utils | |
| import livereload from 'gulp-livereload'; | |
| import postcss from 'gulp-postcss'; | |
| import zip from 'gulp-zip'; | |
| import concat from 'gulp-concat'; | |
| import replace from 'gulp-replace'; | |
| import uglify from 'gulp-uglify'; | |
| import beeper from 'beeper'; | |
| // postcss plugins | |
| import autoprefixer from 'autoprefixer'; | |
| import colorFunction from 'postcss-color-mod-function'; | |
| import cssnano from 'cssnano'; | |
| import easyimport from 'postcss-easy-import'; | |
| import { createRequire } from 'module'; | |
| const require = createRequire(import.meta.url); | |
| const pkg = require('./package.json'); | |
| // Configuration Block | |
| const LIVE_RELOAD_URL = 'http://mydevbox.local:35729/livereload.js'; | |
| const GHOST_THEME_PATH = path.join(process.cwd(), '../docker/docker-ghost-content/themes/my-ghost-theme'); | |
| // End Configuration Block | |
| // Check the parent of GHOST_THEME_PATH exists | |
| if (!fs.existsSync(path.dirname(GHOST_THEME_PATH))) { | |
| console.error('Error: Parent directory of GHOST_THEME_PATH does not exist. You must install the theme manually first.'); | |
| process.exit(1); | |
| } | |
| function serve(done) { | |
| livereload.listen(); | |
| done(); | |
| } | |
| const handleError = (done) => { | |
| return function (err) { | |
| if (err) { | |
| beeper(); | |
| } | |
| return done(err); | |
| }; | |
| }; | |
| function hbs(done) { | |
| pump([ | |
| src(['*.hbs', 'partials/**/*.hbs'], { base: '.' }), | |
| replace('{{LIVERELOAD_SCRIPT}}', '<script async src="' + LIVE_RELOAD_URL + '"></script>'), | |
| dest(GHOST_THEME_PATH + '/'), | |
| livereload() | |
| ], handleError(done)); | |
| } | |
| function css(done) { | |
| pump([ | |
| src('assets/css/*.css', { sourcemaps: true }), | |
| postcss([ | |
| easyimport, | |
| colorFunction(), | |
| autoprefixer(), | |
| cssnano() | |
| ]), | |
| dest('assets/built/', { sourcemaps: '.' }), | |
| dest(GHOST_THEME_PATH + '/'), | |
| livereload() | |
| ], handleError(done)); | |
| } | |
| function js(done) { | |
| pump([ | |
| src([ | |
| // pull in lib files first so our own code can depend on it | |
| 'assets/js/lib/*.js', | |
| 'assets/js/*.js' | |
| ], { sourcemaps: true }), | |
| concat('casper.js'), | |
| uglify(), | |
| dest('assets/built/', { sourcemaps: '.' }), | |
| dest(GHOST_THEME_PATH + '/'), | |
| livereload() | |
| ], handleError(done)); | |
| } | |
| function copyToDockerGhost(done) { | |
| // 1) Copy all non-HBS assets as-is (no string replacement on binary/text assets). | |
| pump([ | |
| src([ | |
| '**', | |
| '!node_modules', '!node_modules/**', | |
| '!dist', '!dist/**', | |
| '!yarn-error.log', | |
| '!yarn.lock', | |
| '!gulpfile.js', | |
| '!gulpfile.mjs', | |
| '!.git', '!.git/**', | |
| '!*.hbs', | |
| '!partials/**/*.hbs' | |
| ], { encoding: false }), | |
| dest(GHOST_THEME_PATH) | |
| ], function (err) { | |
| if (err) { | |
| return handleError(done)(err); | |
| } | |
| // 2) Copy HBS templates with live-reload script replacement. | |
| pump([ | |
| src(['*.hbs', 'partials/**/*.hbs'], { base: '.' }), | |
| replace('{{LIVERELOAD_SCRIPT}}', '<script async src="' + LIVE_RELOAD_URL + '"></script>'), | |
| dest(GHOST_THEME_PATH) | |
| ], handleError(done)); | |
| }); | |
| } | |
| function zipper(done) { | |
| const filename = pkg.name + '.zip'; | |
| // Copy non-HBS files as-is (binary-safe) | |
| const nonHbs = src([ | |
| '**', | |
| '!node_modules', '!node_modules/**', | |
| '!dist', '!dist/**', | |
| '!src', '!src/**', | |
| '!.git', '!.git/**', | |
| '!gulpfile.js', | |
| '!gulpfile.mjs', | |
| '!package-lock.json', | |
| '!yarn.lock', | |
| '!.DS_Store', | |
| '!*.log', | |
| '!.vscode', '!.vscode/**', | |
| '!.env', '!.env.*', | |
| '!*.hbs', | |
| '!partials/**/*.hbs' | |
| ], { encoding: false }); | |
| // Copy HBS files with livereload script removed | |
| const hbs = src(['*.hbs', 'partials/**/*.hbs'], { base: '.' }) | |
| .pipe(replace('{{LIVERELOAD_SCRIPT}}', '')); | |
| // Merge both streams, zip, and output | |
| return merge(nonHbs, hbs) | |
| .pipe(zip(filename)) | |
| .pipe(dest('dist/')); | |
| } | |
| const cssWatcher = () => watch('assets/css/**', series(css, copyToDockerGhost)); | |
| const jsWatcher = () => watch('assets/js/**', js); | |
| const hbsWatcher = () => watch(['*.hbs', 'partials/**/*.hbs'], series(hbs, copyToDockerGhost)); | |
| const watcher = parallel(cssWatcher, jsWatcher, hbsWatcher); | |
| const build = series(css, js); | |
| export { build }; | |
| const _zip = series(build, zipper); | |
| export { _zip as zip }; | |
| export default series(build, copyToDockerGhost, serve, watcher); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment