-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgulpfile.js
237 lines (219 loc) · 6.8 KB
/
gulpfile.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
const { src, dest, series, parallel, watch } = require("gulp");
const sourcemaps = require("gulp-sourcemaps");
const sass = require("gulp-sass")(require("sass"));
const postcss = require("gulp-postcss");
const babel = require("gulp-babel");
const concat = require("gulp-concat");
const gulpWebpack = require("webpack-stream");
const webpack = require("webpack");
const named = require("vinyl-named");
const gulpif = require("gulp-if");
const ejs = require("gulp-ejs");
const rename = require("gulp-rename");
const exec = require("gulp-exec");
const msgfmt = require("gulp-potomo");
const clean = require("gulp-clean");
const argv = require("yargs").option("dest", {
type: "string",
description: "The output directory of the build.",
}).argv;
const production = process.env.NODE_ENV === "production";
const data = require("./package.json");
const composer = require("./composer.json");
sass.compiler = require("sass");
let BUILD_DIR = "build";
if (argv.dest) {
BUILD_DIR = argv.dest;
}
/**
* Installs PHP dependencies in the build directory using composer. This step only
* installs runtime dependencies and no build dependencies.
*/
function installDependencies() {
return src(["composer.json", "composer.lock"])
.pipe(dest(BUILD_DIR))
.pipe(exec(`composer install --working-dir=${BUILD_DIR} --no-dev`));
}
/**
* Copies the includes directory into the build folder. There is no compilation required
* for the PHP files.
*/
function copyIncludes() {
return src("includes/**/*").pipe(dest(`${BUILD_DIR}/includes`));
}
/**
* Copies the WordPress templates from the `templates` folder into the build folder. The
* templates are copied into the root of the `build` directory so that the WordPress
* system can find them. No additional compilation is needed.
*/
function copyTemplates() {
return src("templates/**/*").pipe(dest(BUILD_DIR));
}
/**
* Copies the twig templates from the `views` folder into the `views` directory of the
* build folder. The templates are compiled on demand so no further compilation is
* needed here.
*/
function copyViews() {
return src("views/**/*").pipe(dest(`${BUILD_DIR}/views`));
}
/**
* Compiles the JavaScript files in the `scripts` directory and combines them into a
* single `musille.js` file that is then output into the build directory.
*
* The files are transpiled with Babel and are accompanied by sourcemaps.
*/
function compileScripts() {
return src("scripts/*.js")
.pipe(sourcemaps.init())
.pipe(babel())
.pipe(concat("musille.js"))
.pipe(sourcemaps.write("."))
.pipe(dest(BUILD_DIR));
}
/**
* Compiles the Gutenberg Blocks scripts. This task invoked webpack and outputs its
* result to the `blocks` directory in the build folder.
*
* See the `webpack.config.js` file for details on this step.
*/
function buildBlocks() {
return src("blocks/*.js")
.pipe(named())
.pipe(gulpWebpack(require("./webpack.config"), webpack))
.pipe(dest(`${BUILD_DIR}/blocks`));
}
/**
* Compiles the styles of the script into the build directory. All styles are compiled
* using Sass/SCSS and are post-processed with PostCSS and Autoprefixer.
*
* Sourcemaps are generated for all files.
*/
function buildStyles() {
return src(["styles/*.scss", "!styles/_*.scss"])
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(
sass({ outputStyle: production ? "compressed" : "expanded" }).on(
"error",
sass.logError
)
)
.pipe(postcss([require("autoprefixer")]))
.pipe(sourcemaps.write("."))
.pipe(dest(BUILD_DIR));
}
/**
* Copies the files from the `theme` folder into the root of the build folder. Any files
* with an `.ejs` extension are compiled using EJS. The templates receive the complete
* `package.json` object as `data` and `composer.json` object as `composer`.
*
* If we are building a release in GitHub CI the `release` object contains the
* respective webhook payload object.
*/
function copyThemeFiles() {
return src(["theme/*"])
.pipe(
gulpif(
/.ejs$/,
ejs({
data,
composer,
release:
process.env.GITHUB_EVENT_NAME === "release"
? require(process.env.GITHUB_EVENT_PATH).release
: {},
})
)
)
.pipe(gulpif(/.ejs$/, rename({ extname: "" })))
.pipe(dest(BUILD_DIR));
}
/**
* Compiles the translations from the `languages` folder into `.mo` files and outputs
* them into the `languages` folder of the build directory. The `musille-` prefix is
* removed from the filename.
*/
function compileMoTranslations() {
return src("./languages/*.po")
.pipe(msgfmt())
.pipe(
rename((file) => {
file.basename = file.basename.replace(/^musille-/, "");
return file;
})
)
.pipe(dest(`${BUILD_DIR}/languages`));
}
/**
* Runs `wp i18n make-json` on all translation files in the `languages` directory and
* outputs the resulting files into the `languages` folder of the build directory.
*/
function compileJedTranslations() {
return src("./languages/*.po").pipe(
exec( file =>
`./vendor/bin/wp i18n make-json --no-purge "${file.path}" ${BUILD_DIR}/languages/`
)
);
}
/**
* Dumps the composer autoload files for production builds. This will generate an
* authoritative classmap for all PHP files.
*/
function dumpAutoload() {
const command = ["composer", "dump-autoload", `--working-dir=${BUILD_DIR}`];
if (production) {
command.push("--classmap-authoritative");
}
return src(["composer.json", "composer.lock"])
.pipe(dest(BUILD_DIR))
.pipe(exec(command.join(" ")));
}
/**
* Removes temporary files from the build directory. This should always be the last step
* in a build pipeline.
*/
function cleanup() {
return src(`${BUILD_DIR}/composer.{json,lock}`, { read: false }).pipe(
clean()
);
}
/**
* Watches for changes in the source code and triggers the appropriate build steps to
* rebuild that part of the theme.
*/
function serve() {
watch("includes/**/*.php", copyIncludes);
watch("templates/**/*.php", copyTemplates);
watch("views/**/*.twig", copyViews);
watch("scripts/**/*.js", compileScripts);
watch("blocks/**/*.js", buildBlocks);
watch("styles/**/*.scss", buildStyles);
watch("theme/**/*", copyThemeFiles);
watch(
"languages/*.po",
parallel(compileMoTranslations, compileJedTranslations)
);
}
/**
* Builds the whole theme. This is triggered by `npm run build` and `npm run build-dev`.
*/
exports.default = series(
parallel(
series(
parallel(installDependencies, copyIncludes, copyTemplates),
dumpAutoload
),
copyViews,
compileScripts,
buildBlocks,
buildStyles,
copyThemeFiles,
compileMoTranslations,
compileJedTranslations
),
cleanup
);
/**
* Builds the theme and them watches changes. This is triggered by `npm run watch`.
*/
exports.watch = series(exports.default, serve);