laravel-mix-pug-recursive
Version:
Laravel Mix Plugin for compiling Pug/Jade templates.
183 lines (144 loc) • 4.52 kB
JavaScript
const FileCollection = require('laravel-mix/src/FileCollection');
const File = require('laravel-mix/src/File');
const Task = require('laravel-mix/src/tasks/Task');
const PugSeeder = require('./PugSeeder');
const notifier = require('node-notifier');
const glob = require('glob');
const path = require('path');
const pug = require('pug');
const fs = require('fs');
const mkdirp = require('mkdirp');
class MixPugTask extends Task {
/**
* Run the pug compiler.
*/
run() {
let {files, dest, options} = this.data;
if (!options) {
options = {
seeds: null,
locals: {},
pug: null,
ext: '.html',
excludePath: null
};
}
// Set destination folder
this.dest = dest;
// Set pug options
this.pugOptions = options.pug;
// Setup template seeder
this.seedPath = options.seeds;
this.locals = options.locals || {};
this.extension = options.ext || '.html';
this.excludePath = options.excludePath || null;
this.seeder = this.createSeeder();
// Prepare Template Files
this.templates = files;
// We'll be watching for changes on all pug files
// in case a layout, mixin or partial changes and
// all seed files included.
this.files = new FileCollection(
glob.sync('**/*.pug', {ignore: 'node_modules/**/*'}).concat(
this.seeder.files
)
);
// Preprare destination assets
this.assets = files.map(asset => this.prepareAssets(asset));
this.compile();
}
/**
* Compiles a collection of Pug templates.
*
*/
compile() {
this.templates.forEach((template, index) => this.compileTemplate(template, index));
return this;
}
/**
* Compiles a single pug template
*
* @param {string} src Path to the pug source file
* @param {number} index
*/
compileTemplate(src, index) {
let file = new File(src);
let output = this.assets[index];
try {
let template = pug.compileFile(file.path(), this.pugOptions);
let html = template(
this.seeder.locals
);
fs.writeFileSync(output.path(), html);
this.onSuccess();
} catch (e) {
this.onFail(e.name + ': ' + e.message);
}
}
/**
* Updates seeder with changed data files
*
*/
createSeeder() {
return new PugSeeder(this.seedPath)
.extend(this.locals);
}
/**
* Recompile on change when using watch
*
* @param {string} updatedFile
*/
onChange(updatedFile) {
this.seeder = this.createSeeder();
this.compile();
}
/**
* Handle successful compilation.
*
* @param {string} output
*/
onSuccess(output) {
if (Config.notifications.onSuccess) {
notifier.notify({
title: 'Laravel Mix',
message: 'Pug Compilation Successful',
contentImage: 'node_modules/laravel-mix-pug/src/logo.png'
});
}
}
/**
* Handle failed compilation.
*
* @param {string} output
*/
onFail(output) {
console.log("\n");
console.log('Pug Compilation Failed!');
console.log();
console.log(output);
if (Mix.isUsing('notifications')) {
notifier.notify({
title: 'Laravel Mix',
subtitle: 'Pug Compilation Failed',
message: output,
contentImage: 'node_modules/laravel-mix-pug/src/logo.png'
});
}
}
relativePathFromSource(filePath, excludePath) {
excludePath = excludePath || 'resources/assets/pug';
return filePath.split(excludePath).pop();
}
prepareAssets(src) {
let file = new File(src);
let pathFromBase = this.relativePathFromSource(file.base(), this.excludePath);
let baseDir = (new File(path.join(this.dest, pathFromBase))).absolutePath;
if (!File.exists(baseDir)) {
mkdirp.sync(baseDir);
}
let output = path.join(baseDir, file.nameWithoutExtension() + this.extension);
let asset = new File(output);
return asset;
}
}
module.exports = MixPugTask;