templates/modernkit/gulpfile.js
2026-04-12 21:03:18 +03:00

303 lines
9.4 KiB
JavaScript

import gulp from 'gulp';
import twig from 'gulp-twig';
import * as dartSass from 'sass';
import gulpSass from 'gulp-sass';
import autoprefixer from 'gulp-autoprefixer';
import browserSync from 'browser-sync';
import babel from 'gulp-babel';
import concat from 'gulp-concat';
import uglify from 'gulp-uglify';
import imagemin from 'gulp-imagemin';
import cleanCss from 'gulp-clean-css';
import { deleteAsync } from 'del';
import sourcemaps from 'gulp-sourcemaps';
import fs from 'fs';
import plumber from 'gulp-plumber';
import svgstore from 'gulp-svgstore';
import cheerio from 'gulp-cheerio';
import through2 from 'through2';
import data from 'gulp-data';
import path from 'path';
import webp from 'gulp-webp';
import rev from 'gulp-rev';
import revReplace from 'gulp-rev-replace';
import cached from 'gulp-cached';
import remember from 'gulp-remember';
import { exec } from 'child_process';
import puppeteer from 'puppeteer';
import postcss from 'gulp-postcss';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const sass = gulpSass(dartSass);
browserSync.create();
const cleanTask = () => {
return deleteAsync(['dist']);
};
const lintJsTask = (cb) => {
exec('npx @biomejs/biome check src/js', (err, stdout, stderr) => {
console.log(stdout);
console.error(stderr);
if (err) {
console.error('Biome check failed!', err);
return cb(err);
}
cb();
});
};
const formatJsTask = (cb) => {
exec('npx @biomejs/biome format --write src/js', (err, stdout, stderr) => {
console.log(stdout);
console.error(stderr);
if (err) {
console.error('Biome format failed!', err);
return cb(err);
}
cb();
});
};
export const svgSpriteTask = (cb) => {
let svgContent = '';
return gulp.src('src/icons/**/*.svg')
.pipe(cached('svgIcons')) // Cache SVG icons
.pipe(plumber())
.pipe(cheerio({
run: function ($) {
$('[fill]').removeAttr('fill');
$('[stroke]').removeAttr('stroke');
$('[style]').removeAttr('style');
},
parserOptions: { xmlMode: true }
}))
.pipe(svgstore({
inlineSvg: true
}))
.pipe(remember('svgIcons')) // Remember all SVG icons
.pipe(through2.obj(function (file, enc, cb2) {
svgContent = file.contents.toString();
cb2(null, file);
}))
.pipe(gulp.dest('dist')) // Still write to dist for consistency
.on('end', () => {
// Ensure the file is written before calling the callback
fs.promises.writeFile('./dist/svg-sprite.svg', svgContent)
.then(cb)
.catch(cb);
});
};
const twigTask = () => {
const globalData = JSON.parse(fs.readFileSync('./src/data/global.json'));
const svgSprite = fs.readFileSync('./dist/svg-sprite.svg', 'utf8');
return gulp.src('src/templates/*.twig') // Process only top-level twig files
.pipe(cached('twigTemplates')) // Cache twig templates
.pipe(plumber())
.pipe(data(function(file) {
const fileName = path.basename(file.path, '.twig');
const dataFilePath = `./src/data/${fileName}.json`;
let pageData = {};
if (fs.existsSync(dataFilePath)) {
pageData = JSON.parse(fs.readFileSync(dataFilePath));
}
return { ...globalData, ...pageData, svgSprite: svgSprite };
}))
.pipe(twig())
.pipe(remember('twigTemplates')) // Remember all twig templates
.pipe(gulp.dest('dist'))
.pipe(browserSync.stream());
};
const scssTask = () => {
return gulp.src('src/scss/main.scss')
.pipe(cached('scss')) // Cache SCSS files
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer())
.pipe(sourcemaps.write('.'))
.pipe(remember('scss')) // Remember all SCSS files
.pipe(gulp.dest('dist'))
.pipe(browserSync.stream());
};
const scssProdTask = () => {
return gulp.src('src/scss/main.scss')
.pipe(cached('scssProd')) // Cache SCSS files for prod
.pipe(plumber())
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer())
.pipe(cleanCss())
.pipe(remember('scssProd')) // Remember all SCSS files for prod
.pipe(gulp.dest('dist'));
};
const jsDevTask = () => {
return gulp.src('src/js/**/*.js')
.pipe(cached('jsDev')) // Cache JS files for dev
.pipe(plumber())
.pipe(babel({
presets: ['@babel/env']
}))
.pipe(concat('main.js'))
.pipe(sourcemaps.write('.'))
.pipe(remember('jsDev')) // Remember all JS files for dev
.pipe(gulp.dest('dist/js'))
.pipe(browserSync.stream());
};
const jsMinTask = () => {
return gulp.src(['src/js/**/*.js', '!src/js/**/*.test.js'])
.pipe(cached('jsProd')) // Cache JS files for prod
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(babel({
presets: ['@babel/env']
}))
.pipe(concat('main.min.js'))
.pipe(uglify())
.pipe(sourcemaps.write('.'))
.pipe(remember('jsProd')) // Remember all JS files for prod
.pipe(gulp.dest('dist/js'))
.pipe(browserSync.stream());
};
const jsTask = () => {
return gulp.src(['src/js/**/*.js', '!src/js/**/*.test.js'])
.pipe(cached('jsProd')) // Cache JS files for prod
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(babel({
presets: ['@babel/env']
}))
.pipe(concat('main.js'))
.pipe(sourcemaps.write('.'))
.pipe(remember('jsProd')) // Remember all JS files for prod
.pipe(gulp.dest('dist/js'))
.pipe(browserSync.stream());
};
const imagesTask = () => {
return gulp.src('src/images/*')
.pipe(cached('images')) // Cache images
.pipe(plumber())
.pipe(imagemin())
.pipe(remember('images')) // Remember all images
.pipe(gulp.dest('dist/images'))
.pipe(browserSync.stream());
};
const imagesProdTask = () => {
return gulp.src('src/images/*')
.pipe(cached('imagesProd')) // Cache images for prod
.pipe(plumber())
.pipe(imagemin())
.pipe(gulp.dest('dist/images'))
.pipe(webp())
.pipe(gulp.dest('dist/images'));
};
const copyAssetsTask = () => {
return gulp.src('src/assets/**/*')
.pipe(cached('assets')) // Cache assets
.pipe(plumber())
.pipe(remember('assets')) // Remember all assets
.pipe(gulp.dest('dist/assets'))
.pipe(browserSync.stream());
};
const copyFaviconTask = () => {
return gulp.src('src/favicon.ico')
.pipe(cached('favicon')) // Cache favicon
.pipe(plumber())
.pipe(remember('favicon')) // Remember favicon
.pipe(gulp.dest('dist'))
.pipe(browserSync.stream());
};
const copyFontsTask = () => {
return gulp.src('src/fonts/**/*')
.pipe(cached('fonts')) // Cache fonts
.pipe(plumber())
.pipe(remember('fonts')) // Remember all fonts
.pipe(gulp.dest('dist/fonts'))
.pipe(browserSync.stream());
};
const revTask = () => {
return gulp.src(['dist/**/*.css', 'dist/**/*.js'], { base: 'dist' })
.pipe(gulp.dest('dist')) // write original assets to dist
.pipe(rev())
.pipe(gulp.dest('dist')) // write rev'd assets to dist
.pipe(rev.manifest())
.pipe(gulp.dest('dist')); // write manifest to dist
};
const revReplaceTask = () => {
const manifest = gulp.src('dist/rev-manifest.json');
return gulp.src('dist/**/*.html')
.pipe(revReplace({ manifest: manifest }))
.pipe(gulp.dest('dist'));
};
const screenshotsTask = async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
const resolutions = [
{ width: 1920, height: 1080, name: 'desktop' },
{ width: 1366, height: 768, name: 'laptop' },
{ width: 768, height: 1024, name: 'tablet' },
{ width: 375, height: 667, name: 'mobile' },
];
// Ensure the screenshots directory exists
if (!fs.existsSync('dist/screenshots')) {
fs.mkdirSync('dist/screenshots');
}
for (const res of resolutions) {
await page.setViewport({ width: res.width, height: res.height });
await page.goto('file://' + path.resolve(__dirname, 'dist/index.html'));
await page.screenshot({ path: `dist/screenshots/screenshot-${res.name}-${res.width}x${res.height}.png` });
console.log(`Screenshot captured for ${res.name} (${res.width}x${res.height})`);
}
await browser.close();
};
const watchTask = () => {
browserSync.init({
server: {
baseDir: './dist'
},
https: true // Enable HTTPS
});
gulp.watch('src/templates/**/*.twig', twigTask);
gulp.watch('src/scss/**/*.scss', scssTask);
gulp.watch('src/js/**/*.js', gulp.series(lintJsTask, jsDevTask));
gulp.watch('src/images/*', imagesTask);
gulp.watch('src/data/**/*.json', twigTask);
gulp.watch('src/assets/**/*', copyAssetsTask);
gulp.watch('src/favicon.ico', copyFaviconTask);
gulp.watch('src/icons/**/*.svg', gulp.series(svgSpriteTask, twigTask)); // Watch for changes in SVG icons
gulp.watch('src/fonts/**/*', copyFontsTask); // Watch for changes in fonts
};
const devBuild = gulp.series(cleanTask, svgSpriteTask, gulp.parallel(scssTask, jsDevTask, imagesTask, copyAssetsTask, copyFaviconTask, copyFontsTask), twigTask);
export const build = gulp.series(cleanTask, lintJsTask, svgSpriteTask, twigTask, gulp.parallel(scssTask, jsDevTask, imagesTask, copyAssetsTask, copyFaviconTask, copyFontsTask));
export const buildProd = gulp.series(cleanTask, lintJsTask, svgSpriteTask, twigTask, gulp.parallel(scssProdTask, jsTask, jsMinTask, imagesProdTask, copyAssetsTask, copyFaviconTask, copyFontsTask), revTask, revReplaceTask, screenshotsTask);
export const screenshots = screenshotsTask;
export default gulp.series(devBuild, watchTask);