├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
└── src
├── MixPugTask.js
├── PugSeeder.js
├── index.js
└── logo.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## [v0.3.0 (2019-03-01)](https://github.com/matejsvajger/laravel-mix-pug/compare/0.2.1...0.3.0)
4 |
5 | ### Fixed
6 | - Fixed compatibilty with laravel-mix v4 ([#10](https://github.com/matejsvajger/laravel-mix-pug/pull/10))
7 | - Fixed typo in Readme.md
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Matej Svajger
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # laravel-mix-pug
2 | Laravel Mix Plugin for compiling Pug/Jade templates.
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | ## Introduction
11 |
12 | This package provides a plugin for Laravel Mix to compile pug templates. `laravel-mix-pug` requires Laravel Mix to work. Please follow the instructions on how to use it on the package [repository](https://github.com/JeffreyWay/laravel-mix).
13 |
14 | ## Usage
15 |
16 | Install this package into your project:
17 |
18 | ```
19 | npm install laravel-mix-pug --save-dev
20 | ```
21 | Head over to your `webpack.mix.js` and register it on the Laravel Mix API:
22 |
23 | ```js
24 | let mix = require('laravel-mix');
25 | mix.pug = require('laravel-mix-pug');
26 |
27 | mix.js('src/app.js', 'dist')
28 | .sass('src/app.scss', 'dist')
29 | .pug('src/*.pug', 'dist')
30 | .setPublicPath('dist');
31 | ```
32 |
33 | ## Options
34 | You can also pass in a third optional parameter: *options* object. It accepts two options:
35 |
36 | ### seeds
37 | This is a path to a folder with seed files. Files can be of type `json` or `yaml`. They will be parsed and provided in your pug template locals under the seed file name and then contents.
38 |
39 | ```js
40 | mix.pug('src/*.pug', 'dist', {seeds:'src/seeds'});
41 | ```
42 |
43 | And if you have a file `demo.yml` in there all the content will be available in your template under
44 |
45 | ```pug
46 | a(href=seed.demo.anchor.link) seed.demo.anchor.name
47 | ```
48 |
49 | ### locals
50 | It's possible to pass in an object which will be added to locals in your pug templates:
51 |
52 | ```js
53 | mix.pug('src/*.pug', 'dist', {
54 | locals: {
55 | config: { baseUrl: 'http://my-template.dev/' }
56 | }
57 | });
58 | ```
59 |
60 | and in your pug file:
61 |
62 | ```pug
63 | link(rel="stylesheet" media="screen" href=`{config.baseUrl}css/app.css`)
64 | script(src=`{config.baseUrl}js/main.js`)
65 | ```
66 |
67 | ### pug
68 | You can pass in [pug config options](https://pugjs.org/api/reference.html#options) under `pug` key:
69 |
70 | ```js
71 | mix.pug('src/*.pug', 'dist', {
72 | pug: {
73 | pretty: true,
74 | debug: true
75 | }
76 | });
77 | ```
78 |
79 | ### ext && excludePath
80 | It is possible to change to output file extension and exclude part of the path.
81 | i.e.: You want your destination file to be in `resources/assets/views` and the folder structure in there to continue from the `resources/assets/pug/{..}`:
82 |
83 | ```js
84 | mix.pug('resources/assets/pug/*.pug', 'resources/assets/views', {
85 | ext: '.blade.php',
86 | excludePath: 'resources/assets/pug'
87 | });
88 | ````
89 |
90 | ## License
91 |
92 | Laravel Mix Pug is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).
93 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "laravel-mix-pug",
3 | "version": "0.3.0",
4 | "description": "Laravel Mix Plugin for compiling Pug/Jade templates.",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/matejsvajger/laravel-mix-pug.git"
12 | },
13 | "keywords": [
14 | "laravel",
15 | "mix",
16 | "pug"
17 | ],
18 | "author": "Matej Svajger ",
19 | "license": "MIT",
20 | "bugs": {
21 | "url": "https://github.com/matejsvajger/laravel-mix-pug/issues"
22 | },
23 | "homepage": "https://github.com/matejsvajger/laravel-mix-pug#readme",
24 | "dependencies": {
25 | "foldero": "^0.1.1",
26 | "glob": "^7.1.2",
27 | "js-yaml": "^3.9.1"
28 | },
29 | "peerDependencies": {
30 | "laravel-mix": "^1.4.2 || 2.x || 3.x || 4.x"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/MixPugTask.js:
--------------------------------------------------------------------------------
1 | const FileCollection = require('laravel-mix/src/FileCollection');
2 | const File = require('laravel-mix/src/File');
3 | const Task = require('laravel-mix/src/tasks/Task');
4 | const PugSeeder = require('./PugSeeder');
5 |
6 | const notifier = require('node-notifier');
7 | const glob = require('glob');
8 | const path = require('path');
9 | const pug = require('pug');
10 | const fs = require('fs');
11 |
12 | class MixPugTask extends Task {
13 |
14 | /**
15 | * Run the pug compiler.
16 | */
17 | run() {
18 |
19 | let {files, dest, options} = this.data;
20 |
21 | if (!options) {
22 | options = {
23 | seeds: null,
24 | locals: {},
25 | pug: null,
26 | ext: '.html',
27 | excludePath: null
28 | };
29 | }
30 |
31 | // Set destination folder
32 | this.dest = dest;
33 |
34 | // Set pug options
35 | this.pugOptions = options.pug;
36 |
37 | // Setup template seeder
38 | this.seedPath = options.seeds;
39 | this.locals = options.locals || {};
40 | this.extension = options.ext || '.html';
41 | this.excludePath = options.excludePath || null;
42 |
43 | this.seeder = this.createSeeder();
44 |
45 | // Prepare Template Files
46 | this.templates = files;
47 |
48 | // We'll be watching for changes on all pug files
49 | // in case a layout, mixin or partial changes and
50 | // all seed files included.
51 | this.files = new FileCollection(
52 | glob.sync('**/*.pug', {ignore: 'node_modules/**/*'}).concat(
53 | this.seeder.files
54 | )
55 | );
56 |
57 | // Preprare destination assets
58 | this.assets = files.map(asset => this.prepareAssets(asset));
59 |
60 | this.compile();
61 | }
62 |
63 |
64 | /**
65 | * Compiles a collection of Pug templates.
66 | *
67 | */
68 | compile() {
69 |
70 | this.templates.forEach((template, index) => this.compileTemplate(template, index));
71 |
72 | return this;
73 | }
74 |
75 | /**
76 | * Compiles a single pug template
77 | *
78 | * @param {string} src Path to the pug source file
79 | * @param {number} index
80 | */
81 | compileTemplate(src, index) {
82 | let file = new File(src);
83 | let output = this.assets[index];
84 |
85 | try {
86 |
87 | let template = pug.compileFile(file.path(), this.pugOptions);
88 |
89 | let html = template(
90 | this.seeder.locals
91 | );
92 |
93 | fs.writeFileSync(output.path(), html);
94 |
95 | this.onSuccess();
96 |
97 | } catch (e) {
98 | this.onFail(e.name + ': ' + e.message);
99 | }
100 | }
101 |
102 | /**
103 | * Updates seeder with changed data files
104 | *
105 | */
106 | createSeeder() {
107 | return new PugSeeder(this.seedPath)
108 | .extend(this.locals);
109 | }
110 |
111 | /**
112 | * Recompile on change when using watch
113 | *
114 | * @param {string} updatedFile
115 | */
116 | onChange(updatedFile) {
117 | this.seeder = this.createSeeder();
118 | this.compile();
119 | }
120 |
121 |
122 | /**
123 | * Handle successful compilation.
124 | *
125 | * @param {string} output
126 | */
127 | onSuccess(output) {
128 | if (Config.notifications.onSuccess) {
129 | notifier.notify({
130 | title: 'Laravel Mix',
131 | message: 'Pug Compilation Successful',
132 | contentImage: 'node_modules/laravel-mix-pug/src/logo.png'
133 | });
134 | }
135 | }
136 |
137 |
138 | /**
139 | * Handle failed compilation.
140 | *
141 | * @param {string} output
142 | */
143 | onFail(output) {
144 | console.log("\n");
145 | console.log('Pug Compilation Failed!');
146 | console.log();
147 | console.log(output);
148 |
149 | if (Mix.isUsing('notifications')) {
150 | notifier.notify({
151 | title: 'Laravel Mix',
152 | subtitle: 'Pug Compilation Failed',
153 | message: output,
154 | contentImage: 'node_modules/laravel-mix-pug/src/logo.png'
155 | });
156 | }
157 | }
158 |
159 | relativePathFromSource(filePath, excludePath) {
160 | excludePath = excludePath || 'resources/assets/pug';
161 | return filePath.split(excludePath).pop();
162 | }
163 |
164 | prepareAssets(src) {
165 | let file = new File(src);
166 | let pathFromBase = this.relativePathFromSource(file.base(), this.excludePath);
167 | let baseDir = path.join(pathFromBase, this.dest);
168 |
169 | if (!File.exists(baseDir)) {
170 | new File(baseDir).makeDirectories();
171 | }
172 |
173 | let output = path.join(baseDir, file.nameWithoutExtension() + this.extension);
174 | let asset = new File(output);
175 |
176 | return asset;
177 | }
178 |
179 | }
180 |
181 | module.exports = MixPugTask;
182 |
--------------------------------------------------------------------------------
/src/PugSeeder.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const _ = require('lodash');
3 | const glob = require('glob');
4 | const yaml = require('js-yaml');
5 | const foldero = require('foldero');
6 |
7 | class PugSeeder {
8 |
9 | constructor(path) {
10 |
11 | this.path = path;
12 | this.files = path ? glob.sync(path + '/**/*.+(json|yaml|yml)') : [];
13 | this.locals = {
14 | seed: path ? this.parse(path) : null
15 | };
16 | }
17 |
18 | /**
19 | * Parses all json|yaml files in the seed folder
20 | * and assigns them to locals object.
21 | *
22 | * @param {string} seedPath Path to directory with seed files
23 | */
24 | parse(seedPath) {
25 | if (fs.existsSync(seedPath)) {
26 | return foldero(seedPath, {
27 | recurse: true,
28 | whitelist: '(.*/)*.+\.(json|ya?ml)$',
29 | loader: file => this.parseFile(file)
30 | });
31 | }
32 | }
33 |
34 | /**
35 | * Parses a single seed file and
36 | * returns a representative object.
37 | *
38 | * @param {string} file path to seed file for parsing
39 | */
40 | parseFile(file) {
41 | let json = {};
42 |
43 | try {
44 | json = (path.extname(file).match(/^.ya?ml$/)) ?
45 | yaml.safeLoad(fs.readFileSync(file, 'utf8')):
46 | JSON.parse(fs.readFileSync(file, 'utf8'));
47 | } catch(e) {
48 | console.log(`Error Parsing DATA file: ${file}\n`);
49 | console.log('==== Details Below ====' + `\n${e.message}`);
50 |
51 | if (Mix.isUsing('notifications')) {
52 | notifier.notify({
53 | title: 'Laravel Mix',
54 | subtitle: 'Pug Compilation Failed',
55 | message: e.message,
56 | contentImage: 'node_modules/laravel-mix-pug/src/logo.png'
57 | });
58 | }
59 | }
60 |
61 | return json;
62 | }
63 |
64 | /**
65 | * Extends locals object with passed in object
66 | *
67 | * @param {object} data
68 | */
69 | extend(data) {
70 | this.locals = _.extend(this.locals, data);
71 | return this;
72 | }
73 |
74 | }
75 |
76 | module.exports = PugSeeder;
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | let Verify, Assert;
2 | // laravel-mix@1.x
3 | try { Verify = require('laravel-mix/src/Verify'); }
4 | // laravel-mix@>=2.x
5 | catch (e) { Assert = require('laravel-mix/src/Assert'); }
6 |
7 | const notifier = require('node-notifier');
8 | const glob = require('glob');
9 |
10 | function pug(src, dest, options) {
11 |
12 | // laravel-mix@1.x
13 | if (Verify != null) Verify.dependency('pug', ['pug'], true);
14 | // laravel-mix@>=2.x
15 | else Assert.dependencies(['pug'], true);
16 |
17 | let files = glob.sync(src);
18 |
19 | let MixPugTask = require('./MixPugTask');
20 |
21 | Mix.addTask(new MixPugTask({
22 | files, dest, options
23 | }));
24 |
25 | return this;
26 | }
27 |
28 | module.exports = pug;
29 |
--------------------------------------------------------------------------------
/src/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matejsvajger/laravel-mix-pug/dc6d286adc27f7f78f8a79c648ffefd07fbd417d/src/logo.png
--------------------------------------------------------------------------------