mirror of
https://github.com/google/blockly.git
synced 2026-01-09 10:00:09 +01:00
* Move fields and renderers into their own entry point so folks are able to be more selective about which fields and renderers they include in their bundle.
855 lines
27 KiB
JavaScript
855 lines
27 KiB
JavaScript
/**
|
|
* @license
|
|
* Visual Blocks Editor
|
|
*
|
|
* Copyright 2018 Google Inc.
|
|
* https://developers.google.com/blockly/
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/**
|
|
* @fileoverview Gulp script to build Blockly for Node & NPM.
|
|
* Run this script by calling "npm install" in this directory.
|
|
*/
|
|
|
|
var gulp = require('gulp');
|
|
gulp.shell = require('gulp-shell');
|
|
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');
|
|
|
|
var path = require('path');
|
|
var fs = require('fs');
|
|
var rimraf = require('rimraf');
|
|
var execSync = require('child_process').execSync;
|
|
|
|
var closureCompiler = require('google-closure-compiler').gulp();
|
|
var packageJson = require('./package.json');
|
|
var argv = require('yargs').argv;
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Build //
|
|
////////////////////////////////////////////////////////////
|
|
|
|
const licenseRegex = `\\/\\*\\*
|
|
\\* @license
|
|
\\* [\\w: ]+
|
|
\\*
|
|
\\* (Copyright \\d+ (Google Inc.|Massachusetts Institute of Technology))
|
|
\\* (https://developers.google.com/blockly/|All rights reserved.)
|
|
\\*
|
|
\\* Licensed under the Apache License, Version 2.0 \\(the "License"\\);
|
|
\\* you may not use this file except in compliance with the License.
|
|
\\* You may obtain a copy of the License at
|
|
\\*
|
|
\\* http://www.apache.org/licenses/LICENSE-2.0
|
|
\\*
|
|
\\* Unless required by applicable law or agreed to in writing, software
|
|
\\* distributed under the License is distributed on an "AS IS" BASIS,
|
|
\\* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
\\* See the License for the specific language governing permissions and
|
|
\\* limitations under the License.
|
|
\\*\\/`;
|
|
|
|
/**
|
|
* Helper method for stripping the Google's and MIT's Apache Licenses.
|
|
*/
|
|
function stripApacheLicense() {
|
|
// Strip out Google's and MIT's Apache licences.
|
|
// Closure Compiler preserves dozens of Apache licences in the Blockly code.
|
|
// Remove these if they belong to Google or MIT.
|
|
// MIT's permission to do this is logged in Blockly issue #2412.
|
|
return gulp.replace(new RegExp(licenseRegex, "g"), '');
|
|
}
|
|
|
|
/**
|
|
* Helper method for prepending the auto-generated header text.
|
|
*/
|
|
function prependHeader() {
|
|
return gulp.insert.prepend(`// Do not edit this file; automatically generated by gulp.\n`);
|
|
}
|
|
|
|
/**
|
|
* Helper method for calling the Closure compiler.
|
|
* @param {*} compilerOptions
|
|
* @param {boolean=} opt_verbose Optional option for verbose logging
|
|
*/
|
|
function compile(compilerOptions, opt_verbose) {
|
|
if (!compilerOptions) compilerOptions = {};
|
|
compilerOptions.compilation_level = 'SIMPLE_OPTIMIZATIONS';
|
|
compilerOptions.warning_level = opt_verbose ? 'VERBOSE' : 'DEFAULT';
|
|
compilerOptions.language_out = 'ECMASCRIPT5_STRICT';
|
|
compilerOptions.rewrite_polyfills = false;
|
|
compilerOptions.hide_warnings_for = 'node_modules';
|
|
|
|
const platform = ['native', 'java', 'javascript'];
|
|
|
|
return closureCompiler(compilerOptions, { platform });
|
|
}
|
|
|
|
/**
|
|
* This task builds Blockly's core files.
|
|
* blockly_compressed.js
|
|
*/
|
|
gulp.task('build-core', function () {
|
|
const defines = 'Blockly.VERSION="' + packageJson.version + '"';
|
|
return gulp.src([
|
|
'core/**/**/*.js'
|
|
], {base: './'})
|
|
// Directories in Blockly are used to group similar files together
|
|
// but are not used to limit access with @package, instead the
|
|
// method means something is internal to Blockly and not a public
|
|
// API.
|
|
// Flatten all files so they're in the same directory, but ensure that
|
|
// files with the same name don't conflict.
|
|
.pipe(gulp.rename(function (p) {
|
|
var dirname = p.dirname.replace(new RegExp(path.sep, "g"), "-");
|
|
p.dirname = "";
|
|
p.basename = dirname + "-" + p.basename;
|
|
}))
|
|
.pipe(stripApacheLicense())
|
|
.pipe(compile({
|
|
dependency_mode: 'PRUNE',
|
|
entry_point: './core-requires.js',
|
|
js_output_file: 'blockly_compressed.js',
|
|
externs: './externs/svg-externs.js',
|
|
define: defines
|
|
}, argv.verbose))
|
|
.pipe(prependHeader())
|
|
.pipe(gulp.dest('./'));
|
|
});
|
|
|
|
/**
|
|
* This task builds the Blockly's built in blocks.
|
|
* blocks_compressed.js
|
|
*/
|
|
gulp.task('build-blocks', function () {
|
|
const provides = `goog.provide('Blockly');\ngoog.provide('Blockly.Blocks');\n`;
|
|
return gulp.src('blocks/*.js', {base: './'})
|
|
// Add Blockly.Blocks to be compatible with the compiler.
|
|
.pipe(gulp.replace(`goog.provide('Blockly.Constants.Colour');`,
|
|
`${provides}goog.provide('Blockly.Constants.Colour');`))
|
|
.pipe(stripApacheLicense())
|
|
.pipe(compile({
|
|
dependency_mode: 'NONE',
|
|
js_output_file: 'blocks_compressed.js'
|
|
}, argv.verbose))
|
|
.pipe(gulp.replace('\'use strict\';', '\'use strict\';\n\n\n'))
|
|
// Remove Blockly.Blocks to be compatible with Blockly.
|
|
.pipe(gulp.replace('var Blockly={Blocks:{}};', ''))
|
|
.pipe(prependHeader())
|
|
.pipe(gulp.dest('./'));
|
|
});
|
|
|
|
/**
|
|
* A helper method for building a Blockly code generator.
|
|
* @param {string} language Generator language.
|
|
* @param {string} namespace Language namespace.
|
|
*/
|
|
function buildGenerator(language, namespace) {
|
|
var provides = `goog.provide('Blockly.Generator');\ngoog.provide('Blockly.utils.string');\n`;
|
|
return gulp.src([`generators/${language}.js`, `generators/${language}/*.js`], {base: './'})
|
|
.pipe(stripApacheLicense())
|
|
// Add Blockly.Generator and Blockly.utils.string to be compatible with the compiler.
|
|
.pipe(gulp.replace(`goog.provide('Blockly.${namespace}');`,
|
|
`${provides}goog.provide('Blockly.${namespace}');`))
|
|
.pipe(compile({
|
|
dependency_mode: 'NONE',
|
|
js_output_file: `${language}_compressed.js`
|
|
}, argv.verbose))
|
|
.pipe(gulp.replace('\'use strict\';', '\'use strict\';\n\n\n'))
|
|
// Remove Blockly.Generator and Blockly.utils.string to be compatible with Blockly.
|
|
.pipe(gulp.replace('var Blockly={Generator:{},utils:{}};Blockly.utils.string={};', ''))
|
|
.pipe(prependHeader())
|
|
.pipe(gulp.dest('./'));
|
|
};
|
|
|
|
/**
|
|
* This task builds the javascript generator.
|
|
* javascript_compressed.js
|
|
*/
|
|
gulp.task('build-javascript', function() {
|
|
return buildGenerator('javascript', 'JavaScript');
|
|
});
|
|
|
|
/**
|
|
* This task builds the python generator.
|
|
* python_compressed.js
|
|
*/
|
|
gulp.task('build-python', function() {
|
|
return buildGenerator('python', 'Python');
|
|
});
|
|
|
|
/**
|
|
* This task builds the php generator.
|
|
* php_compressed.js
|
|
*/
|
|
gulp.task('build-php', function() {
|
|
return buildGenerator('php', 'PHP');
|
|
});
|
|
|
|
/**
|
|
* This task builds the lua generator.
|
|
* lua_compressed.js
|
|
*/
|
|
gulp.task('build-lua', function() {
|
|
return buildGenerator('lua', 'Lua');
|
|
});
|
|
|
|
/**
|
|
* This task builds the dart generator:
|
|
* dart_compressed.js
|
|
*/
|
|
gulp.task('build-dart', function() {
|
|
return buildGenerator('dart', 'Dart');
|
|
});
|
|
|
|
/**
|
|
* This task builds Blockly's uncompressed file.
|
|
* blockly_uncompressed.js
|
|
*/
|
|
gulp.task('build-uncompressed', function() {
|
|
const header = `// Do not edit this file; automatically generated by build.py.
|
|
'use strict';
|
|
|
|
this.IS_NODE_JS = !!(typeof module !== 'undefined' && module.exports);
|
|
|
|
this.BLOCKLY_DIR = (function(root) {
|
|
if (!root.IS_NODE_JS) {
|
|
// Find name of current directory.
|
|
var scripts = document.getElementsByTagName('script');
|
|
var re = new RegExp('(.+)[\\\/]blockly_(.*)uncompressed\\\.js$');
|
|
for (var i = 0, script; script = scripts[i]; i++) {
|
|
var match = re.exec(script.src);
|
|
if (match) {
|
|
return match[1];
|
|
}
|
|
}
|
|
alert('Could not detect Blockly\\'s directory name.');
|
|
}
|
|
return '';
|
|
})(this);
|
|
|
|
this.BLOCKLY_BOOT = function(root) {
|
|
var dir = '';
|
|
if (root.IS_NODE_JS) {
|
|
dir = 'blockly';
|
|
} else {
|
|
dir = this.BLOCKLY_DIR.match(/[^\\/]+$/)[0];
|
|
}
|
|
// Execute after Closure has loaded.
|
|
`;
|
|
const footer = `
|
|
delete root.BLOCKLY_DIR;
|
|
delete root.BLOCKLY_BOOT;
|
|
delete root.IS_NODE_JS;
|
|
};
|
|
|
|
if (this.IS_NODE_JS) {
|
|
this.BLOCKLY_BOOT(this);
|
|
module.exports = Blockly;
|
|
} else {
|
|
// Delete any existing Closure (e.g. Soy's nogoog_shim).
|
|
document.write('<script>var goog = undefined;</script>');
|
|
// Load fresh Closure Library.
|
|
document.write('<script src="' + this.BLOCKLY_DIR +
|
|
'/closure-library/base.js"></script>');
|
|
document.write('<script>this.BLOCKLY_BOOT(this);</script>');
|
|
}
|
|
`;
|
|
const file = 'blockly_uncompressed.js';
|
|
// Run depswriter.py and which scans the core directory and writes out a ``goog.addDependency`` line for each file.
|
|
const cmd = `python ./node_modules/google-closure-library/closure/bin/build/depswriter.py \
|
|
--root_with_prefix="./core ../core" > ${file}`;
|
|
execSync(cmd, { stdio: 'inherit' });
|
|
|
|
let providesBuilder = `\n// Load Blockly.\n`;
|
|
const provides = new Set();
|
|
const dependencies = fs.readFileSync(file, "utf8");
|
|
const re = /\'(Blockly[^\']*)\'/gi;
|
|
let m;
|
|
while (m = re.exec(dependencies)) {
|
|
provides.add(`goog.require('${m[1]}');`);
|
|
}
|
|
providesBuilder += Array.from(provides).sort().join('\n') + '\n';
|
|
|
|
return gulp.src(file)
|
|
// Remove comments so we're compatible with the build.py script
|
|
.pipe(gulp.replace(/\/\/.*\n/gm, ''))
|
|
// Replace quotes to be compatible with build.py
|
|
.pipe(gulp.replace(/\'(.*\.js)\'/gm, '"$1"'))
|
|
// Find the Blockly directory name and replace it with a JS variable.
|
|
// This allows blockly_uncompressed.js to be compiled on one computer and be
|
|
// used on another, even if the directory name differs.
|
|
.pipe(gulp.replace(/\.\.\/core/gm, `../../" + dir + "/core`))
|
|
.pipe(gulp.insert.wrap(header, providesBuilder + footer))
|
|
.pipe(gulp.dest('./'));
|
|
});
|
|
|
|
/**
|
|
* This task builds all of Blockly:
|
|
* blockly_compressed.js
|
|
* blocks_compressed.js
|
|
* javascript_compressed.js
|
|
* python_compressed.js
|
|
* php_compressed.js
|
|
* lua_compressed.js
|
|
* dart_compressed.js
|
|
*/
|
|
gulp.task('build', gulp.parallel(
|
|
'build-core',
|
|
'build-blocks',
|
|
'build-javascript',
|
|
'build-python',
|
|
'build-php',
|
|
'build-lua',
|
|
'build-dart'
|
|
));
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Node //
|
|
////////////////////////////////////////////////////////////
|
|
|
|
// Concatenates the necessary files to load Blockly in a Node.js VM. Blockly's
|
|
// individual libraries target use in a browser, where globals (via the window
|
|
// objects) are used to share state and APIs. By concatenating all the
|
|
// necessary components into a single file, Blockly can be loaded as a Node.js
|
|
// module.
|
|
//
|
|
// This task builds Node with the assumption that the app needs English blocks
|
|
// and JavaScript code generation. If you need another localization or
|
|
// generator language, just copy and edit the srcs. Only one localization
|
|
// language can be included.
|
|
gulp.task('blockly_node_javascript_en', function() {
|
|
var srcs = [
|
|
'blockly_compressed.js',
|
|
'blocks_compressed.js',
|
|
'javascript_compressed.js',
|
|
'msg/js/en.js'
|
|
];
|
|
// Concatenate the sources, appending the module export at the bottom.
|
|
// Override textToDomDocument, providing Node alternative to DOMParser.
|
|
return gulp.src(srcs)
|
|
.pipe(gulp.concat('blockly_node_javascript_en.js'))
|
|
.pipe(gulp.insert.append(`
|
|
if (typeof DOMParser !== 'function') {
|
|
var JSDOM = require('jsdom').JSDOM;
|
|
var window = (new JSDOM()).window;
|
|
var document = window.document;
|
|
var Element = window.Element;
|
|
Blockly.utils.xml.textToDomDocument = function(text) {
|
|
var jsdom = new JSDOM(text, { contentType: 'text/xml' });
|
|
return jsdom.window.document;
|
|
};
|
|
}
|
|
if (typeof module === 'object') { module.exports = Blockly; }
|
|
if (typeof window === 'object') { window.Blockly = Blockly; }\n`))
|
|
.pipe(gulp.dest('.'));
|
|
});
|
|
|
|
/**
|
|
* Task-builder for the watch function. Currently any change invokes the whole
|
|
* build script. Invoke with "gulp watch".
|
|
*
|
|
* @param {?string=} concatTask Name of the concatenating task for node usage.
|
|
*/
|
|
// TODO: Only run the necessary phases of the build script for a given change.
|
|
function buildWatchTaskFn(concatTask) {
|
|
return function() {
|
|
// Tasks to trigger.
|
|
var tasks = ['build'];
|
|
if (concatTask) {
|
|
tasks.push(concatTask);
|
|
}
|
|
|
|
// Currently any changes invokes the whole build script. (To fix.)
|
|
var srcs = [
|
|
'core/**/*.js', // Blockly core code
|
|
'blocks/*.js', // Block definitions
|
|
'generators/**/*.js', // Code generation
|
|
'msg/messages.js', 'msg/json/*.json' // Localization data
|
|
];
|
|
var options = {
|
|
debounceDelay: 2000 // Milliseconds to delay rebuild.
|
|
};
|
|
gulp.watch(srcs, options, gulp.parallel(tasks));
|
|
};
|
|
}
|
|
|
|
// Watch Blockly files for changes and trigger automatic rebuilds, including
|
|
// the Node-ready blockly_node_javascript_en.js file.
|
|
gulp.task('watch', buildWatchTaskFn('blockly_node_javascript_en'));
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Typings //
|
|
////////////////////////////////////////////////////////////
|
|
|
|
// Generates the TypeScript definition file (d.ts) for Blockly.
|
|
// As well as generating the typings of each of the files under core/ and msg/,
|
|
// the script also pulls in a number of part files from typings/parts.
|
|
// This includes the header (incl License), additional useful interfaces
|
|
// including Blockly Options and Google Closure typings.
|
|
gulp.task('typings', function (cb) {
|
|
const tmpDir = './typings/tmp';
|
|
const blocklySrcs = [
|
|
"core/",
|
|
"core/components",
|
|
"core/components/tree",
|
|
"core/components/menu",
|
|
"core/keyboard_nav",
|
|
"core/renderers/common",
|
|
"core/renderers/measurables",
|
|
"core/theme",
|
|
"core/utils",
|
|
"msg/"
|
|
];
|
|
// Clean directory if exists.
|
|
if (fs.existsSync(tmpDir)) {
|
|
rimraf.sync(tmpDir);
|
|
}
|
|
fs.mkdirSync(tmpDir);
|
|
|
|
// Find all files that will be included in the typings file.
|
|
let files = [];
|
|
blocklySrcs.forEach((src) => {
|
|
files = files.concat(fs.readdirSync(src)
|
|
.filter(fn => fn.endsWith('.js'))
|
|
.map(fn => path.join(src, fn)));
|
|
});
|
|
|
|
// Generate typings file for each file.
|
|
files.forEach((file) => {
|
|
const typescriptFileName = `${path.join(tmpDir, file)}.d.ts`;
|
|
if (file.indexOf('core/msg.js') > -1) {
|
|
return;
|
|
}
|
|
const cmd = `node ./node_modules/typescript-closure-tools/definition-generator/src/main.js ${file} ${typescriptFileName}`;
|
|
console.log(`Generating typings for ${file}`);
|
|
execSync(cmd, { stdio: 'inherit' });
|
|
});
|
|
|
|
const srcs = [
|
|
'typings/parts/blockly-header.d.ts',
|
|
'typings/parts/blockly-interfaces.d.ts',
|
|
'typings/parts/goog-closure.d.ts',
|
|
`${tmpDir}/core/**`,
|
|
`${tmpDir}/core/components/**`,
|
|
`${tmpDir}/core/components/tree/**`,
|
|
`${tmpDir}/core/components/menu/**`,
|
|
`${tmpDir}/core/keyboard_nav/**`,
|
|
`${tmpDir}/core/renderers/common/**`,
|
|
`${tmpDir}/core/renderers/measurables/**`,
|
|
`${tmpDir}/core/utils/**`,
|
|
`${tmpDir}/core/theme/**`,
|
|
`${tmpDir}/msg/**`
|
|
];
|
|
return gulp.src(srcs)
|
|
.pipe(gulp.concat('blockly.d.ts'))
|
|
.pipe(gulp.dest('typings'))
|
|
.on('end', function () {
|
|
// Clean up tmp directory.
|
|
if (fs.existsSync(tmpDir)) {
|
|
rimraf.sync(tmpDir);
|
|
}
|
|
});
|
|
});
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// NPM packaging tasks //
|
|
////////////////////////////////////////////////////////////
|
|
|
|
// The destination path where all the NPM distribution files will go.
|
|
const packageDistribution = './dist';
|
|
|
|
/**
|
|
* 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) {
|
|
return gulp.umd({
|
|
dependencies: function () { return dependencies; },
|
|
namespace: function () { return namespace; },
|
|
exports: function () { return namespace; },
|
|
template: path.join(__dirname, 'package/templates/umd.template')
|
|
});
|
|
};
|
|
|
|
/**
|
|
* A helper method for wrapping a file into a CommonJS module for Node.js.
|
|
* @param {string} namespace The export namespace.
|
|
* @param {Array<Object>} dependencies An array of dependencies to inject.
|
|
*/
|
|
function packageCommonJS(namespace, dependencies) {
|
|
return gulp.umd({
|
|
dependencies: function () { return dependencies; },
|
|
namespace: function () { return namespace; },
|
|
exports: function () { return namespace; },
|
|
template: path.join(__dirname, 'package/templates/node.template')
|
|
});
|
|
};
|
|
|
|
/**
|
|
* This task wraps blockly_compressed.js into a UMD module.
|
|
* @example import 'blockly/blockly';
|
|
*/
|
|
gulp.task('package-blockly', function() {
|
|
return gulp.src('blockly_compressed.js')
|
|
.pipe(gulp.insert.prepend(`
|
|
var self = this;`))
|
|
.pipe(packageUMD('Blockly', []))
|
|
.pipe(gulp.rename('blockly.js'))
|
|
.pipe(gulp.dest(packageDistribution));
|
|
});
|
|
|
|
/**
|
|
* This task wraps blocks_compressed.js into a CommonJS module for Node.js.
|
|
* This is an equivelant task to package-blockly but for Node.js.
|
|
* @example import 'blockly/blockly-node';
|
|
*/
|
|
gulp.task('package-blockly-node', function() {
|
|
// Override textToDomDocument, providing a Node.js alternative to DOMParser.
|
|
return gulp.src('blockly_compressed.js')
|
|
.pipe(gulp.insert.wrap(`
|
|
var self = global;`,
|
|
`if (typeof DOMParser !== 'function') {
|
|
var JSDOM = require('jsdom').JSDOM;
|
|
var window = (new JSDOM()).window;
|
|
var document = window.document;
|
|
var Element = window.Element;
|
|
Blockly.utils.xml.textToDomDocument = function(text) {
|
|
var jsdom = new JSDOM(text, { contentType: 'text/xml' });
|
|
return jsdom.window.document;
|
|
};
|
|
}`))
|
|
.pipe(packageCommonJS('Blockly', []))
|
|
.pipe(gulp.rename('blockly-node.js'))
|
|
.pipe(gulp.dest(packageDistribution));
|
|
})
|
|
|
|
/**
|
|
* This task wraps blocks_compressed.js into a UMD module.
|
|
* @example import 'blockly/blocks';
|
|
*/
|
|
gulp.task('package-blocks', function() {
|
|
return gulp.src('blocks_compressed.js')
|
|
.pipe(gulp.insert.prepend(`
|
|
Blockly.Blocks={};`))
|
|
.pipe(packageUMD('Blockly.Blocks', [{
|
|
name: 'Blockly',
|
|
amd: './core',
|
|
cjs: './core',
|
|
}]))
|
|
.pipe(gulp.rename('blocks.js'))
|
|
.pipe(gulp.dest(packageDistribution));
|
|
});
|
|
|
|
/**
|
|
* This task wraps package/index.js into a UMD module.
|
|
* We implicitly require the Node entry point in CommonJS environments,
|
|
* and the Browser entry point for AMD environments.
|
|
* @example import * as Blockly from 'blockly';
|
|
*/
|
|
gulp.task('package-index', function() {
|
|
return gulp.src('package/index.js')
|
|
.pipe(packageUMD('Blockly', [{
|
|
name: 'Blockly',
|
|
amd: './browser',
|
|
cjs: './node',
|
|
}]))
|
|
.pipe(gulp.rename('index.js'))
|
|
.pipe(gulp.dest(packageDistribution));
|
|
});
|
|
|
|
/**
|
|
* This task wraps package/browser/index.js into a UMD module.
|
|
* By default, the module includes Blockly core and built-in blocks,
|
|
* as well as the JavaScript code generator and the English block
|
|
* localization files.
|
|
* This module is configured (in package.json) to replaces the module
|
|
* built by package-node in browser environments.
|
|
* @example import * as Blockly from 'blockly/browser';
|
|
*/
|
|
gulp.task('package-browser', function() {
|
|
return gulp.src('package/browser/index.js')
|
|
.pipe(packageUMD('Blockly', [{
|
|
name: 'Blockly',
|
|
amd: './core-browser',
|
|
cjs: './core-browser',
|
|
},{
|
|
name: 'En',
|
|
amd: './msg/en',
|
|
cjs: './msg/en',
|
|
},{
|
|
name: 'BlocklyBlocks',
|
|
amd: './blocks',
|
|
cjs: './blocks',
|
|
},{
|
|
name: 'BlocklyJS',
|
|
amd: './javascript',
|
|
cjs: './javascript',
|
|
}]))
|
|
.pipe(gulp.rename('browser.js'))
|
|
.pipe(gulp.dest(packageDistribution));
|
|
});
|
|
|
|
/**
|
|
* This task wraps package/browser/core.js into a UMD module.
|
|
* By default, the module includes the Blockly core package and a
|
|
* helper method to set the locale.
|
|
* This module is configured (in package.json) to replaces the module
|
|
* built by package-node-core in browser environments.
|
|
* @example import * as Blockly from 'blockly/core';
|
|
*/
|
|
gulp.task('package-core', function() {
|
|
return gulp.src('package/browser/core.js')
|
|
.pipe(packageUMD('Blockly', [{
|
|
name: 'Blockly',
|
|
amd: './blockly',
|
|
cjs: './blockly',
|
|
}]))
|
|
.pipe(gulp.rename('core-browser.js'))
|
|
.pipe(gulp.dest(packageDistribution));
|
|
});
|
|
|
|
/**
|
|
* This task wraps package/node/index.js into a CommonJS module for Node.js.
|
|
* By default, the module includes Blockly core and built-in blocks,
|
|
* as well as all the code generators and the English block localization files.
|
|
* This module is configured (in package.json) to be replaced by the module
|
|
* built by package-browser in browser environments.
|
|
* @example import * as Blockly from 'blockly/node';
|
|
*/
|
|
gulp.task('package-node', function() {
|
|
return gulp.src('package/node/index.js')
|
|
.pipe(packageCommonJS('Blockly', [{
|
|
name: 'Blockly',
|
|
cjs: './core',
|
|
},{
|
|
name: 'En',
|
|
cjs: './msg/en',
|
|
},{
|
|
name: 'BlocklyBlocks',
|
|
cjs: './blocks',
|
|
},{
|
|
name: 'BlocklyJS',
|
|
cjs: './javascript',
|
|
},{
|
|
name: 'BlocklyPython',
|
|
cjs: './python',
|
|
},{
|
|
name: 'BlocklyPHP',
|
|
cjs: './php',
|
|
},{
|
|
name: 'BlocklyLua',
|
|
cjs: './lua',
|
|
}, {
|
|
name: 'BlocklyDart',
|
|
cjs: './dart',
|
|
}]))
|
|
.pipe(gulp.rename('node.js'))
|
|
.pipe(gulp.dest(packageDistribution));
|
|
});
|
|
|
|
/**
|
|
* This task wraps package/node/core.js into a CommonJS module for Node.js.
|
|
* By default, the module includes the Blockly core package for Node.js
|
|
* and a helper method to set the locale.
|
|
* This module is configured (in package.json) to be replaced by the module
|
|
* built by package-core in browser environments.
|
|
* @example import * as Blockly from 'blockly/core';
|
|
*/
|
|
gulp.task('package-node-core', function() {
|
|
return gulp.src('package/node/core.js')
|
|
.pipe(packageCommonJS('Blockly', [{
|
|
name: 'Blockly',
|
|
amd: './blockly-node',
|
|
cjs: './blockly-node',
|
|
}]))
|
|
.pipe(gulp.rename('core.js'))
|
|
.pipe(gulp.dest(packageDistribution));
|
|
});
|
|
|
|
/**
|
|
* A helper method for packaging a Blockly code generator into a UMD module.
|
|
* @param {string} file Source file name.
|
|
* @param {string} rename Destination file name.
|
|
* @param {string} generator Generator export namespace.
|
|
*/
|
|
function packageGenerator(file, rename, generator) {
|
|
return gulp.src(file)
|
|
.pipe(packageUMD(generator, [{
|
|
name: 'Blockly',
|
|
amd: './core',
|
|
cjs: './core',
|
|
}]))
|
|
.pipe(gulp.rename(rename))
|
|
.pipe(gulp.dest(packageDistribution));
|
|
};
|
|
|
|
/**
|
|
* This task wraps javascript_compressed.js into a UMD module.
|
|
* @example import 'blockly/javascript';
|
|
*/
|
|
gulp.task('package-javascript', function() {
|
|
return packageGenerator('javascript_compressed.js', 'javascript.js', 'Blockly.JavaScript');
|
|
});
|
|
|
|
/**
|
|
* This task wraps python_compressed.js into a UMD module.
|
|
* @example import 'blockly/python';
|
|
*/
|
|
gulp.task('package-python', function() {
|
|
return packageGenerator('python_compressed.js', 'python.js', 'Blockly.Python');
|
|
});
|
|
|
|
/**
|
|
* This task wraps lua_compressed.js into a UMD module.
|
|
* @example import 'blockly/lua';
|
|
*/
|
|
gulp.task('package-lua', function() {
|
|
return packageGenerator('lua_compressed.js', 'lua.js', 'Blockly.Lua');
|
|
});
|
|
|
|
/**
|
|
* This task wraps dart_compressed.js into a UMD module.
|
|
* @example import 'blockly/dart';
|
|
*/
|
|
gulp.task('package-dart', function() {
|
|
return packageGenerator('dart_compressed.js', 'dart.js', 'Blockly.Dart');
|
|
});
|
|
|
|
/**
|
|
* This task wraps php_compressed.js into a UMD module.
|
|
* @example import 'blockly/php';
|
|
*/
|
|
gulp.task('package-php', function() {
|
|
return packageGenerator('php_compressed.js', 'php.js', 'Blockly.PHP');
|
|
});
|
|
|
|
/**
|
|
* This task wraps each of the msg/js/* files into a UMD module.
|
|
* @example import * as En from 'blockly/msg/en';
|
|
*/
|
|
gulp.task('package-locales', function() {
|
|
// Remove references to goog.provide and goog.require.
|
|
return gulp.src('msg/js/*.js')
|
|
.pipe(gulp.replace(/goog\.[^\n]+/g, ''))
|
|
.pipe(gulp.insert.prepend(`
|
|
var Blockly = {};Blockly.Msg={};`))
|
|
.pipe(packageUMD('Blockly.Msg', [{
|
|
name: 'Blockly',
|
|
amd: '../core',
|
|
cjs: '../core',
|
|
}]))
|
|
.pipe(gulp.dest(`${packageDistribution}/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>
|
|
*/
|
|
gulp.task('package-umd-bundle', function() {
|
|
var srcs = [
|
|
'blockly_compressed.js',
|
|
'msg/js/en.js',
|
|
'blocks_compressed.js',
|
|
'javascript_compressed.js'
|
|
];
|
|
return gulp.src(srcs)
|
|
.pipe(gulp.concat('blockly.min.js'))
|
|
.pipe(packageUMD('Blockly', []))
|
|
.pipe(gulp.dest(`${packageDistribution}`))
|
|
});
|
|
|
|
/**
|
|
* This task copies all the media/* files into the distribution directory.
|
|
*/
|
|
gulp.task('package-media', function() {
|
|
return gulp.src('./media/*')
|
|
.pipe(gulp.dest(`${packageDistribution}/media`));
|
|
});
|
|
|
|
/**
|
|
* This task copies the package.json file into the distribution directory.
|
|
*/
|
|
gulp.task('package-json', function() {
|
|
return gulp.src('./package.json')
|
|
.pipe(gulp.dest(`${packageDistribution}`))
|
|
});
|
|
|
|
/**
|
|
* This task copies the package/README.md file into the distribution directory.
|
|
* This file is what developers will see at https://www.npmjs.com/package/blockly.
|
|
*/
|
|
gulp.task('package-readme', function() {
|
|
return gulp.src('./package/README.md')
|
|
.pipe(gulp.dest(`${packageDistribution}`))
|
|
});
|
|
|
|
/**
|
|
* This task copies the typings/blockly.d.ts TypeScript definition file into the
|
|
* distribution directory.
|
|
* The bundled declaration file is referenced in package.json in the types property.
|
|
*/
|
|
gulp.task('package-dts', function() {
|
|
return gulp.src('./typings/blockly.d.ts')
|
|
.pipe(gulp.dest(`${packageDistribution}`))
|
|
});
|
|
|
|
/**
|
|
* This task prepares the NPM distribution files under the /dist directory.
|
|
*/
|
|
gulp.task('package', gulp.parallel(
|
|
'package-index',
|
|
'package-browser',
|
|
'package-node',
|
|
'package-core',
|
|
'package-node-core',
|
|
'package-blockly',
|
|
'package-blockly-node',
|
|
'package-blocks',
|
|
'package-javascript',
|
|
'package-python',
|
|
'package-lua',
|
|
'package-dart',
|
|
'package-php',
|
|
'package-locales',
|
|
'package-media',
|
|
'package-umd-bundle',
|
|
'package-json',
|
|
'package-readme',
|
|
'package-dts'
|
|
));
|
|
|
|
// The release task prepares Blockly for an npm release.
|
|
// It rebuilds the Blockly compressed files and updates the TypeScript
|
|
// typings, and then packages all the npm release files into the /dist directory
|
|
gulp.task('release', gulp.series(['build', 'typings', function() {
|
|
// Clean directory if exists
|
|
if (fs.existsSync(packageDistribution)) {
|
|
rimraf.sync(packageDistribution);
|
|
}
|
|
fs.mkdirSync(packageDistribution);
|
|
}, 'package']));
|
|
|
|
// The default task concatenates files for Node.js, using English language
|
|
// blocks and the JavaScript generator.
|
|
gulp.task('default', gulp.series(['build', 'blockly_node_javascript_en']));
|