-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Expand file tree
/
Copy pathpackage_tasks.js
More file actions
262 lines (244 loc) · 8.35 KB
/
package_tasks.js
File metadata and controls
262 lines (244 loc) · 8.35 KB
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
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/**
* @license
* Copyright 2018 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Gulp tasks to package Blockly for distribution on NPM.
*/
const gulp = require('gulp');
gulp.concat = require('gulp-concat');
gulp.replace = require('gulp-replace');
gulp.rename = require('gulp-rename');
gulp.insert = require('gulp-insert');
gulp.umd = require('gulp-umd');
gulp.replace = require('gulp-replace');
const path = require('path');
const fs = require('fs');
const {rimraf} = require('rimraf');
const build = require('./build_tasks');
const {getPackageJson} = require('./helper_tasks');
const {BUILD_DIR, LANG_BUILD_DIR, RELEASE_DIR, TYPINGS_BUILD_DIR} = require('./config');
// Path to template files for gulp-umd.
const TEMPLATE_DIR = 'scripts/package/templates';
/**
* A helper method for wrapping a file into a Universal Module Definition.
* @param {string} namespace The export namespace.
* @param {Array<Object>} dependencies An array of dependencies to inject.
*/
function packageUMD(namespace, dependencies, template = 'umd.template') {
return gulp.umd({
dependencies: function () { return dependencies; },
namespace: function () { return namespace; },
exports: function () { return namespace; },
template: path.join(TEMPLATE_DIR, template)
});
};
/**
* This task wraps scripts/package/index.js into a UMD module.
*
* This module is the main entrypoint for the blockly package, and
* loads blockly/core, blockly/blocks and blockly/msg/en and then
* calls setLocale(en).
*/
function packageIndex() {
return gulp.src('scripts/package/index.js')
.pipe(packageUMD('Blockly', [{
name: 'Blockly',
amd: 'blockly/core',
cjs: 'blockly/core',
},{
name: 'en',
amd: 'blockly/msg/en',
cjs: 'blockly/msg/en',
global: 'Blockly.Msg',
},{
name: 'blocks',
amd: 'blockly/blocks',
cjs: 'blockly/blocks',
global: 'Blockly.Blocks',
}]))
.pipe(gulp.dest(RELEASE_DIR));
};
/**
* This task copies scripts/package/core-node.js into into the
* package. This module will be the 'blockly/core' entrypoint for
* node.js environments.
*
* Note that, unlike index.js, this file does not get a UMD wrapper.
* This is because it is only used in node.js environments and so is
* guaranteed to be loaded as a CJS module.
*/
function packageCoreNode() {
return gulp.src('scripts/package/core-node.js')
.pipe(gulp.dest(RELEASE_DIR));
};
/**
* This task wraps each of the files in ${BUILD_DIR/msg/ into a UMD module.
* @example import * as En from 'blockly/msg/en';
*/
function packageLocales() {
// Remove references to goog.provide and goog.require.
return gulp.src(`${LANG_BUILD_DIR}/*.js`)
.pipe(gulp.replace(/goog\.[^\n]+/g, ''))
.pipe(packageUMD('Blockly.Msg', [], 'umd-msg.template'))
.pipe(gulp.dest(`${RELEASE_DIR}/msg`));
};
/**
* This task creates a UMD bundle of Blockly which includes the Blockly
* core files, the built-in blocks, the JavaScript code generator and the
* English localization files.
* @example <script src="https://unpkg.com/blockly/blockly.min.js"></script>
*/
function packageUMDBundle() {
const srcs = [
`${RELEASE_DIR}/blockly_compressed.js`,
`${RELEASE_DIR}/msg/en.js`,
`${RELEASE_DIR}/blocks_compressed.js`,
`${RELEASE_DIR}/javascript_compressed.js`,
];
return gulp.src(srcs)
.pipe(gulp.concat('blockly.min.js'))
.pipe(gulp.dest(`${RELEASE_DIR}`));
};
/**
* This task creates shims for the submodule entrypoints, for the
* benefit of bundlers and other build tools that do not correctly
* support the exports declaration in package.json. These shims just
* require() and reexport the corresponding *_compressed.js bundle.
*
* This should solve issues encountered by users of bundlers that don't
* support exports at all (e.g. browserify) as well as ones that don't
* support it in certain circumstances (e.g., when using webpack's
* resolve.alias configuration option to alias 'blockly' to
* 'node_modules/blockly', as we formerly did in most plugins, which
* causes webpack to ignore blockly's package.json entirely).
*
* Assumptions:
* - Such bundlers will _completely_ ignore the exports declaration.
* - The bundles are intended to be used in a browser—or at least not
* in node.js—so the core entrypoint never needs to route to
* core-node.js. This is reasonable since there's little reason to
* bundle code for node.js, and node.js has supported the exports
* clause since at least v12, consideably older than any version of
* node.js we officially support.
* - It suffices to provide only a CJS entrypoint (because we can only
* provide CJS or ESM, not both. (We could in future switch to
* providing only an ESM entrypoint instead, though.)
*
* @param {Function} done Callback to call when done.
*/
function packageLegacyEntrypoints(done) {
for (entrypoint of [
'core', 'blocks', 'dart', 'javascript', 'lua', 'php', 'python'
]) {
const bundle =
(entrypoint === 'core' ? 'blockly' : entrypoint) + '_compressed.js';
fs.writeFileSync(path.join(RELEASE_DIR, `${entrypoint}.js`),
`// Shim for backwards-compatibility with bundlers that do not
// support the 'exports' clause in package.json, to allow them
// to load the blockly/${entrypoint} submodule entrypoint.
module.exports = require('./${bundle}');
`);
}
done();
}
/**
* This task copies all the media/* files into the release directory.
*/
function packageMedia() {
return gulp.src('media/*', {encoding: false})
.pipe(gulp.dest(`${RELEASE_DIR}/media`));
};
/**
* This task copies the package.json file into the release directory,
* with modifications:
*
* - The scripts section is removed.
*
* Prerequisite: buildLangfiles.
*
* @param {Function} done Callback to call when done.
*/
function packageJSON(done) {
// Copy package.json, so we can safely modify it.
const json = JSON.parse(JSON.stringify(getPackageJson()));
// Remove unwanted entries.
delete json['scripts'];
// Set "type": "commonjs", since that's what .js files in the
// package root are. This should be a no-op since that's the
// default, but by setting it explicitly we ensure that any chage to
// the repository top-level package.json to set "type": "module"
// won't break the published package accidentally.
json.type = 'commonjs';
// Write resulting package.json file to release directory.
if (!fs.existsSync(RELEASE_DIR)) {
fs.mkdirSync(RELEASE_DIR, {recursive: true});
}
fs.writeFileSync(`${RELEASE_DIR}/package.json`,
JSON.stringify(json, null, 2));
done();
};
/**
* This task copies the scripts/package/README.md file into the
* release directory. This file is what developers will see at
* https://www.npmjs.com/package/blockly .
*/
function packageReadme() {
return gulp.src('scripts/package/README.md')
.pipe(gulp.dest(RELEASE_DIR));
};
/**
* This task copies the generated .d.ts files in build/declarations and the
* hand-written .d.ts files in typings/ into the release directory. The main
* entrypoint file (index.d.ts) is referenced in package.json in the types
* property.
*/
function packageDTS() {
const handwrittenSrcs = [
'typings/*.d.ts',
'typings/msg/*.d.ts',
];
return gulp.src(handwrittenSrcs, {base: 'typings'})
.pipe(gulp.src(`${TYPINGS_BUILD_DIR}/**/*.d.ts`, {ignore: [
`${TYPINGS_BUILD_DIR}/blocks/**/*`,
]}))
.pipe(gulp.replace('AnyDuringMigration', 'any'))
.pipe(gulp.dest(RELEASE_DIR));
};
/**
* This task cleans the release directory (by deleting it).
*/
function cleanReleaseDir() {
// Sanity check.
if (RELEASE_DIR === '.' || RELEASE_DIR === '/') {
return Promise.reject(`Refusing to rm -rf ${RELEASE_DIR}`);
}
return rimraf(RELEASE_DIR);
}
/**
* This task prepares the files to be included in the NPM by copying
* them into the release directory.
*
* Prerequisite: build.
*/
const package = gulp.series(
gulp.parallel(
build.cleanBuildDir,
cleanReleaseDir),
build.build,
gulp.parallel(
packageIndex,
packageCoreNode,
packageLegacyEntrypoints,
packageMedia,
gulp.series(packageLocales, packageUMDBundle),
packageJSON,
packageReadme,
packageDTS)
);
module.exports = {
// Main sequence targets. Each should invoke any immediate prerequisite(s).
cleanReleaseDir: cleanReleaseDir,
package: package,
};