Move babel-standalone into main Babel repo (#6029)

* Move babel-standalone into main Babel repo

* Don't try to gather coverage data for babel-standalone test

* Fix JSX test

* Always use npm v4 on Travis

* Include pull request number as part of version number

* Cherry-picking 5721b2e43e

Remove deprecated packages to prevent Babel v6 files from being pulled in

* Use RootMostResolvePlugin to dedupe packages

* Avoid destructuring so the build works on archaic Node.js versions

* - Fix version number
- Remove Babili packages (they should be in separate babili-standalone)
- Remove deprecated  syntax-class-constructor-call

* - Remove more Babili packages
- Remove `babel-plugin-inline-replace-variables` for now as it pulls in Babel 6 stuff

* Actually remove reference to babel-plugin-undeclared-variables-check

* Add Babylon to root package.json so we hoist the right version. This fixes the tests.
This commit is contained in:
Daniel Lo Nigro 2017-08-11 23:36:19 -07:00 committed by GitHub
parent 0538c3cd8c
commit a04c18af71
22 changed files with 1915 additions and 56 deletions

View File

@ -7,3 +7,9 @@ packages/*/lib
packages/*/dist packages/*/dist
packages/*/test/fixtures packages/*/test/fixtures
packages/*/test/tmp packages/*/test/tmp
packages/babel-standalone/babel.js
packages/babel-standalone/babel.min.js
# Prettier tries to insert trailing commas in function calls, which Node.js
# doesn't natively support. This causes an error when loading the Gulp tasks.
packages/babel-standalone/src/gulpTasks.js

2
.gitignore vendored
View File

@ -27,3 +27,5 @@ package-lock.json
/packages/*/lib /packages/*/lib
.nyc_output .nyc_output
/babel.sublime-workspace /babel.sublime-workspace
packages/babel-standalone/babel.js
packages/babel-standalone/babel.min.js

View File

@ -20,6 +20,9 @@ before_install:
- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.28.1 - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.28.1
script: script:
# Babel doesn't build correctly with npm v2 (which comes bundled with Node v4)
# so we manually upgrade to a known working npm version.
- npm install --global npm@4
- 'if [ "$JOB" = "test" ]; then make test-ci; fi' - 'if [ "$JOB" = "test" ]; then make test-ci; fi'
- 'if [ "$JOB" = "lint" ]; then make lint && make flow; fi' - 'if [ "$JOB" = "lint" ]; then make lint && make flow; fi'

View File

@ -9,6 +9,7 @@ const watch = require("gulp-watch");
const gutil = require("gulp-util"); const gutil = require("gulp-util");
const gulp = require("gulp"); const gulp = require("gulp");
const path = require("path"); const path = require("path");
const registerBabelStandaloneTasks = require("./packages/babel-standalone/src/gulpTasks");
const base = path.join(__dirname, "packages"); const base = path.join(__dirname, "packages");
const scripts = "./packages/*/src/**/*.js"; const scripts = "./packages/*/src/**/*.js";
@ -59,3 +60,5 @@ gulp.task("watch", ["build"], function() {
gulp.start("build"); gulp.start("build");
}); });
}); });
registerBabelStandaloneTasks(gulp);

View File

@ -10,6 +10,9 @@ export FORCE_COLOR = true
build: clean build: clean
rm -rf packages/*/lib rm -rf packages/*/lib
./node_modules/.bin/gulp build ./node_modules/.bin/gulp build
ifneq ($(BABEL_ENV), "cov")
./node_modules/.bin/gulp build-babel-standalone
endif
build-dist: build build-dist: build
cd packages/babel-polyfill; \ cd packages/babel-polyfill; \

View File

@ -1,3 +1,8 @@
general:
artifacts:
- "packages/babel-standalone/babel.js"
- "packages/babel-standalone/babel.min.js"
machine: machine:
node: node:
version: version:
@ -14,3 +19,9 @@ dependencies:
test: test:
override: override:
- make test-ci-coverage - make test-ci-coverage
# Builds babel-standalone with the regular Babel config
- make build
# test-ci-coverage doesn't test babel-standalone, as trying to gather coverage
# data for a JS file that's several megabytes large is bound to fail. Here,
# we just run the babel-standalone test separately.
- ./node_modules/mocha/bin/_mocha packages/babel-standalone/test/ --opts test/mocha.opts

View File

@ -14,11 +14,13 @@
"babel-cli": "7.0.0-alpha.18", "babel-cli": "7.0.0-alpha.18",
"babel-core": "7.0.0-alpha.18", "babel-core": "7.0.0-alpha.18",
"babel-eslint": "8.0.0-alpha.15", "babel-eslint": "8.0.0-alpha.15",
"babel-loader": "^7.1.1",
"babel-plugin-istanbul": "^4.1.4", "babel-plugin-istanbul": "^4.1.4",
"babel-preset-env": "2.0.0-alpha.18", "babel-preset-env": "2.0.0-alpha.18",
"babel-preset-flow": "7.0.0-alpha.18", "babel-preset-flow": "7.0.0-alpha.18",
"babel-preset-stage-0": "7.0.0-alpha.18", "babel-preset-stage-0": "7.0.0-alpha.18",
"babel-register": "7.0.0-alpha.18", "babel-register": "7.0.0-alpha.18",
"babylon": "7.0.0-beta.18",
"browserify": "^13.1.1", "browserify": "^13.1.1",
"bundle-collapser": "^1.2.1", "bundle-collapser": "^1.2.1",
"chai": "^4.1.0", "chai": "^4.1.0",
@ -58,7 +60,8 @@
"all": true, "all": true,
"exclude": [ "exclude": [
"scripts/*.js", "scripts/*.js",
"packages/*/test/**" "packages/*/test/**",
"packages/babel-standalone/**"
], ],
"sourceMap": false, "sourceMap": false,
"instrument": false "instrument": false

View File

@ -0,0 +1,93 @@
babel-standalone
================
babel-standalone is a standalone build of Babel for use in non-Node.js environments, including browsers. It's bundled with all the standard Babel plugins and presets, and [a build of babili (babel-minify)](http://dl.vc/babili-standalone) is optionally available too.
But why?!
=========
It's true that using Babel through Webpack, Browserify or Gulp should be sufficient for most use cases. However, there are some valid use cases for babel-standalone:
- Sites like [JSFiddle](https://jsfiddle.net/), [JS Bin](https://jsbin.com/), the [REPL on the Babel site](http://babeljs.io/repl/), etc. These sites compile user-provided JavaScript in real-time.
- Apps that embed a JavaScript engine such as V8 directly, and want to use Babel for compilation
- Apps that want to use JavaScript as a scripting language for extending the app itself, including all the goodies that ES2015 provides.
- Integration of Babel into a non-Node.js environment ([ReactJS.NET](http://reactjs.net/), [ruby-babel-transpiler](https://github.com/babel/ruby-babel-transpiler), [php-babel-transpiler](https://github.com/talyssonoc/php-babel-transpiler), etc).
Installation
============
There are several ways to get a copy of babel-standalone. Pick whichever one you like:
- Use it via UNPKG: https://unpkg.com/babel-standalone@6/babel.min.js. This is a simple way to embed it on a webpage without having to do any other setup.
- Install via Bower: `bower install babel-standalone`
- Install via NPM: `npm install --save babel-standalone`
- Manually grab `babel.js` and/or `babel.min.js` from the [GitHub releases page](https://github.com/Daniel15/babel-standalone/releases). Every release includes these files.
- Install it via Git: You can use the repo at https://github.com/Daniel15/babel-standalone-bower to pull a prebuilt version from Git. Note that this is generally only advised for systems that *must* pull artifacts from Git, such as Bower.
Usage
=====
Load `babel.js` or `babel.min.js` in your environment. This will expose [Babel's API](http://babeljs.io/docs/usage/api/) in a `Babel` object:
```js
var input = 'const getMessage = () => "Hello World";';
var output = Babel.transform(input, { presets: ['es2015'] }).code;
```
When loaded in a browser, babel-standalone will automatically compile and execute all script tags with type `text/babel` or `text/jsx`:
```html
<div id="output"></div>
<!-- Load Babel -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- Your custom script here -->
<script type="text/babel">
const getMessage = () => "Hello World";
document.getElementById('output').innerHTML = getMessage();
</script>
```
You can use the `data-plugins` and `data-presets` attributes to specify the Babel plugins/presets to use:
```html
<script type="text/babel" data-presets="es2015,stage-2">
```
Loading external scripts via `src` attribute is supported too:
```html
<script type="text/babel" src="foo.js"></script>
```
Note that `.babelrc` doesn't work in babel-standalone, as no file system access is available. The presets and/or plugins to use **must** be specified in the options passed to `Babel.transform`.
Customisation
=============
Custom plugins and presets can be added using the `registerPlugin` and `registerPreset` methods respectively:
```js
// Simple plugin that converts every identifier to "LOL"
function lolizer() {
return {
visitor: {
Identifier(path) {
path.node.name = 'LOL';
}
}
}
}
Babel.registerPlugin('lolizer', lolizer);
```
Once registered, just use the name of the plugin:
```js
var output = Babel.transform(
'function helloWorld() { alert(hello); }',
{plugins: ['lolizer']}
);
// Returns "function LOL() { LOL(LOL); }"
```
Custom plugins also work for inline `<script>`s:
```html
<script type="text/babel" data-plugins="lolizer">
```

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>babel-standalone example</title>
</head>
<body>
Input:
<textarea id="input" style="width: 100%" rows="10">
const getMessage = () => 'Hello World';
const someDiv = <div>{getMessage()}</div>;
</textarea>
Transformed code using Babel <strong id="version"></strong>:
<pre id="output">Loading...</pre>
<script src="../babel.js"></script>
<script>
console.log('Babel =', Babel);
document.getElementById('version').innerHTML = Babel.version;
var inputEl = document.getElementById('input');
var outputEl = document.getElementById('output');
function transform() {
try {
outputEl.innerHTML = Babel.transform(inputEl.value, {
presets: ['es2015', 'react', 'stage-0']
}).code;
} catch (ex) {
outputEl.innerHTML = 'ERROR: ' + ex.message;
}
}
inputEl.addEventListener('keyup', transform, false);
transform();
</script>
</body>
</html>

View File

@ -0,0 +1,8 @@
/* global Babel */
const doStuff = () => {
const name = "world";
document.getElementById("output").innerHTML = `Hello ${name}`;
document.getElementById("version").innerHTML = Babel.version;
};
doStuff();

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>babel-standalone example - Script tag</title>
</head>
<body>
Using Babel <strong id="version"></strong>:
<pre id="output">Loading...</pre>
<script src="../babel.js"></script>
<script type="text/javascript">
// just disable the auto transformation
Babel.disableScriptTags();
var script = document.createElement('script');
script.type = 'text/babel';
script.text = "const doStuff = () => {" +
" const name = 'world';" +
" document.getElementById('output').innerHTML = `Hello ${name}`;" +
" document.getElementById('version').innerHTML = Babel.version;" +
"};" +
"doStuff();";
document.querySelector('head').appendChild(script)
// transform when you want to
Babel.transformScriptTags()
</script>
</body>
</html>

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>babel-standalone example - Script tag</title>
</head>
<body>
Using Babel <strong id="version"></strong>:
<pre id="output">Loading...</pre>
<script src="../babel.js"></script>
<script type="text/babel">
const doStuff = () => {
const name = 'world';
document.getElementById('output').innerHTML = `Hello ${name}`;
document.getElementById('version').innerHTML = Babel.version;
};
doStuff();
</script>
</body>
</html>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>babel-standalone example - External script</title>
</head>
<body>
Using Babel <strong id="version"></strong>:
<pre id="output">Loading...</pre>
<script src="../babel.js"></script>
<script type="text/babel" src="example.js"></script>
</body>
</html>

View File

@ -0,0 +1,122 @@
{
"name": "babel-standalone",
"version": "7.0.0-alpha.19",
"description": "Standalone build of Babel for use in non-Node.js environments.",
"main": "babel.js",
"files": [
"babel.js",
"babel.min.js",
"src"
],
"devDependencies": {
"babel-core": "7.0.0-alpha.19",
"babel-helper-builder-react-jsx": "7.0.0-alpha.19",
"babel-loader": "7.1.1",
"babel-plugin-check-es2015-constants": "7.0.0-alpha.19",
"babel-plugin-external-helpers": "7.0.0-alpha.19",
"babel-plugin-inline-replace-variables": "1.3.1",
"babel-plugin-syntax-async-functions": "7.0.0-alpha.19",
"babel-plugin-syntax-async-generators": "7.0.0-alpha.19",
"babel-plugin-syntax-class-properties": "7.0.0-alpha.19",
"babel-plugin-syntax-decorators": "7.0.0-alpha.19",
"babel-plugin-syntax-do-expressions": "7.0.0-alpha.19",
"babel-plugin-syntax-exponentiation-operator": "7.0.0-alpha.19",
"babel-plugin-syntax-export-extensions": "7.0.0-alpha.19",
"babel-plugin-syntax-flow": "7.0.0-alpha.19",
"babel-plugin-syntax-function-bind": "7.0.0-alpha.19",
"babel-plugin-syntax-function-sent": "7.0.0-alpha.19",
"babel-plugin-syntax-jsx": "7.0.0-alpha.19",
"babel-plugin-syntax-object-rest-spread": "7.0.0-alpha.19",
"babel-plugin-syntax-trailing-function-commas": "7.0.0-alpha.19",
"babel-plugin-transform-async-functions": "7.0.0-alpha.19",
"babel-plugin-transform-async-to-generator": "7.0.0-alpha.19",
"babel-plugin-transform-async-to-module-method": "7.0.0-alpha.19",
"babel-plugin-transform-class-properties": "7.0.0-alpha.19",
"babel-plugin-transform-decorators": "7.0.0-alpha.19",
"babel-plugin-transform-do-expressions": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-arrow-functions": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-block-scoped-functions": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-block-scoping": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-classes": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-computed-properties": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-destructuring": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-duplicate-keys": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-for-of": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-function-name": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-instanceof": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-literals": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-modules-amd": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-modules-commonjs": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-modules-systemjs": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-modules-umd": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-object-super": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-parameters": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-shorthand-properties": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-spread": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-sticky-regex": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-template-literals": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-typeof-symbol": "7.0.0-alpha.19",
"babel-plugin-transform-es2015-unicode-regex": "7.0.0-alpha.19",
"babel-plugin-transform-es3-member-expression-literals": "7.0.0-alpha.19",
"babel-plugin-transform-es3-property-literals": "7.0.0-alpha.19",
"babel-plugin-transform-es5-property-mutators": "7.0.0-alpha.19",
"babel-plugin-transform-eval": "7.0.0-alpha.19",
"babel-plugin-transform-exponentiation-operator": "7.0.0-alpha.19",
"babel-plugin-transform-export-extensions": "7.0.0-alpha.19",
"babel-plugin-transform-flow-comments": "7.0.0-alpha.19",
"babel-plugin-transform-flow-strip-types": "7.0.0-alpha.19",
"babel-plugin-transform-function-bind": "7.0.0-alpha.19",
"babel-plugin-transform-jscript": "7.0.0-alpha.19",
"babel-plugin-transform-object-assign": "7.0.0-alpha.19",
"babel-plugin-transform-object-rest-spread": "7.0.0-alpha.19",
"babel-plugin-transform-object-set-prototype-of-to-assign": "7.0.0-alpha.19",
"babel-plugin-transform-proto-to-assign": "7.0.0-alpha.19",
"babel-plugin-transform-react-constant-elements": "7.0.0-alpha.19",
"babel-plugin-transform-react-display-name": "7.0.0-alpha.19",
"babel-plugin-transform-react-inline-elements": "7.0.0-alpha.19",
"babel-plugin-transform-react-jsx": "7.0.0-alpha.19",
"babel-plugin-transform-react-jsx-compat": "7.0.0-alpha.19",
"babel-plugin-transform-react-jsx-self": "7.0.0-alpha.19",
"babel-plugin-transform-react-jsx-source": "7.0.0-alpha.19",
"babel-plugin-transform-regenerator": "7.0.0-alpha.19",
"babel-plugin-transform-runtime": "7.0.0-alpha.19",
"babel-plugin-transform-strict-mode": "7.0.0-alpha.19",
"babel-preset-env": "2.0.0-alpha.19",
"babel-preset-es2015": "7.0.0-alpha.19",
"babel-preset-es2016": "7.0.0-alpha.19",
"babel-preset-es2017": "7.0.0-alpha.19",
"babel-preset-react": "7.0.0-alpha.19",
"babel-preset-stage-0": "7.0.0-alpha.19",
"babel-preset-stage-1": "7.0.0-alpha.19",
"babel-preset-stage-2": "7.0.0-alpha.19",
"babel-preset-stage-3": "7.0.0-alpha.19",
"gulp-rename": "^1.2.2",
"gulp-uglify": "^3.0.0",
"json-loader": "^0.5.7",
"lazypipe": "^1.0.1",
"pump": "^1.0.2",
"react": "^16.0.0-beta.3",
"webpack": "^3.4.1",
"webpack-dependency-suite": "^2.4.4",
"webpack-stream": "^4.0.0"
},
"keywords": [
"babel",
"babeljs",
"6to5",
"transpile",
"transpiler"
],
"author": "Daniel Lo Nigro <daniel@dan.cx> (http://dan.cx/)",
"license": "MIT",
"bugs": {
"url": "https://github.com/babel/babel-standalone/issues"
},
"homepage": "https://github.com/babel/babel-standalone#readme",
"jest": {
"transformIgnorePatterns": [
"/node_modules/",
"babel.js"
]
}
}

View File

@ -0,0 +1,8 @@
/**
* A shim that replaces Babel's require('package.json') statement.
* Babel requires the entire package.json file just to get the version number.
*/
/* global BABEL_VERSION */
export const version = BABEL_VERSION;

View File

@ -0,0 +1,123 @@
/**
* This file contains the Gulp tasks for babel-standalone. Note that
* babel-standalone is compiled using Webpack, and performs its own Babel
* compilation of all the JavaScript files. This is because it targets web
* browsers, so more transforms are needed than the regular Babel builds that
* only target Node.js.
*/
const pump = require("pump");
const rename = require("gulp-rename");
const RootMostResolvePlugin = require("webpack-dependency-suite").RootMostResolvePlugin;
const webpack = require("webpack");
const webpackStream = require("webpack-stream");
const uglify = require("gulp-uglify");
function webpackBuild(filename, libraryName, version) {
// If this build is part of a pull request, include the pull request number in
// the version number.
if (process.env.CIRCLE_PR_NUMBER) {
version += '+pr.' + process.env.CIRCLE_PR_NUMBER;
}
const typeofPlugin = require("babel-plugin-transform-es2015-typeof-symbol")
.default;
// babel-plugin-transform-es2015-typeof-symbol is not idempotent, and something
// else is already running it, so we need to exclude it from the transform.
const preset2015 = require("babel-preset-es2015").default();
const es2015WithoutTypeof = {
plugins: preset2015.plugins.filter(plugin => plugin !== typeofPlugin),
};
const config = {
module: {
rules: [
{
//exclude: /node_modules/,
test: /\.js$/,
loader: "babel-loader",
options: {
// Some of the node_modules may have their own "babel" section in
// their project.json (or a ".babelrc" file). We need to ignore
// those as we're using our own Babel options.
babelrc: false,
presets: [es2015WithoutTypeof, require("babel-preset-stage-0")],
},
},
],
},
node: {
// Mock Node.js modules that Babel require()s but that we don't
// particularly care about.
fs: "empty",
module: "empty",
net: "empty",
},
output: {
filename: filename,
library: libraryName,
libraryTarget: "umd",
},
plugins: [
new webpack.DefinePlugin({
"process.env.NODE_ENV": '"production"',
BABEL_VERSION:
JSON.stringify(require("babel-core/package.json").version),
VERSION: JSON.stringify(version),
}),
// Use browser version of visionmedia-debug
new webpack.NormalModuleReplacementPlugin(
/debug\/node/,
"debug/src/browser"
),
/*new webpack.NormalModuleReplacementPlugin(
/..\/..\/package/,
"../../../../src/babel-package-shim"
),*/
new webpack.optimize.ModuleConcatenationPlugin(),
],
resolve: {
plugins: [
// Dedupe packages that are used across multiple plugins.
// This replaces DedupePlugin from Webpack 1.x
new RootMostResolvePlugin(__dirname + '/../../../', true),
],
},
};
if (libraryName !== "Babel") {
// This is a secondary package (eg. Babili), we should expect that Babel
// was already loaded, rather than bundling it in here too.
config.externals = {
"babel-standalone": "Babel",
};
}
return webpackStream(config, webpack);
// To write JSON for debugging:
/*return webpackStream(config, webpack, (err, stats) => {
require('gulp-util').log(stats.toString({colors: true}));
require('fs').writeFileSync('webpack-debug.json', JSON.stringify(stats.toJson()));
});*/
}
function registerGulpTasks(gulp) {
gulp.task("build-babel-standalone", ["build"], cb => {
pump(
[
gulp.src(__dirname + "/index.js"),
webpackBuild(
"babel.js",
"Babel",
require(__dirname + "/../package.json").version
),
gulp.dest(__dirname + "/../"),
uglify(),
rename({ extname: ".min.js" }),
gulp.dest(__dirname + "/../"),
],
cb
);
});
}
module.exports = registerGulpTasks;

View File

@ -0,0 +1,317 @@
/**
* Entry point for babel-standalone. This wraps Babel's API in a version that's
* friendlier for use in web browers. It removes the automagical detection of
* plugins, instead explicitly registering all the available plugins and
* presets, and requiring custom ones to be registered through `registerPlugin`
* and `registerPreset` respectively.
*/
/* global VERSION */
/* eslint-disable max-len */
import * as Babel from "babel-core";
import { runScripts } from "./transformScriptTags";
const isArray =
Array.isArray ||
(arg => Object.prototype.toString.call(arg) === "[object Array]");
/**
* Loads the given name (or [name, options] pair) from the given table object
* holding the available presets or plugins.
*
* Returns undefined if the preset or plugin is not available; passes through
* name unmodified if it (or the first element of the pair) is not a string.
*/
function loadBuiltin(builtinTable, name) {
if (isArray(name) && typeof name[0] === "string") {
if (builtinTable.hasOwnProperty(name[0])) {
return [builtinTable[name[0]]].concat(name.slice(1));
}
return;
} else if (typeof name === "string") {
return builtinTable[name];
}
// Could be an actual preset/plugin module
return name;
}
/**
* Parses plugin names and presets from the specified options.
*/
function processOptions(options) {
// Parse preset names
const presets = (options.presets || []).map(presetName => {
const preset = loadBuiltin(availablePresets, presetName);
if (preset) {
// workaround for babel issue
// at some point, babel copies the preset, losing the non-enumerable
// buildPreset key; convert it into an enumerable key.
if (
isArray(preset) &&
typeof preset[0] === "object" &&
preset[0].hasOwnProperty("buildPreset")
) {
preset[0] = { ...preset[0], buildPreset: preset[0].buildPreset };
}
} else {
throw new Error(
`Invalid preset specified in Babel options: "${presetName}"`,
);
}
return preset;
});
// Parse plugin names
const plugins = (options.plugins || []).map(pluginName => {
const plugin = loadBuiltin(availablePlugins, pluginName);
if (!plugin) {
throw new Error(
`Invalid plugin specified in Babel options: "${pluginName}"`,
);
}
return plugin;
});
return {
babelrc: false,
...options,
presets,
plugins,
};
}
export function transform(code, options) {
return Babel.transform(code, processOptions(options));
}
export function transformFromAst(ast, code, options) {
return Babel.transformFromAst(ast, code, processOptions(options));
}
export const availablePlugins = {};
export const availablePresets = {};
export const buildExternalHelpers = Babel.buildExternalHelpers;
/**
* Registers a named plugin for use with Babel.
*/
export function registerPlugin(name, plugin) {
if (availablePlugins.hasOwnProperty(name)) {
console.warn(
`A plugin named "${name}" is already registered, it will be overridden`,
);
}
availablePlugins[name] = plugin;
}
/**
* Registers multiple plugins for use with Babel. `newPlugins` should be an object where the key
* is the name of the plugin, and the value is the plugin itself.
*/
export function registerPlugins(newPlugins) {
Object.keys(newPlugins).forEach(name =>
registerPlugin(name, newPlugins[name]),
);
}
/**
* Registers a named preset for use with Babel.
*/
export function registerPreset(name, preset) {
if (availablePresets.hasOwnProperty(name)) {
console.warn(
`A preset named "${name}" is already registered, it will be overridden`,
);
}
availablePresets[name] = preset;
}
/**
* Registers multiple presets for use with Babel. `newPresets` should be an object where the key
* is the name of the preset, and the value is the preset itself.
*/
export function registerPresets(newPresets) {
Object.keys(newPresets).forEach(name =>
registerPreset(name, newPresets[name]),
);
}
// All the plugins we should bundle
registerPlugins({
"check-es2015-constants": require("babel-plugin-check-es2015-constants"),
"external-helpers": require("babel-plugin-external-helpers"),
"syntax-async-functions": require("babel-plugin-syntax-async-functions"),
"syntax-async-generators": require("babel-plugin-syntax-async-generators"),
"syntax-class-properties": require("babel-plugin-syntax-class-properties"),
"syntax-decorators": require("babel-plugin-syntax-decorators"),
"syntax-do-expressions": require("babel-plugin-syntax-do-expressions"),
"syntax-exponentiation-operator": require("babel-plugin-syntax-exponentiation-operator"),
"syntax-export-extensions": require("babel-plugin-syntax-export-extensions"),
"syntax-flow": require("babel-plugin-syntax-flow"),
"syntax-function-bind": require("babel-plugin-syntax-function-bind"),
"syntax-function-sent": require("babel-plugin-syntax-function-sent"),
"syntax-jsx": require("babel-plugin-syntax-jsx"),
"syntax-object-rest-spread": require("babel-plugin-syntax-object-rest-spread"),
"syntax-trailing-function-commas": require("babel-plugin-syntax-trailing-function-commas"),
"transform-async-functions": require("babel-plugin-transform-async-functions"),
"transform-async-to-generator": require("babel-plugin-transform-async-to-generator"),
"transform-async-to-module-method": require("babel-plugin-transform-async-to-module-method"),
"transform-class-properties": require("babel-plugin-transform-class-properties"),
"transform-decorators": require("babel-plugin-transform-decorators"),
"transform-do-expressions": require("babel-plugin-transform-do-expressions"),
"transform-es2015-arrow-functions": require("babel-plugin-transform-es2015-arrow-functions"),
"transform-es2015-block-scoped-functions": require("babel-plugin-transform-es2015-block-scoped-functions"),
"transform-es2015-block-scoping": require("babel-plugin-transform-es2015-block-scoping"),
"transform-es2015-classes": require("babel-plugin-transform-es2015-classes"),
"transform-es2015-computed-properties": require("babel-plugin-transform-es2015-computed-properties"),
"transform-es2015-destructuring": require("babel-plugin-transform-es2015-destructuring"),
"transform-es2015-duplicate-keys": require("babel-plugin-transform-es2015-duplicate-keys"),
"transform-es2015-for-of": require("babel-plugin-transform-es2015-for-of"),
"transform-es2015-function-name": require("babel-plugin-transform-es2015-function-name"),
"transform-es2015-instanceof": require("babel-plugin-transform-es2015-instanceof"),
"transform-es2015-literals": require("babel-plugin-transform-es2015-literals"),
"transform-es2015-modules-amd": require("babel-plugin-transform-es2015-modules-amd"),
"transform-es2015-modules-commonjs": require("babel-plugin-transform-es2015-modules-commonjs"),
"transform-es2015-modules-systemjs": require("babel-plugin-transform-es2015-modules-systemjs"),
"transform-es2015-modules-umd": require("babel-plugin-transform-es2015-modules-umd"),
"transform-es2015-object-super": require("babel-plugin-transform-es2015-object-super"),
"transform-es2015-parameters": require("babel-plugin-transform-es2015-parameters"),
"transform-es2015-shorthand-properties": require("babel-plugin-transform-es2015-shorthand-properties"),
"transform-es2015-spread": require("babel-plugin-transform-es2015-spread"),
"transform-es2015-sticky-regex": require("babel-plugin-transform-es2015-sticky-regex"),
"transform-es2015-template-literals": require("babel-plugin-transform-es2015-template-literals"),
"transform-es2015-typeof-symbol": require("babel-plugin-transform-es2015-typeof-symbol"),
"transform-es2015-unicode-regex": require("babel-plugin-transform-es2015-unicode-regex"),
"transform-es3-member-expression-literals": require("babel-plugin-transform-es3-member-expression-literals"),
"transform-es3-property-literals": require("babel-plugin-transform-es3-property-literals"),
"transform-es5-property-mutators": require("babel-plugin-transform-es5-property-mutators"),
"transform-eval": require("babel-plugin-transform-eval"),
"transform-exponentiation-operator": require("babel-plugin-transform-exponentiation-operator"),
"transform-export-extensions": require("babel-plugin-transform-export-extensions"),
"transform-flow-comments": require("babel-plugin-transform-flow-comments"),
"transform-flow-strip-types": require("babel-plugin-transform-flow-strip-types"),
"transform-function-bind": require("babel-plugin-transform-function-bind"),
"transform-jscript": require("babel-plugin-transform-jscript"),
"transform-object-assign": require("babel-plugin-transform-object-assign"),
"transform-object-rest-spread": require("babel-plugin-transform-object-rest-spread"),
"transform-object-set-prototype-of-to-assign": require("babel-plugin-transform-object-set-prototype-of-to-assign"),
"transform-proto-to-assign": require("babel-plugin-transform-proto-to-assign"),
"transform-react-constant-elements": require("babel-plugin-transform-react-constant-elements"),
"transform-react-display-name": require("babel-plugin-transform-react-display-name"),
"transform-react-inline-elements": require("babel-plugin-transform-react-inline-elements"),
"transform-react-jsx": require("babel-plugin-transform-react-jsx"),
"transform-react-jsx-compat": require("babel-plugin-transform-react-jsx-compat"),
"transform-react-jsx-self": require("babel-plugin-transform-react-jsx-self"),
"transform-react-jsx-source": require("babel-plugin-transform-react-jsx-source"),
"transform-regenerator": require("babel-plugin-transform-regenerator"),
"transform-runtime": require("babel-plugin-transform-runtime"),
"transform-strict-mode": require("babel-plugin-transform-strict-mode"),
});
// All the presets we should bundle
registerPresets({
es2015: require("babel-preset-es2015"),
es2016: require("babel-preset-es2016"),
es2017: require("babel-preset-es2017"),
react: require("babel-preset-react"),
"stage-0": require("babel-preset-stage-0"),
"stage-1": require("babel-preset-stage-1"),
"stage-2": require("babel-preset-stage-2"),
"stage-3": require("babel-preset-stage-3"),
// ES2015 preset with es2015-modules-commonjs removed
// Plugin list copied from babel-preset-es2015/index.js
"es2015-no-commonjs": {
plugins: [
require("babel-plugin-transform-es2015-template-literals"),
require("babel-plugin-transform-es2015-literals"),
require("babel-plugin-transform-es2015-function-name"),
require("babel-plugin-transform-es2015-arrow-functions"),
require("babel-plugin-transform-es2015-block-scoped-functions"),
require("babel-plugin-transform-es2015-classes"),
require("babel-plugin-transform-es2015-object-super"),
require("babel-plugin-transform-es2015-shorthand-properties"),
require("babel-plugin-transform-es2015-computed-properties"),
require("babel-plugin-transform-es2015-for-of"),
require("babel-plugin-transform-es2015-sticky-regex"),
require("babel-plugin-transform-es2015-unicode-regex"),
require("babel-plugin-check-es2015-constants"),
require("babel-plugin-transform-es2015-spread"),
require("babel-plugin-transform-es2015-parameters"),
require("babel-plugin-transform-es2015-destructuring"),
require("babel-plugin-transform-es2015-block-scoping"),
require("babel-plugin-transform-es2015-typeof-symbol"),
[
require("babel-plugin-transform-regenerator"),
{ async: false, asyncGenerators: false },
],
],
},
// ES2015 preset with plugins set to loose mode.
// Based off https://github.com/bkonkle/babel-preset-es2015-loose/blob/master/index.js
"es2015-loose": {
plugins: [
[
require("babel-plugin-transform-es2015-template-literals"),
{ loose: true },
],
require("babel-plugin-transform-es2015-literals"),
require("babel-plugin-transform-es2015-function-name"),
require("babel-plugin-transform-es2015-arrow-functions"),
require("babel-plugin-transform-es2015-block-scoped-functions"),
[require("babel-plugin-transform-es2015-classes"), { loose: true }],
require("babel-plugin-transform-es2015-object-super"),
require("babel-plugin-transform-es2015-shorthand-properties"),
require("babel-plugin-transform-es2015-duplicate-keys"),
[
require("babel-plugin-transform-es2015-computed-properties"),
{ loose: true },
],
[require("babel-plugin-transform-es2015-for-of"), { loose: true }],
require("babel-plugin-transform-es2015-sticky-regex"),
require("babel-plugin-transform-es2015-unicode-regex"),
require("babel-plugin-check-es2015-constants"),
[require("babel-plugin-transform-es2015-spread"), { loose: true }],
require("babel-plugin-transform-es2015-parameters"),
[require("babel-plugin-transform-es2015-destructuring"), { loose: true }],
require("babel-plugin-transform-es2015-block-scoping"),
require("babel-plugin-transform-es2015-typeof-symbol"),
[
require("babel-plugin-transform-es2015-modules-commonjs"),
{ loose: true },
],
[
require("babel-plugin-transform-regenerator"),
{ async: false, asyncGenerators: false },
],
],
},
});
export const version = VERSION;
// Listen for load event if we're in a browser and then kick off finding and
// running of scripts with "text/babel" type.
if (typeof window !== "undefined" && window && window.addEventListener) {
window.addEventListener(
"DOMContentLoaded",
() => transformScriptTags(),
false,
);
}
/**
* Transform <script> tags with "text/babel" type.
* @param {Array} scriptTags specify script tags to transform, transform all in the <head> if not given
*/
export function transformScriptTags(scriptTags) {
runScripts(transform, scriptTags);
}
/**
* Disables automatic transformation of <script> tags with "text/babel" type.
*/
export function disableScriptTags() {
window.removeEventListener("DOMContentLoaded", transformScriptTags);
}

View File

@ -0,0 +1,203 @@
/**
* Copyright 2013-2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of the React source tree.
*/
const scriptTypes = ["text/jsx", "text/babel"];
let headEl;
let inlineScriptCount = 0;
/**
* Actually transform the code.
*/
function transformCode(transformFn, script) {
let source;
if (script.url != null) {
source = script.url;
} else {
source = "Inline Babel script";
inlineScriptCount++;
if (inlineScriptCount > 1) {
source += " (" + inlineScriptCount + ")";
}
}
return transformFn(script.content, {
filename: source,
...buildBabelOptions(script),
}).code;
}
/**
* Builds the Babel options for transforming the specified script, using some
* sensible default presets and plugins if none were explicitly provided.
*/
function buildBabelOptions(script) {
return {
presets: script.presets || ["react", "es2015"],
plugins: script.plugins || [
"transform-class-properties",
"transform-object-rest-spread",
"transform-flow-strip-types",
],
sourceMaps: "inline",
};
}
/**
* Appends a script element at the end of the <head> with the content of code,
* after transforming it.
*/
function run(transformFn, script) {
const scriptEl = document.createElement("script");
scriptEl.text = transformCode(transformFn, script);
headEl.appendChild(scriptEl);
}
/**
* Load script from the provided url and pass the content to the callback.
*/
function load(url, successCallback, errorCallback) {
const xhr = new XMLHttpRequest();
// async, however scripts will be executed in the order they are in the
// DOM to mirror normal script loading.
xhr.open("GET", url, true);
if ("overrideMimeType" in xhr) {
xhr.overrideMimeType("text/plain");
}
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 0 || xhr.status === 200) {
successCallback(xhr.responseText);
} else {
errorCallback();
throw new Error("Could not load " + url);
}
}
};
return xhr.send(null);
}
/**
* Converts a comma-separated data attribute string into an array of values. If
* the string is empty, returns an empty array. If the string is not defined,
* returns null.
*/
function getPluginsOrPresetsFromScript(script, attributeName) {
const rawValue = script.getAttribute(attributeName);
if (rawValue === "") {
// Empty string means to not load ANY presets or plugins
return [];
}
if (!rawValue) {
// Any other falsy value (null, undefined) means we're not overriding this
// setting, and should use the default.
return null;
}
return rawValue.split(",").map(item => item.trim());
}
/**
* Loop over provided script tags and get the content, via innerHTML if an
* inline script, or by using XHR. Transforms are applied if needed. The scripts
* are executed in the order they are found on the page.
*/
function loadScripts(transformFn, scripts) {
const result = [];
const count = scripts.length;
function check() {
let script, i;
for (i = 0; i < count; i++) {
script = result[i];
if (script.loaded && !script.executed) {
script.executed = true;
run(transformFn, script);
} else if (!script.loaded && !script.error && !script.async) {
break;
}
}
}
scripts.forEach((script, i) => {
const scriptData = {
// script.async is always true for non-JavaScript script tags
async: script.hasAttribute("async"),
error: false,
executed: false,
plugins: getPluginsOrPresetsFromScript(script, "data-plugins"),
presets: getPluginsOrPresetsFromScript(script, "data-presets"),
};
if (script.src) {
result[i] = {
...scriptData,
content: null,
loaded: false,
url: script.src,
};
load(
script.src,
content => {
result[i].loaded = true;
result[i].content = content;
check();
},
() => {
result[i].error = true;
check();
},
);
} else {
result[i] = {
...scriptData,
content: script.innerHTML,
loaded: true,
url: null,
};
}
});
check();
}
/**
* Run script tags with type="text/jsx".
* @param {Array} scriptTags specify script tags to run, run all in the <head> if not given
*/
export function runScripts(transformFn, scripts) {
headEl = document.getElementsByTagName("head")[0];
if (!scripts) {
scripts = document.getElementsByTagName("script");
}
// Array.prototype.slice cannot be used on NodeList on IE8
const jsxScripts = [];
for (let i = 0; i < scripts.length; i++) {
const script = scripts.item(i);
// Support the old type="text/jsx;harmony=true"
const type = script.type.split(";")[0];
if (scriptTypes.indexOf(type) !== -1) {
jsxScripts.push(script);
}
}
if (jsxScripts.length === 0) {
return;
}
console.warn(
"You are using the in-browser Babel transformer. Be sure to precompile " +
"your scripts for production - https://babeljs.io/docs/setup/",
);
loadScripts(transformFn, jsxScripts);
}

View File

@ -0,0 +1,137 @@
const assert = require("assert");
const Babel = require("../babel");
// Basic smoke tests for babel-standalone
describe("babel-standalone", () => {
it("handles the es2015-no-commonjs preset", () => {
const output = Babel.transform('const getMessage = () => "Hello World"', {
presets: ["es2015-no-commonjs"],
}).code;
assert.equal(
output,
"var getMessage = function getMessage() {\n" +
' return "Hello World";\n' +
"};",
);
});
it("can translate simple ast", () => {
const ast = {
type: "Program",
start: 0,
end: 2,
directives: [],
body: [
{
type: "ExpressionStatement",
start: 0,
end: 1,
expression: {
type: "NumericLiteral",
start: 0,
end: 2,
value: 42,
raw: "42",
},
},
],
sourceType: "module",
};
const output = Babel.transformFromAst(ast, "42", { presets: ["es2015"] })
.code;
assert.equal(output, '"use strict";\n' + "\n" + "42;");
});
it("handles the react preset", () => {
const output = Babel.transform(
"const someDiv = <div>{getMessage()}</div>",
{
presets: ["react"],
},
).code;
assert.equal(
output,
'const someDiv = React.createElement("div", null, getMessage());',
);
});
it("handles presets with options", () => {
const output = Babel.transform("export let x", {
presets: [["es2015", { modules: false }]],
}).code;
assert.equal(output, "export var x = void 0;");
});
it("handles specifying a plugin by name", () => {
const output = Babel.transform('const getMessage = () => "Hello World"', {
plugins: ["transform-es2015-arrow-functions"],
}).code;
// Transforms arrow syntax but NOT "const".
assert.equal(
output,
"const getMessage = function () {\n" + ' return "Hello World";\n' + "};",
);
});
it("handles plugins with options", () => {
const output = Babel.transform("`${x}`", {
plugins: [["transform-es2015-template-literals", { spec: true }]],
}).code;
assert.equal(
output,
'"".concat(x);', // https://github.com/babel/babel/pull/5791
);
});
it("throws on invalid preset name", () => {
assert.throws(
() => Babel.transform("var foo", { presets: ["lolfail"] }),
/Invalid preset specified in Babel options: "lolfail"/,
);
});
it("throws on invalid plugin name", () => {
assert.throws(
() => Babel.transform("var foo", { plugins: ["lolfail"] }),
/Invalid plugin specified in Babel options: "lolfail"/,
);
});
describe("custom plugins and presets", () => {
const lolizer = () => ({
visitor: {
Identifier(path) {
path.node.name = "LOL";
},
},
});
it("allows custom plugins to be registered", () => {
Babel.registerPlugin("lolizer", lolizer);
const output = Babel.transform(
"function helloWorld() { alert(hello); }",
{ plugins: ["lolizer"] },
);
assert.equal(
output.code,
`function LOL() {
LOL(LOL);
}`,
);
});
it("allows custom presets to be registered", () => {
Babel.registerPreset("lulz", { plugins: [lolizer] });
const output = Babel.transform(
"function helloWorld() { alert(hello); }",
{ presets: ["lulz"] },
);
assert.equal(
output.code,
`function LOL() {
LOL(LOL);
}`,
);
});
});
});

View File

@ -7,6 +7,10 @@ for f in packages/*; do
if [ -n "$TEST_ONLY" ] && [[ `basename $f` != *"$TEST_ONLY"* ]]; then if [ -n "$TEST_ONLY" ] && [[ `basename $f` != *"$TEST_ONLY"* ]]; then
continue continue
fi fi
# Exclude babel-standalone from coverage runs
if [ "$TEST_TYPE" = "cov" ] && [ `basename $f` = 'babel-standalone' ]; then
continue
fi
if [ -d "$f/test" ]; then if [ -d "$f/test" ]; then
TEST_DIRS="$f/test $TEST_DIRS" TEST_DIRS="$f/test $TEST_DIRS"

View File

@ -1,5 +1,6 @@
#!/bin/sh #!/bin/sh
set -e set -e
node_modules/.bin/nyc node_modules/mocha/bin/_mocha --opts test/mocha.opts `scripts/_get-test-directories.sh` testDirs=`TEST_TYPE=cov scripts/_get-test-directories.sh`
node_modules/.bin/nyc node_modules/mocha/bin/_mocha --opts test/mocha.opts $testDirs
node_modules/.bin/nyc report --reporter=json node_modules/.bin/nyc report --reporter=json

817
yarn.lock

File diff suppressed because it is too large Load Diff