build: Refactor gulpfiles from CJS to ESM (#9149)

* refactor(build): Rename "package" gulp task (but not npm script) to "pack"

  This is to avoid an issue due to "package" being a reserved word
  in JavaScript, and therefore not a valid export identifier.

* refactor(build): Convert gulpfile.js from CJS to ESM.

* refactor(build): Convert scripts/gulpfiles/*.js from CJS to ESM

* fix(build): Fix eslint warning for @license tag in gulpfile.mjs

* chore(build): Remove unused imports

* fix(build): Fix incorrect import of gulp-gzip

* fix(build): Fix incorrect sourcemaps import reference
This commit is contained in:
Christopher Allen
2025-06-30 09:32:08 -07:00
committed by GitHub
parent 6a04d0eadb
commit 9424deb06a
14 changed files with 251 additions and 238 deletions

View File

@@ -184,7 +184,7 @@ export default [
files: [ files: [
'eslint.config.mjs', 'eslint.config.mjs',
'.prettierrc.js', '.prettierrc.js',
'gulpfile.js', 'gulpfile.mjs',
'scripts/helpers.js', 'scripts/helpers.js',
'tests/mocha/.mocharc.js', 'tests/mocha/.mocharc.js',
'tests/migration/validate-renamings.mjs', 'tests/migration/validate-renamings.mjs',

View File

@@ -1,54 +0,0 @@
/**
* @license
* Copyright 2018 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Gulp script to build Blockly for Node & NPM.
* Run this script by calling "npm install" in this directory.
*/
/* eslint-env node */
const gulp = require('gulp');
const buildTasks = require('./scripts/gulpfiles/build_tasks');
const packageTasks = require('./scripts/gulpfiles/package_tasks');
const gitTasks = require('./scripts/gulpfiles/git_tasks');
const appengineTasks = require('./scripts/gulpfiles/appengine_tasks');
const releaseTasks = require('./scripts/gulpfiles/release_tasks');
const docsTasks = require('./scripts/gulpfiles/docs_tasks');
const testTasks = require('./scripts/gulpfiles/test_tasks');
module.exports = {
// Default target if gulp invoked without specifying.
default: buildTasks.build,
// Main sequence targets. They already invoke prerequisites.
langfiles: buildTasks.langfiles, // Build build/msg/*.js from msg/json/*.
tsc: buildTasks.tsc,
deps: buildTasks.deps,
minify: buildTasks.minify,
build: buildTasks.build,
package: packageTasks.package,
publish: releaseTasks.publish,
publishBeta: releaseTasks.publishBeta,
prepareDemos: appengineTasks.prepareDemos,
deployDemos: appengineTasks.deployDemos,
deployDemosBeta: appengineTasks.deployDemosBeta,
gitUpdateGithubPages: gitTasks.updateGithubPages,
// Manually-invokable targets, with prerequisites where required.
messages: buildTasks.messages, // Generate msg/json/en.json et al.
clean: gulp.parallel(buildTasks.cleanBuildDir, packageTasks.cleanReleaseDir),
test: testTasks.test,
testGenerators: testTasks.generators,
buildAdvancedCompilationTest: buildTasks.buildAdvancedCompilationTest,
gitCreateRC: gitTasks.createRC,
docs: docsTasks.docs,
// Legacy targets, to be deleted.
recompile: releaseTasks.recompile,
gitSyncDevelop: gitTasks.syncDevelop,
gitSyncMaster: gitTasks.syncMaster,
};

95
gulpfile.mjs Normal file
View File

@@ -0,0 +1,95 @@
/**
* @license
* Copyright 2018 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Gulp script to build Blockly for Node & NPM.
* Run this script by calling "npm install" in this directory.
*/
/* eslint-env node */
// Needed to prevent prettier from munging exports order, due to
// https://github.com/simonhaenisch/prettier-plugin-organize-imports/issues/146
// - but has the unfortunate side effect of suppressing ordering of
// imports too:
//
// organize-imports-ignore
import {parallel} from 'gulp';
import {
deployDemos,
deployDemosBeta,
prepareDemos,
} from './scripts/gulpfiles/appengine_tasks.mjs';
import {
build,
buildAdvancedCompilationTest,
cleanBuildDir,
langfiles,
messages,
minify,
tsc,
} from './scripts/gulpfiles/build_tasks.mjs';
import {docs} from './scripts/gulpfiles/docs_tasks.mjs';
import {
createRC,
syncDevelop,
syncMaster,
updateGithubPages,
} from './scripts/gulpfiles/git_tasks.mjs';
import {cleanReleaseDir, pack} from './scripts/gulpfiles/package_tasks.mjs';
import {
publish,
publishBeta,
recompile,
} from './scripts/gulpfiles/release_tasks.mjs';
import {generators, test} from './scripts/gulpfiles/test_tasks.mjs';
const clean = parallel(cleanBuildDir, cleanReleaseDir);
// Default target if gulp invoked without specifying.
export default build;
// Main sequence targets. They already invoke prerequisites. Listed
// in typical order of invocation, and strictly listing prerequisites
// before dependants.
//
// prettier-ignore
export {
langfiles,
tsc,
minify,
build,
pack, // Formerly package.
publishBeta,
publish,
prepareDemos,
deployDemosBeta,
deployDemos,
updateGithubPages as gitUpdateGithubPages,
}
// Manually-invokable targets that also invoke prerequisites where
// required.
//
// prettier-ignore
export {
messages, // Generate msg/json/en.json et al.
clean,
test,
generators as testGenerators,
buildAdvancedCompilationTest,
createRC as gitCreateRC,
docs,
}
// Legacy targets, to be deleted.
//
// prettier-ignore
export {
recompile,
syncDevelop as gitSyncDevelop,
syncMaster as gitSyncMaster,
}

View File

@@ -33,7 +33,7 @@
"lint:fix": "eslint . --fix", "lint:fix": "eslint . --fix",
"langfiles": "gulp langfiles", "langfiles": "gulp langfiles",
"minify": "gulp minify", "minify": "gulp minify",
"package": "gulp package", "package": "gulp pack",
"postinstall": "patch-package", "postinstall": "patch-package",
"prepareDemos": "gulp prepareDemos", "prepareDemos": "gulp prepareDemos",
"publish": "npm ci && gulp publish", "publish": "npm ci && gulp publish",

View File

@@ -8,16 +8,16 @@
* @fileoverview Gulp script to deploy Blockly demos on appengine. * @fileoverview Gulp script to deploy Blockly demos on appengine.
*/ */
const gulp = require('gulp'); import * as gulp from 'gulp';
const fs = require('fs'); import * as fs from 'fs';
const path = require('path'); import * as path from 'path';
const execSync = require('child_process').execSync; import {execSync} from 'child_process';
const buildTasks = require('./build_tasks.js'); import * as buildTasks from './build_tasks.mjs';
const packageTasks = require('./package_tasks.js'); import {getPackageJson} from './helper_tasks.mjs';
const {rimraf} = require('rimraf'); import * as packageTasks from './package_tasks.mjs';
import {rimraf} from 'rimraf';
const packageJson = require('../../package.json');
const demoTmpDir = '../_deploy'; const demoTmpDir = '../_deploy';
const demoStaticTmpDir = '../_deploy/static'; const demoStaticTmpDir = '../_deploy/static';
@@ -123,7 +123,7 @@ function deployToAndClean(demoVersion) {
*/ */
function getDemosVersion() { function getDemosVersion() {
// Replace all '.' with '-' e.g. 9-3-3-beta-2 // Replace all '.' with '-' e.g. 9-3-3-beta-2
return packageJson.version.replace(/\./g, '-'); return getPackageJson().version.replace(/\./g, '-');
} }
/** /**
@@ -162,7 +162,7 @@ function deployBetaAndClean(done) {
* *
* Prerequisites (invoked): clean, build * Prerequisites (invoked): clean, build
*/ */
const prepareDemos = gulp.series( export const prepareDemos = gulp.series(
prepareDeployDir, prepareDeployDir,
gulp.parallel( gulp.parallel(
gulp.series( gulp.series(
@@ -180,16 +180,9 @@ const prepareDemos = gulp.series(
/** /**
* Deploys demos. * Deploys demos.
*/ */
const deployDemos = gulp.series(prepareDemos, deployAndClean); export const deployDemos = gulp.series(prepareDemos, deployAndClean);
/** /**
* Deploys beta version of demos (version appended with -beta). * Deploys beta version of demos (version appended with -beta).
*/ */
const deployDemosBeta = gulp.series(prepareDemos, deployBetaAndClean); export const deployDemosBeta = gulp.series(prepareDemos, deployBetaAndClean);
module.exports = {
// Main sequence targets. Each should invoke any immediate prerequisite(s).
deployDemos: deployDemos,
deployDemosBeta: deployDemosBeta,
prepareDemos: prepareDemos
};

View File

@@ -8,25 +8,32 @@
* @fileoverview Gulp script to build Blockly for Node & NPM. * @fileoverview Gulp script to build Blockly for Node & NPM.
*/ */
const gulp = require('gulp'); import * as gulp from 'gulp';
gulp.replace = require('gulp-replace'); import replace from 'gulp-replace';
gulp.rename = require('gulp-rename'); import rename from 'gulp-rename';
gulp.sourcemaps = require('gulp-sourcemaps'); import sourcemaps from 'gulp-sourcemaps';
const path = require('path'); import * as path from 'path';
const fs = require('fs'); import * as fs from 'fs';
const fsPromises = require('fs/promises'); import * as fsPromises from 'fs/promises';
const {exec, execSync} = require('child_process'); import {exec, execSync} from 'child_process';
const {globSync} = require('glob'); import {globSync} from 'glob';
const closureCompiler = require('google-closure-compiler').gulp(); // For v20250609.0.0 and later:
const argv = require('yargs').argv; // import {gulp as closureCompiler} from 'google-closure-compiler';
const {rimraf} = require('rimraf'); import ClosureCompiler from 'google-closure-compiler';
import yargs from 'yargs';
import {hideBin} from 'yargs/helpers';
import {rimraf} from 'rimraf';
const {BUILD_DIR, LANG_BUILD_DIR, RELEASE_DIR, TSC_OUTPUT_DIR, TYPINGS_BUILD_DIR} = require('./config'); import {BUILD_DIR, LANG_BUILD_DIR, RELEASE_DIR, TSC_OUTPUT_DIR, TYPINGS_BUILD_DIR} from './config.mjs';
const {getPackageJson} = require('./helper_tasks'); import {getPackageJson} from './helper_tasks.mjs';
const {posixPath, quote} = require('../helpers'); import {posixPath, quote} from '../helpers.js';
const closureCompiler = ClosureCompiler.gulp();
const argv = yargs(hideBin(process.argv)).parse();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Build // // Build //
@@ -182,7 +189,7 @@ function stripApacheLicense() {
// Closure Compiler preserves dozens of Apache licences in the Blockly code. // Closure Compiler preserves dozens of Apache licences in the Blockly code.
// Remove these if they belong to Google or MIT. // Remove these if they belong to Google or MIT.
// MIT's permission to do this is logged in Blockly issue #2412. // MIT's permission to do this is logged in Blockly issue #2412.
return gulp.replace(new RegExp(licenseRegex, 'g'), '\n\n\n\n'); return replace(new RegExp(licenseRegex, 'g'), '\n\n\n\n');
// Replace with the same number of lines so that source-maps are not affected. // Replace with the same number of lines so that source-maps are not affected.
} }
@@ -306,7 +313,7 @@ const JSCOMP_OFF = [
* Builds Blockly as a JS program, by running tsc on all the files in * Builds Blockly as a JS program, by running tsc on all the files in
* the core directory. * the core directory.
*/ */
function buildJavaScript(done) { export function tsc(done) {
execSync( execSync(
`tsc -outDir "${TSC_OUTPUT_DIR}" -declarationDir "${TYPINGS_BUILD_DIR}"`, `tsc -outDir "${TSC_OUTPUT_DIR}" -declarationDir "${TYPINGS_BUILD_DIR}"`,
{stdio: 'inherit'}); {stdio: 'inherit'});
@@ -318,7 +325,7 @@ function buildJavaScript(done) {
* This task regenerates msg/json/en.js and msg/json/qqq.js from * This task regenerates msg/json/en.js and msg/json/qqq.js from
* msg/messages.js. * msg/messages.js.
*/ */
function generateMessages(done) { export function messages(done) {
// Run js_to_json.py // Run js_to_json.py
const jsToJsonCmd = `${PYTHON} scripts/i18n/js_to_json.py \ const jsToJsonCmd = `${PYTHON} scripts/i18n/js_to_json.py \
--input_file ${path.join('msg', 'messages.js')} \ --input_file ${path.join('msg', 'messages.js')} \
@@ -573,10 +580,10 @@ function buildCompiled() {
// Fire up compilation pipline. // Fire up compilation pipline.
return gulp.src(chunkOptions.js, {base: './'}) return gulp.src(chunkOptions.js, {base: './'})
.pipe(stripApacheLicense()) .pipe(stripApacheLicense())
.pipe(gulp.sourcemaps.init()) .pipe(sourcemaps.init())
.pipe(compile(options)) .pipe(compile(options))
.pipe(gulp.rename({suffix: COMPILED_SUFFIX})) .pipe(rename({suffix: COMPILED_SUFFIX}))
.pipe(gulp.sourcemaps.write('.')) .pipe(sourcemaps.write('.'))
.pipe(gulp.dest(RELEASE_DIR)); .pipe(gulp.dest(RELEASE_DIR));
} }
@@ -668,7 +675,7 @@ async function buildLangfileShims() {
// (We have to do it this way because messages.js is a script and // (We have to do it this way because messages.js is a script and
// not a CJS module with exports.) // not a CJS module with exports.)
globalThis.Blockly = {Msg: {}}; globalThis.Blockly = {Msg: {}};
require('../../msg/messages.js'); await import('../../msg/messages.js');
const exportedNames = Object.keys(globalThis.Blockly.Msg); const exportedNames = Object.keys(globalThis.Blockly.Msg);
delete globalThis.Blockly; delete globalThis.Blockly;
@@ -689,12 +696,14 @@ ${exportedNames.map((name) => ` ${name},`).join('\n')}
} }
/** /**
* This task builds Blockly core, blocks and generators together and uses * This task uses Closure Compiler's ADVANCED_COMPILATION mode to
* Closure Compiler's ADVANCED_COMPILATION mode. * compile together Blockly core, blocks and generators with a simple
* test app; the purpose is to verify that Blockly is compatible with
* the ADVANCED_COMPILATION mode.
* *
* Prerequisite: buildJavaScript. * Prerequisite: buildJavaScript.
*/ */
function buildAdvancedCompilationTest() { function compileAdvancedCompilationTest() {
// If main_compressed.js exists (from a previous run) delete it so that // If main_compressed.js exists (from a previous run) delete it so that
// a later browser-based test won't check it should the compile fail. // a later browser-based test won't check it should the compile fail.
try { try {
@@ -718,9 +727,9 @@ function buildAdvancedCompilationTest() {
}; };
return gulp.src(srcs, {base: './'}) return gulp.src(srcs, {base: './'})
.pipe(stripApacheLicense()) .pipe(stripApacheLicense())
.pipe(gulp.sourcemaps.init()) .pipe(sourcemaps.init())
.pipe(compile(options)) .pipe(compile(options))
.pipe(gulp.sourcemaps.write( .pipe(sourcemaps.write(
'.', {includeContent: false, sourceRoot: '../../'})) '.', {includeContent: false, sourceRoot: '../../'}))
.pipe(gulp.dest('./tests/compile/')); .pipe(gulp.dest('./tests/compile/'));
} }
@@ -728,7 +737,7 @@ function buildAdvancedCompilationTest() {
/** /**
* This task cleans the build directory (by deleting it). * This task cleans the build directory (by deleting it).
*/ */
function cleanBuildDir() { export function cleanBuildDir() {
// Sanity check. // Sanity check.
if (BUILD_DIR === '.' || BUILD_DIR === '/') { if (BUILD_DIR === '.' || BUILD_DIR === '/') {
return Promise.reject(`Refusing to rm -rf ${BUILD_DIR}`); return Promise.reject(`Refusing to rm -rf ${BUILD_DIR}`);
@@ -737,16 +746,13 @@ function cleanBuildDir() {
} }
// Main sequence targets. Each should invoke any immediate prerequisite(s). // Main sequence targets. Each should invoke any immediate prerequisite(s).
exports.cleanBuildDir = cleanBuildDir; // function cleanBuildDir, above
exports.langfiles = gulp.parallel(buildLangfiles, buildLangfileShims); export const langfiles = gulp.parallel(buildLangfiles, buildLangfileShims);
exports.tsc = buildJavaScript; export const minify = gulp.series(tsc, buildCompiled, buildShims);
exports.minify = gulp.series(exports.tsc, buildCompiled, buildShims); // function tsc, above
exports.build = gulp.parallel(exports.minify, exports.langfiles); export const build = gulp.parallel(minify, langfiles);
// Manually-invokable targets, with prerequisites where required. // Manually-invokable targets, with prerequisites where required.
exports.messages = generateMessages; // Generate msg/json/en.json et al. // function messages, above
exports.buildAdvancedCompilationTest = export const buildAdvancedCompilationTest =
gulp.series(exports.tsc, buildAdvancedCompilationTest); gulp.series(tsc, compileAdvancedCompilationTest);
// Targets intended only for invocation by scripts; may omit prerequisites.
exports.onlyBuildAdvancedCompilationTest = buildAdvancedCompilationTest;

View File

@@ -8,7 +8,7 @@
* @fileoverview Common configuration for Gulp scripts. * @fileoverview Common configuration for Gulp scripts.
*/ */
const path = require('path'); import * as path from 'path';
// Paths are all relative to the repository root. Do not include // Paths are all relative to the repository root. Do not include
// trailing slash. // trailing slash.
@@ -21,21 +21,21 @@ const path = require('path');
// - tests/scripts/update_metadata.sh // - tests/scripts/update_metadata.sh
// Directory to write compiled output to. // Directory to write compiled output to.
exports.BUILD_DIR = 'build'; export const BUILD_DIR = 'build';
// Directory to write typings output to. // Directory to write typings output to.
exports.TYPINGS_BUILD_DIR = path.join(exports.BUILD_DIR, 'declarations'); export const TYPINGS_BUILD_DIR = path.join(BUILD_DIR, 'declarations');
// Directory to write langfile output to. // Directory to write langfile output to.
exports.LANG_BUILD_DIR = path.join(exports.BUILD_DIR, 'msg'); export const LANG_BUILD_DIR = path.join(BUILD_DIR, 'msg');
// Directory where typescript compiler output can be found. // Directory where typescript compiler output can be found.
// Matches the value in tsconfig.json: outDir // Matches the value in tsconfig.json: outDir
exports.TSC_OUTPUT_DIR = path.join(exports.BUILD_DIR, 'src'); export const TSC_OUTPUT_DIR = path.join(BUILD_DIR, 'src');
// Directory for files generated by compiling test code. // Directory for files generated by compiling test code.
exports.TEST_TSC_OUTPUT_DIR = path.join(exports.BUILD_DIR, 'tests'); export const TEST_TSC_OUTPUT_DIR = path.join(BUILD_DIR, 'tests');
// Directory in which to assemble (and from which to publish) the // Directory in which to assemble (and from which to publish) the
// blockly npm package. // blockly npm package.
exports.RELEASE_DIR = 'dist'; export const RELEASE_DIR = 'dist';

View File

@@ -1,9 +1,9 @@
const {execSync} = require('child_process'); import {execSync} from 'child_process';
const {Extractor} = require('markdown-tables-to-json'); import {Extractor} from 'markdown-tables-to-json';
const fs = require('fs'); import * as fs from 'fs';
const gulp = require('gulp'); import * as gulp from 'gulp';
const header = require('gulp-header'); import * as header from 'gulp-header';
const replace = require('gulp-replace'); import * as replace from 'gulp-replace';
const DOCS_DIR = 'docs'; const DOCS_DIR = 'docs';
@@ -140,8 +140,7 @@ const createToc = function(done) {
done(); done();
} }
const docs = gulp.series( export const docs = gulp.series(
generateApiJson, removeRenames, generateDocs, generateApiJson, removeRenames, generateDocs,
gulp.parallel(prependBook, createToc)); gulp.parallel(prependBook, createToc));
module.exports = {docs};

View File

@@ -8,11 +8,11 @@
* @fileoverview Git-related gulp tasks for Blockly. * @fileoverview Git-related gulp tasks for Blockly.
*/ */
const gulp = require('gulp'); import * as gulp from 'gulp';
const execSync = require('child_process').execSync; import {execSync} from 'child_process';
const buildTasks = require('./build_tasks'); import * as buildTasks from './build_tasks.mjs';
const packageTasks = require('./package_tasks'); import * as packageTasks from './package_tasks.mjs';
const UPSTREAM_URL = 'https://github.com/google/blockly.git'; const UPSTREAM_URL = 'https://github.com/google/blockly.git';
@@ -63,7 +63,7 @@ function syncBranch(branchName) {
* Stash current state, check out develop, and sync with * Stash current state, check out develop, and sync with
* google/blockly. * google/blockly.
*/ */
function syncDevelop() { export function syncDevelop() {
return syncBranch('develop'); return syncBranch('develop');
}; };
@@ -71,7 +71,7 @@ function syncDevelop() {
* Stash current state, check out master, and sync with * Stash current state, check out master, and sync with
* google/blockly. * google/blockly.
*/ */
function syncMaster() { export function syncMaster() {
return syncBranch('master'); return syncBranch('master');
}; };
@@ -111,7 +111,7 @@ function checkoutBranch(branchName) {
* Create and push an RC branch. * Create and push an RC branch.
* Note that this pushes to google/blockly. * Note that this pushes to google/blockly.
*/ */
const createRC = gulp.series( export const createRC = gulp.series(
syncDevelop(), syncDevelop(),
function(done) { function(done) {
const branchName = getRCBranchName(); const branchName = getRCBranchName();
@@ -122,7 +122,7 @@ const createRC = gulp.series(
); );
/** Create the rebuild branch. */ /** Create the rebuild branch. */
function createRebuildBranch(done) { export function createRebuildBranch(done) {
const branchName = getRebuildBranchName(); const branchName = getRebuildBranchName();
console.log(`make-rebuild-branch: creating branch ${branchName}`); console.log(`make-rebuild-branch: creating branch ${branchName}`);
execSync(`git switch -C ${branchName}`, { stdio: 'inherit' }); execSync(`git switch -C ${branchName}`, { stdio: 'inherit' });
@@ -130,7 +130,7 @@ function createRebuildBranch(done) {
} }
/** Push the rebuild branch to origin. */ /** Push the rebuild branch to origin. */
function pushRebuildBranch(done) { export function pushRebuildBranch(done) {
console.log('push-rebuild-branch: committing rebuild'); console.log('push-rebuild-branch: committing rebuild');
execSync('git commit -am "Rebuild"', { stdio: 'inherit' }); execSync('git commit -am "Rebuild"', { stdio: 'inherit' });
const branchName = getRebuildBranchName(); const branchName = getRebuildBranchName();
@@ -145,7 +145,7 @@ function pushRebuildBranch(done) {
* *
* Prerequisites (invoked): clean, build. * Prerequisites (invoked): clean, build.
*/ */
const updateGithubPages = gulp.series( export const updateGithubPages = gulp.series(
function(done) { function(done) {
execSync('git stash save -m "Stash for sync"', { stdio: 'inherit' }); execSync('git stash save -m "Stash for sync"', { stdio: 'inherit' });
execSync('git switch -C gh-pages', { stdio: 'inherit' }); execSync('git switch -C gh-pages', { stdio: 'inherit' });
@@ -165,17 +165,3 @@ const updateGithubPages = gulp.series(
done(); done();
} }
); );
module.exports = {
// Main sequence targets. Each should invoke any immediate prerequisite(s).
updateGithubPages,
// Manually-invokable targets that invoke prerequisites.
createRC,
// Legacy script-only targets, to be deleted.
syncDevelop,
syncMaster,
createRebuildBranch,
pushRebuildBranch,
};

View File

@@ -1,19 +0,0 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Any gulp helper functions.
*/
// Clears the require cache to ensure the package.json is up to date.
function getPackageJson() {
delete require.cache[require.resolve('../../package.json')]
return require('../../package.json');
}
module.exports = {
getPackageJson: getPackageJson
}

View File

@@ -0,0 +1,25 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Any gulp helper functions.
*/
import Module from "node:module";
const require = Module.createRequire(import.meta.url);
/**
* Load and return the contents of package.json.
*
* Uses require() rather than import, and clears the require cache, to
* ensure the loaded package.json data is up to date.
*/
export function getPackageJson() {
delete require.cache[require.resolve('../../package.json')];
return require('../../package.json');
}

View File

@@ -8,20 +8,17 @@
* @fileoverview Gulp tasks to package Blockly for distribution on NPM. * @fileoverview Gulp tasks to package Blockly for distribution on NPM.
*/ */
const gulp = require('gulp'); import * as gulp from 'gulp';
gulp.concat = require('gulp-concat'); import concat from 'gulp-concat';
gulp.replace = require('gulp-replace'); import replace from 'gulp-replace';
gulp.rename = require('gulp-rename'); import umd from 'gulp-umd';
gulp.insert = require('gulp-insert');
gulp.umd = require('gulp-umd');
gulp.replace = require('gulp-replace');
const path = require('path'); import * as path from 'path';
const fs = require('fs'); import * as fs from 'fs';
const {rimraf} = require('rimraf'); import {rimraf} from 'rimraf';
const build = require('./build_tasks'); import * as build from './build_tasks.mjs';
const {getPackageJson} = require('./helper_tasks'); import {getPackageJson} from './helper_tasks.mjs';
const {BUILD_DIR, LANG_BUILD_DIR, RELEASE_DIR, TYPINGS_BUILD_DIR} = require('./config'); import {BUILD_DIR, LANG_BUILD_DIR, RELEASE_DIR, TYPINGS_BUILD_DIR} from './config.mjs';
// Path to template files for gulp-umd. // Path to template files for gulp-umd.
const TEMPLATE_DIR = 'scripts/package/templates'; const TEMPLATE_DIR = 'scripts/package/templates';
@@ -32,7 +29,7 @@ const TEMPLATE_DIR = 'scripts/package/templates';
* @param {Array<Object>} dependencies An array of dependencies to inject. * @param {Array<Object>} dependencies An array of dependencies to inject.
*/ */
function packageUMD(namespace, dependencies, template = 'umd.template') { function packageUMD(namespace, dependencies, template = 'umd.template') {
return gulp.umd({ return umd({
dependencies: function () { return dependencies; }, dependencies: function () { return dependencies; },
namespace: function () { return namespace; }, namespace: function () { return namespace; },
exports: function () { return namespace; }, exports: function () { return namespace; },
@@ -88,7 +85,7 @@ function packageCoreNode() {
function packageLocales() { function packageLocales() {
// Remove references to goog.provide and goog.require. // Remove references to goog.provide and goog.require.
return gulp.src(`${LANG_BUILD_DIR}/*.js`) return gulp.src(`${LANG_BUILD_DIR}/*.js`)
.pipe(gulp.replace(/goog\.[^\n]+/g, '')) .pipe(replace(/goog\.[^\n]+/g, ''))
.pipe(packageUMD('Blockly.Msg', [], 'umd-msg.template')) .pipe(packageUMD('Blockly.Msg', [], 'umd-msg.template'))
.pipe(gulp.dest(`${RELEASE_DIR}/msg`)); .pipe(gulp.dest(`${RELEASE_DIR}/msg`));
}; };
@@ -107,7 +104,7 @@ function packageUMDBundle() {
`${RELEASE_DIR}/javascript_compressed.js`, `${RELEASE_DIR}/javascript_compressed.js`,
]; ];
return gulp.src(srcs) return gulp.src(srcs)
.pipe(gulp.concat('blockly.min.js')) .pipe(concat('blockly.min.js'))
.pipe(gulp.dest(`${RELEASE_DIR}`)); .pipe(gulp.dest(`${RELEASE_DIR}`));
}; };
@@ -140,7 +137,7 @@ function packageUMDBundle() {
* @param {Function} done Callback to call when done. * @param {Function} done Callback to call when done.
*/ */
function packageLegacyEntrypoints(done) { function packageLegacyEntrypoints(done) {
for (entrypoint of [ for (const entrypoint of [
'core', 'blocks', 'dart', 'javascript', 'lua', 'php', 'python' 'core', 'blocks', 'dart', 'javascript', 'lua', 'php', 'python'
]) { ]) {
const bundle = const bundle =
@@ -218,14 +215,14 @@ function packageDTS() {
.pipe(gulp.src(`${TYPINGS_BUILD_DIR}/**/*.d.ts`, {ignore: [ .pipe(gulp.src(`${TYPINGS_BUILD_DIR}/**/*.d.ts`, {ignore: [
`${TYPINGS_BUILD_DIR}/blocks/**/*`, `${TYPINGS_BUILD_DIR}/blocks/**/*`,
]})) ]}))
.pipe(gulp.replace('AnyDuringMigration', 'any')) .pipe(replace('AnyDuringMigration', 'any'))
.pipe(gulp.dest(RELEASE_DIR)); .pipe(gulp.dest(RELEASE_DIR));
}; };
/** /**
* This task cleans the release directory (by deleting it). * This task cleans the release directory (by deleting it).
*/ */
function cleanReleaseDir() { export function cleanReleaseDir() {
// Sanity check. // Sanity check.
if (RELEASE_DIR === '.' || RELEASE_DIR === '/') { if (RELEASE_DIR === '.' || RELEASE_DIR === '/') {
return Promise.reject(`Refusing to rm -rf ${RELEASE_DIR}`); return Promise.reject(`Refusing to rm -rf ${RELEASE_DIR}`);
@@ -237,9 +234,13 @@ function cleanReleaseDir() {
* This task prepares the files to be included in the NPM by copying * This task prepares the files to be included in the NPM by copying
* them into the release directory. * them into the release directory.
* *
* This task was formerly called "package" but was renamed in
* preparation for porting gulpfiles to ESM because "package" is a
* reserved word.
*
* Prerequisite: build. * Prerequisite: build.
*/ */
const package = gulp.series( export const pack = gulp.series(
gulp.parallel( gulp.parallel(
build.cleanBuildDir, build.cleanBuildDir,
cleanReleaseDir), cleanReleaseDir),
@@ -254,9 +255,3 @@ const package = gulp.series(
packageReadme, packageReadme,
packageDTS) packageDTS)
); );
module.exports = {
// Main sequence targets. Each should invoke any immediate prerequisite(s).
cleanReleaseDir: cleanReleaseDir,
package: package,
};

View File

@@ -8,15 +8,15 @@
* @fileoverview Gulp scripts for releasing Blockly. * @fileoverview Gulp scripts for releasing Blockly.
*/ */
const execSync = require('child_process').execSync; import {execSync} from 'child_process';
const fs = require('fs'); import * as fs from 'fs';
const gulp = require('gulp'); import * as gulp from 'gulp';
const readlineSync = require('readline-sync'); import * as readlineSync from 'readline-sync';
const gitTasks = require('./git_tasks'); import * as gitTasks from './git_tasks.mjs';
const packageTasks = require('./package_tasks'); import * as packageTasks from './package_tasks.mjs';
const {getPackageJson} = require('./helper_tasks'); import {getPackageJson} from './helper_tasks.mjs';
const {RELEASE_DIR} = require('./config'); import {RELEASE_DIR} from './config.mjs';
// Gets the current major version. // Gets the current major version.
@@ -147,17 +147,17 @@ function updateBetaVersion(done) {
} }
// Rebuild, package and publish to npm. // Rebuild, package and publish to npm.
const publish = gulp.series( export const publish = gulp.series(
packageTasks.package, // Does clean + build. packageTasks.pack, // Does clean + build.
checkBranch, checkBranch,
checkReleaseDir, checkReleaseDir,
loginAndPublish loginAndPublish
); );
// Rebuild, package and publish a beta version of Blockly. // Rebuild, package and publish a beta version of Blockly.
const publishBeta = gulp.series( export const publishBeta = gulp.series(
updateBetaVersion, updateBetaVersion,
packageTasks.package, // Does clean + build. packageTasks.pack, // Does clean + build.
checkBranch, checkBranch,
checkReleaseDir, checkReleaseDir,
loginAndPublishBeta loginAndPublishBeta
@@ -165,19 +165,10 @@ const publishBeta = gulp.series(
// Switch to a new branch, update the version number, build Blockly // Switch to a new branch, update the version number, build Blockly
// and check in the resulting built files. // and check in the resulting built files.
const recompileDevelop = gulp.series( export const recompile = gulp.series(
gitTasks.syncDevelop(), gitTasks.syncDevelop(),
gitTasks.createRebuildBranch, gitTasks.createRebuildBranch,
updateVersionPrompt, updateVersionPrompt,
packageTasks.package, // Does clean + build. packageTasks.pack, // Does clean + build.
gitTasks.pushRebuildBranch gitTasks.pushRebuildBranch
); );
module.exports = {
// Main sequence targets. Each should invoke any immediate prerequisite(s).
publishBeta,
publish,
// Legacy target, to be deleted.
recompile: recompileDevelop,
};

View File

@@ -9,19 +9,19 @@
*/ */
/* eslint-env node */ /* eslint-env node */
const asyncDone = require('async-done'); import asyncDone from 'async-done';
const gulp = require('gulp'); import * as gulp from 'gulp';
const gzip = require('gulp-gzip'); import gzip from 'gulp-gzip';
const fs = require('fs'); import * as fs from 'fs';
const path = require('path'); import * as path from 'path';
const {execSync} = require('child_process'); import {execSync} from 'child_process';
const {rimraf} = require('rimraf'); import {rimraf} from 'rimraf';
const {RELEASE_DIR, TEST_TSC_OUTPUT_DIR} = require('./config'); import {RELEASE_DIR, TEST_TSC_OUTPUT_DIR} from './config.mjs';
const {runMochaTestsInBrowser} = require('../../tests/mocha/webdriver.js'); import {runMochaTestsInBrowser} from '../../tests/mocha/webdriver.js';
const {runGeneratorsInBrowser} = require('../../tests/generators/webdriver.js'); import {runGeneratorsInBrowser} from '../../tests/generators/webdriver.js';
const {runCompileCheckInBrowser} = require('../../tests/compile/webdriver.js'); import {runCompileCheckInBrowser} from '../../tests/compile/webdriver.js';
const OUTPUT_DIR = 'build/generators'; const OUTPUT_DIR = 'build/generators';
const GOLDEN_DIR = 'tests/generators/golden'; const GOLDEN_DIR = 'tests/generators/golden';
@@ -321,7 +321,7 @@ function checkResult(suffix) {
* Run generator tests inside a browser and check the results. * Run generator tests inside a browser and check the results.
* @return {Promise} Asynchronous result. * @return {Promise} Asynchronous result.
*/ */
async function generators() { export async function generators() {
return runTestTask('generators', async () => { return runTestTask('generators', async () => {
// Clean up. // Clean up.
rimraf.sync(OUTPUT_DIR); rimraf.sync(OUTPUT_DIR);
@@ -396,10 +396,6 @@ const tasks = [
advancedCompileInBrowser advancedCompileInBrowser
]; ];
const test = gulp.series(...tasks, reportTestResult); export const test = gulp.series(...tasks, reportTestResult);
module.exports = {
test,
generators,
};