pug-compiler
Renders Pug templates to HTML from the file contents, so earlier plugins can change them. Locals come from file.data and an object or a function of each file, includes and extends resolve from the file's own path, and partials such as _layout.pug are dropped.
npm install --save-dev @zilero/gulp-pug-compilerUsage
import { dest, src } from 'gulp';
import pugCompiler from '@zilero/gulp-pug-compiler';
export const pages = () =>
src('src/**/*.pug')
.pipe(pugCompiler({ data: { year: 2026 }, pugOptions: { pretty: true } })) // index.pug → index.html
.pipe(dest('dist'));data can be a function that returns the locals for each file, the output can have another extension, and onBeforeCompile changes the template before pug sees it:
pugCompiler({ data: async ({ file }) => ({ page: file.stem }) }); // front matter, a JSON file next to it, …
pugCompiler({ extname: '.php' }); // index.pug → index.php
pugCompiler({ onBeforeCompile: ({ content }) => content.replaceAll('{{year}}', '2026') });Options
| Option | Type | Default | Description |
|---|---|---|---|
pugOptions | Options | — | Passed to pug as an object: pretty, doctype, filters, basedir, … filename is set by the plugin. |
data | object | ({ file }) => object | Promise<object> | — | Locals for every template, or a function that returns them for each file. Merged over file.data: these win. |
extname | string | '.html' | The extension of the output, with its dot. |
skipPartials | boolean | true | Drop partials instead of rendering them: files whose name, or the name of a folder they are in below the base, starts with _. |
onBeforeCompile | ({ content, file }) => string | Promise<string> | — | Runs on the template source before pug and returns the source to compile. The file still has its own extension. |
onAfterCompile | ({ content, file }) => string | Promise<string> | — | Runs on the rendered HTML and returns the final HTML. The file already has its new extension. |
Unknown keys, an extension without its dot such as 'html', a data that is neither an object nor a function and a pugOptions that is not an object are an error when the plugin is created.
Locals
A template is rendered with file.data, then data over it: the object, or what the function returns for the file. On a key both have, the option wins. file.data is the convention of gulp-data and front-matter plugins, and is used when it is a plain object.
import data from 'gulp-data';
export const pages = () =>
src('src/pages/**/*.pug')
.pipe(data((file) => ({ title: file.stem }))) // file.data
.pipe(pugCompiler({ data: { siteName: 'Example' } })) // title and siteName
.pipe(dest('dist'));Hooks
onBeforeCompile and onAfterCompile get { content, file } and return the text to continue with, or a promise of it. A hook that returns anything else, say a JavaScript hook that forgets its return, fails the file with onAfterCompile must return the text as a string, got undefined. The data function gets { file }, typed TemplateDataInput. The types are exported from the package: ContentHook, ContentHookInput, TemplateData, TemplateDataFunction, TemplateDataInput.
Notes
- Only
.pugand.jadefiles are rendered, in any case. Other files, and files without contents (read: false), pass through untouched. - Relative includes and
extendsresolve from the file's path. Absolute ones (include /templates/_nav.pug) resolve frombasedir, which defaults tofile.base: the folder before the first glob insrc(). - With
skipPartials, partials leave the stream, so they are not written todest; templates still include them from disk. A partial is a file whose name starts with_(_layout.pug) or that sits in a folder whose name does, belowfile.base(_includes/nav.pug,_layouts/base.pug). - No source maps are produced. A file that already has one (
src(…, { sourcemaps: true })) keeps it, withsourceMap.filefollowing the new extension. - An error from pug,
dataor a hook, such as a template pug cannot compile or render, emits a PluginError with the file path. - Templates are compiled with
compileDebug: true, so an error while rendering quotes the lines of the compiled text, the contents as earlier plugins left them, instead of reading the file from disk. SetpugOptions: { compileDebug: false }to turn it off. - The compiler is pug 3; its options go through
pugOptions.
Migrating
From gulp-pug
| gulp-pug | pug-compiler |
|---|---|
pug({ pretty, doctype, … }) | pugCompiler({ pugOptions: { pretty, doctype, … } }) |
data, locals | data, an object or a function of the file |
file.data wins over data/locals | data wins over file.data |
client: true (compile to functions) | not supported |
pug (your own pug instance), jade | not supported: pug 3 is built in |
verbose | not supported |
renders every .pug file, partials too | partials dropped; skipPartials: false keeps them |
From 1.x
- 1.x compiled the file from disk with
compileFile, ignoring changes made by earlier plugins. Now the file contents are compiled. datais new: locals as an object or a function of the file.extnameis new; the default stays.html.- Partials (
_*.pug) are dropped by default; 1.x rendered every.pugfile, partials included.skipPartials: falsekeeps them. onAfterCompilemoved frompluginOptionsto the top level and gets{ content, file }.onBeforeCompileis new: it changes the template source before pug.basedirdefaults tofile.base, so absolute includes work without options.
See migrating from 1.x for every package.