From 1a1587cb1c828314974562561345ea2880dadfd1 Mon Sep 17 00:00:00 2001 From: Doug Wade Date: Tue, 21 Jun 2016 14:12:02 -0700 Subject: [PATCH 1/2] Add api and cli for module tagging --- .../react-server-gulp-module-tagger/index.js | 95 +------------ .../package.json | 3 +- packages/react-server-module-tagger/README.md | 25 ++++ packages/react-server-module-tagger/index.js | 129 ++++++++++++++++++ .../react-server-module-tagger/package.json | 30 ++++ packages/react-server-module-tagger/test.js | 32 +++++ 6 files changed, 222 insertions(+), 92 deletions(-) create mode 100644 packages/react-server-module-tagger/README.md create mode 100644 packages/react-server-module-tagger/index.js create mode 100644 packages/react-server-module-tagger/package.json create mode 100644 packages/react-server-module-tagger/test.js diff --git a/packages/react-server-gulp-module-tagger/index.js b/packages/react-server-gulp-module-tagger/index.js index 55fb0cb75..e2aa2b04a 100644 --- a/packages/react-server-gulp-module-tagger/index.js +++ b/packages/react-server-gulp-module-tagger/index.js @@ -1,5 +1,6 @@ var replace = require("gulp-replace") , forEach = require("gulp-foreach") +, loggerSpec = require("react-server-module-tagger") // This pattern matches either of these: // - "__LOGGER__" @@ -9,99 +10,11 @@ var isWindows = ('win32' === process.platform) , THIS_MODULE = isWindows ? /(?:[^\\]+\\node_modules\\)?react-server-gulp-module-tagger\\index\.js$/ : /(?:[^\/]+\/node_modules\/)?react-server-gulp-module-tagger\/index\.js$/ -, BASE_PATH = module.filename.replace(THIS_MODULE,'') -module.exports = function(config){ +module.exports = function(config) { config || (config = {}); + config.basePath = module.filename.replace(THIS_MODULE,''); return forEach(function(stream, file){ return stream.pipe(replace(REPLACE_TOKEN, loggerSpec.bind({file, config}))); - }) + }); } - -var loggerSpec = function(fullMatch, optString){ - var fn = this.file.path - , trim = this.config.trim || '' - , opts = {} - - if (fn.indexOf(BASE_PATH) !== 0) { - throw new Error("Unable to handle "+REPLACE_TOKEN+" for "+fn); - } - - if (optString) { - // The slash replacement here is so we don't choke on example - // loggers in comments. - opts = new Function("return "+optString.replace(/^\/\//mg,''))(); // eslint-disable-line no-new-func - } - - opts.name = getName (fn, opts, trim); - opts.color = getColor (opts); - - return JSON.stringify(opts); -} - -var getName = function(fn, opts, trim){ - var slashPattern = isWindows - ?/\\/g - :/\//g - var name = fn.substring(BASE_PATH.length+trim.length, fn.length) - .replace(/\.jsx?$/, '') - .replace(slashPattern,'.') - if (opts.label) { - name += '.'+opts.label - } - return name; -} - -var getColor = (function(){ - - // ANSI escape sequence on the server. - // CSS rgb(...) color in the browser. - var makeColor = function(r,g,b){ - return { - server: 16 + r*36 + g*6 + b, - client: "rgb("+[ - (r*42.5)|0, - (g*42.5)|0, - (b*42.5)|0, - ].join(',')+")", - } - } - - // This produces a list of 24 colors that are distant enough from each - // other to be visually distinct. It's also, conveniently, the same - // palette client side and server side. - var colors = []; - for (var r = 1; r < 6; r+=2) { - for (var g = 1; g < 6; g+=2) { - for (var b = 1; b < 6; b+=2) { - if (r !== g || g !== b) { // No gray. - colors.push(makeColor(r,g,b)); - } - } - } - } - - - // Just want a fairly well distributed deterministic mapping. - // - // Adapted from: - // http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery - var hash = function(str){ - var hash = 0, i, chr, len; - if (str.length === 0) return hash; - for (i = 0, len = str.length; i < len; i++) { - chr = str.charCodeAt(i); - hash = ((hash << 5) - hash) + chr; - hash |= 0; // Convert to 32bit integer - } - - len = colors.length; - - // Positive mod. - return (hash%len+len)%len; - } - - return function(opts){ - return colors[hash(opts.name)]; - } -})(); diff --git a/packages/react-server-gulp-module-tagger/package.json b/packages/react-server-gulp-module-tagger/package.json index 0dce5aee8..0ca0295db 100644 --- a/packages/react-server-gulp-module-tagger/package.json +++ b/packages/react-server-gulp-module-tagger/package.json @@ -16,7 +16,8 @@ "dependencies": { "gulp-foreach": "0.1.0", "gulp-plumber": "^1.1.0", - "gulp-replace": "0.5.2" + "gulp-replace": "0.5.2", + "react-server-module-tagger": "0.0.1" }, "devDependencies": { "ava": "^0.15.2", diff --git a/packages/react-server-module-tagger/README.md b/packages/react-server-module-tagger/README.md new file mode 100644 index 000000000..ee662c30e --- /dev/null +++ b/packages/react-server-module-tagger/README.md @@ -0,0 +1,25 @@ +# react-server-module-tagger + +A function for tagging [react-server](https://www.npmjs.com/package/react-server) +logger instances with information about the module they're being used in. + +To transpile your source for use with +[React Server](https://www.npmjs.com/package/react-server), install gulp and the plugin + +```shell +npm i -D gulp react-server-module-tagger +``` + +Then require and call the function. The tagger expects to have config and file +data on its prototype, so use `.bind`. + +```javascript +const tagger = require('react-server-module-tagger'); +const filepath = 'path/to/my/output.js'; +const optString = '({label:"foo"})' +const moduleTag = tagger.bind({ file: { path: filepath }, config: { trim: 'path/to'} })(filepath, optString)); +``` + +returns a logger instance that will have consistent coloring on the server and +the client, and that has a human-friendly, readable name that easily maps to +the file tree (in this example `components.my-feature.foo`). diff --git a/packages/react-server-module-tagger/index.js b/packages/react-server-module-tagger/index.js new file mode 100644 index 000000000..28a59c4ce --- /dev/null +++ b/packages/react-server-module-tagger/index.js @@ -0,0 +1,129 @@ +var isWindows = ('win32' === process.platform); + +/** + * A util function for tagging modules. Expects to find data on its prototype + * as follows + * { + * file: { + * path: the path to the file to tag + * } + * config: { + * trim: the string to trim off the front of the logger name + * } + * } + * @example + * const file = '/path/to/my/file.js'; + * loggerSpec.bind({file, { trim: 'path.to.' }})(file, '({label: "foo"})') + * // returns '{\"label\":\"foo\",\"name\":\"my.file\",\"color\":{\"server\":87,\"client\":\"rgb(42,212,212)\"}}' + * @param {String} fullMatch May also be provided as this.file.path, the path to the file + * @param {String} optString The label to add to the module tag, in the form '({label:"$label"})' + * @return {String} A json object containing a module identifier + */ +module.exports = function(fullMatch, optString){ + var fn = this.file && this.file.path ? this.file.path : fullMatch + , trim = this.config.trim || '' + , basePath = this.config.basePath || '' + , opts = {} + + if (fn.indexOf(basePath) !== 0) { + throw new Error("Unable to handle " + basePath + " for " + fn); + } + + if (optString) { + // The slash replacement here is so we don't choke on example + // loggers in comments. + opts = new Function("return "+optString.replace(/^\/\//mg,''))(); // eslint-disable-line no-new-func + } + + opts.name = getName (fn, opts, trim, basePath); + opts.color = getColor (opts); + + return JSON.stringify(opts); +} + +/** + * Gets the name of a logger from its filepath. + * @example + * getName( + * 'my-component', + * { label: 'sub' }, + * 'my-project.src', + * 'my-project/src/components/my-component.js' + * ) // returns "components.my-component" + * @param {String} fn filename + * @param {Object} opts { label: 'Optional logger label' } + * @param {String} trim The leading portion of the name to remove. + * @param {String} basePath The path to the file + * @return {String} The logger name, e.g. my-project.components.my-component + */ +var getName = function(fn, opts, trim, basePath){ + var slashPattern = isWindows + ?/\\/g + :/\//g + var name = fn.substring(basePath.length+trim.length, fn.length) + .replace(/\.jsx?$/, '') + .replace(slashPattern,'.') + if (opts.label) { + name += '.'+opts.label + } + return name; +} + +/** + * Gets isomorphic color objects from filenames. + * @param {String} filename + * @return {Object} An isomorphic color object in the form {"color":{"server":147,"client":"rgb(127,127,212)"}} + */ +var getColor = (function(){ + + // ANSI escape sequence on the server. + // CSS rgb(...) color in the browser. + var makeColor = function(r,g,b){ + return { + server: 16 + r*36 + g*6 + b, + client: "rgb("+[ + (r*42.5)|0, + (g*42.5)|0, + (b*42.5)|0, + ].join(',')+")", + } + } + + // This produces a list of 24 colors that are distant enough from each + // other to be visually distinct. It's also, conveniently, the same + // palette client side and server side. + var colors = []; + for (var r = 1; r < 6; r+=2) { + for (var g = 1; g < 6; g+=2) { + for (var b = 1; b < 6; b+=2) { + if (r !== g || g !== b) { // No gray. + colors.push(makeColor(r,g,b)); + } + } + } + } + + + // Just want a fairly well distributed deterministic mapping. + // + // Adapted from: + // http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery + var hash = function(str){ + var hash = 0, i, chr, len; + if (str.length === 0) return hash; + for (i = 0, len = str.length; i < len; i++) { + chr = str.charCodeAt(i); + hash = ((hash << 5) - hash) + chr; + hash |= 0; // Convert to 32bit integer + } + + len = colors.length; + + // Positive mod. + return (hash%len+len)%len; + } + + return function(opts){ + return colors[hash(opts.name)]; + } +})(); diff --git a/packages/react-server-module-tagger/package.json b/packages/react-server-module-tagger/package.json new file mode 100644 index 000000000..2d5258965 --- /dev/null +++ b/packages/react-server-module-tagger/package.json @@ -0,0 +1,30 @@ +{ + "name": "react-server-module-tagger", + "version": "0.0.1", + "description": "calculates module level config", + "main": "index.js", + "scripts": { + "test": "ava test.js", + "clean": "del index.js npm-debug.log*" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/redfin/react-server.git" + }, + "keywords": [ + "react-server" + ], + "author": "Doug Wade ", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/redfin/react-server/issues" + }, + "homepage": "https://github.com/redfin/react-server#readme", + "devDependencies": { + "ava": "^0.15.2", + "babel-cli": "^6.9.0", + "babel-preset-es2015": "^6.9.0", + "babel-preset-stage-0": "^6.5.0", + "del-cli": "^0.2.0" + } +} diff --git a/packages/react-server-module-tagger/test.js b/packages/react-server-module-tagger/test.js new file mode 100644 index 000000000..55f99cec9 --- /dev/null +++ b/packages/react-server-module-tagger/test.js @@ -0,0 +1,32 @@ +import test from 'ava'; +import loggerSpec from '.'; + +test('creates a module tag', t => { + const expected = '{\"name\":\"foo.bar\",\"color\":{\"server\":73,\"client\":\"rgb(42,127,127)\"}}'; + + const file = 'foo/bar'; + const config = {}; + const actual = loggerSpec.bind({file, config})(file); + + t.is(expected, actual); +}); + +test('trims prefix from module tag name', t => { + const expected = '{\"name\":\"quux\",\"color\":{\"server\":229,\"client\":\"rgb(212,212,127)\"}}'; + + const file = 'baz/quux'; + const config = { trim: 'baz.' }; + const actual = loggerSpec.bind({file, config})(file); + + t.is(expected, actual); +}); + +test('adds labels', t => { + const expected = '{\"label\":\"foo\",\"name\":\"has.label.foo\",\"color\":{\"server\":131,\"client\":\"rgb(127,42,42)\"}}'; + + const file = 'has/label'; + const config = {}; + const actual = loggerSpec.bind({file, config})(file, '({label: "foo"})'); + + t.is(expected, actual); +}); From 4b4b40050ba0487cdaefb019833cdd2d60fd34f6 Mon Sep 17 00:00:00 2001 From: Doug Wade Date: Tue, 21 Jun 2016 14:28:41 -0700 Subject: [PATCH 2/2] Add module tagging babel plugin --- packages/babel-plugin-react-server/.babelrc | 3 + packages/babel-plugin-react-server/.gitignore | 3 + packages/babel-plugin-react-server/.npmignore | 3 + packages/babel-plugin-react-server/README.md | 90 +++++++++++++++++++ .../babel-plugin-react-server/package.json | 31 +++++++ .../babel-plugin-react-server/src/index.js | 34 +++++++ .../test/fixtures/configurable-token/.babelrc | 5 ++ .../fixtures/configurable-token/actual.js | 1 + .../fixtures/configurable-token/expected.js | 1 + .../test/fixtures/example/.babelrc | 5 ++ .../test/fixtures/example/actual.js | 1 + .../test/fixtures/example/expected.js | 1 + .../fixtures/reserved-future-tokens/.babelrc | 5 ++ .../fixtures/reserved-future-tokens/actual.js | 2 + .../reserved-future-tokens/expected.js | 2 + .../test/fixtures/trim/.babelrc | 5 ++ .../test/fixtures/trim/actual.js | 1 + .../test/fixtures/trim/expected.js | 1 + .../babel-plugin-react-server/test/index.js | 26 ++++++ packages/babel-preset-react-server/index.js | 16 +--- .../babel-preset-react-server/package.json | 20 ++--- packages/babel-preset-react-server/test.js | 37 ++++++++ .../babel-preset-react-server/tst/expected.js | 7 ++ .../babel-preset-react-server/tst/source.js | 5 ++ 24 files changed, 280 insertions(+), 25 deletions(-) create mode 100644 packages/babel-plugin-react-server/.babelrc create mode 100644 packages/babel-plugin-react-server/.gitignore create mode 100644 packages/babel-plugin-react-server/.npmignore create mode 100644 packages/babel-plugin-react-server/README.md create mode 100644 packages/babel-plugin-react-server/package.json create mode 100644 packages/babel-plugin-react-server/src/index.js create mode 100644 packages/babel-plugin-react-server/test/fixtures/configurable-token/.babelrc create mode 100644 packages/babel-plugin-react-server/test/fixtures/configurable-token/actual.js create mode 100644 packages/babel-plugin-react-server/test/fixtures/configurable-token/expected.js create mode 100644 packages/babel-plugin-react-server/test/fixtures/example/.babelrc create mode 100644 packages/babel-plugin-react-server/test/fixtures/example/actual.js create mode 100644 packages/babel-plugin-react-server/test/fixtures/example/expected.js create mode 100644 packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/.babelrc create mode 100644 packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/actual.js create mode 100644 packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/expected.js create mode 100644 packages/babel-plugin-react-server/test/fixtures/trim/.babelrc create mode 100644 packages/babel-plugin-react-server/test/fixtures/trim/actual.js create mode 100644 packages/babel-plugin-react-server/test/fixtures/trim/expected.js create mode 100644 packages/babel-plugin-react-server/test/index.js create mode 100644 packages/babel-preset-react-server/test.js create mode 100644 packages/babel-preset-react-server/tst/expected.js create mode 100644 packages/babel-preset-react-server/tst/source.js diff --git a/packages/babel-plugin-react-server/.babelrc b/packages/babel-plugin-react-server/.babelrc new file mode 100644 index 000000000..eaf32387b --- /dev/null +++ b/packages/babel-plugin-react-server/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015", "stage-0"] +} diff --git a/packages/babel-plugin-react-server/.gitignore b/packages/babel-plugin-react-server/.gitignore new file mode 100644 index 000000000..45f722230 --- /dev/null +++ b/packages/babel-plugin-react-server/.gitignore @@ -0,0 +1,3 @@ +node_modules +*.log +lib diff --git a/packages/babel-plugin-react-server/.npmignore b/packages/babel-plugin-react-server/.npmignore new file mode 100644 index 000000000..cace0d6dd --- /dev/null +++ b/packages/babel-plugin-react-server/.npmignore @@ -0,0 +1,3 @@ +node_modules +*.log +src diff --git a/packages/babel-plugin-react-server/README.md b/packages/babel-plugin-react-server/README.md new file mode 100644 index 000000000..765ded6e6 --- /dev/null +++ b/packages/babel-plugin-react-server/README.md @@ -0,0 +1,90 @@ +# babel-plugin-react-server + +React Server transpilation + +## Example + +**In** + +```js +var logger = require('react-server').logging.getLogger(__LOGGER__); +``` + +**Out** + +```js +"use strict"; + +var logger = require('react-server').logging.getLogger({ name: 'module.name', color: {} }); +``` + +## Installation + +```sh +$ npm install babel-plugin-react-server +``` + +## Usage + +### Via `.babelrc` (Recommended) + +**.babelrc** + +```json +{ + "plugins": ["react-server"] +} +``` + +### Via CLI + +```sh +$ babel --plugins react-server script.js +``` + +### Via Node API + +```javascript +require("babel-core").transform("code", { + plugins: ["react-server"] +}); +``` + + +## Configuration + +A fully configured babel plugin in your babelrc would look be + +```json +{ + "plugins": [ + ["react-server", { + "trim": "my-project.components.", + "token": "__LOGGER__" + }] + ] +} +``` + + +### Trim + +A substring to trim off the front of the module name + +```javascript +{ + trim: "my-project.pages." +} +``` + +### Token + +The token to replace in the source code with the module tag. By default, uses +the default logger token `__LOGGER__`, and two future reserved tokens, +`__CHANNEL__` and + +```javascript +{ + token: "__LOGGER__" +} +``` diff --git a/packages/babel-plugin-react-server/package.json b/packages/babel-plugin-react-server/package.json new file mode 100644 index 000000000..84a18e853 --- /dev/null +++ b/packages/babel-plugin-react-server/package.json @@ -0,0 +1,31 @@ +{ + "name": "babel-plugin-react-server", + "version": "0.0.1", + "description": "Babel plugin for React Server transpilation", + "repository": "redfin/babel-plugin-react-server", + "author": "Doug Wade ", + "main": "lib/index.js", + "dependencies": { + "react-server-module-tagger": "^0.0.1" + }, + "devDependencies": { + "babel-core": "^6.3.17", + "babel-preset-es2015": "^6.3.13", + "babel-preset-stage-0": "^6.3.13", + "mocha": "^2.2.5" + }, + "scripts": { + "clean": "rm -rf lib npm-debug.log*", + "build": "babel src -d lib", + "test": "mocha --compilers js:babel-register", + "test:watch": "npm run test -- --watch", + "prepublish": "npm run clean && npm run build" + }, + "keywords": [ + "react", + "server", + "babel", + "plugin", + "babel-plugin" + ] +} diff --git a/packages/babel-plugin-react-server/src/index.js b/packages/babel-plugin-react-server/src/index.js new file mode 100644 index 000000000..9a96b8b38 --- /dev/null +++ b/packages/babel-plugin-react-server/src/index.js @@ -0,0 +1,34 @@ +import loggerSpec from 'react-server-module-tagger'; +import path from 'path'; + +module.exports = function({types: t }) { + return { + visitor: { + Identifier(p, state) { + const {node} = p; + const {name, type} = node; + + const config = { trim: state.opts.trim }; + const parent = path.resolve(path.join(process.cwd(), '..')) + path.sep; + const fp = this.file.opts.filename.replace(parent, ''); + const file = { path: fp }; + //TODO: Support labels + const moduleTag = loggerSpec.bind({ file, config })(fp); + + let tokens; + if (state.opts.tokens) { + tokens = new Set(state.opts.tokens); + } else { + tokens = new Set(["__LOGGER__", "__CHANNEL__", "__CACHE__"]); + } + + if (tokens.has(name)) { + // this strikes me as a dirty, nasty hack. I think it would be better + // to parse the object as json and coerce it to an array of + // ObjectProperties to construct an ObjectExpression + p.node.name = moduleTag; + } + } + } + }; +} diff --git a/packages/babel-plugin-react-server/test/fixtures/configurable-token/.babelrc b/packages/babel-plugin-react-server/test/fixtures/configurable-token/.babelrc new file mode 100644 index 000000000..b665985c3 --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/configurable-token/.babelrc @@ -0,0 +1,5 @@ +{ + "plugins": [ + ["../../../src", { "tokens": ["BAR"] }] + ] +} diff --git a/packages/babel-plugin-react-server/test/fixtures/configurable-token/actual.js b/packages/babel-plugin-react-server/test/fixtures/configurable-token/actual.js new file mode 100644 index 000000000..b79db47ce --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/configurable-token/actual.js @@ -0,0 +1 @@ +var logger = require('react-server').logging.getLogger(BAR); diff --git a/packages/babel-plugin-react-server/test/fixtures/configurable-token/expected.js b/packages/babel-plugin-react-server/test/fixtures/configurable-token/expected.js new file mode 100644 index 000000000..ad5807635 --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/configurable-token/expected.js @@ -0,0 +1 @@ +var logger = require('react-server').logging.getLogger({"name":"babel-plugin-react-server.test.fixtures.configurable-token.actual","color":{"server":133,"client":"rgb(127,42,127)"}}); diff --git a/packages/babel-plugin-react-server/test/fixtures/example/.babelrc b/packages/babel-plugin-react-server/test/fixtures/example/.babelrc new file mode 100644 index 000000000..e624888ed --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/example/.babelrc @@ -0,0 +1,5 @@ +{ + "plugins": [ + ["../../../src"] + ] +} diff --git a/packages/babel-plugin-react-server/test/fixtures/example/actual.js b/packages/babel-plugin-react-server/test/fixtures/example/actual.js new file mode 100644 index 000000000..861cdc1c7 --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/example/actual.js @@ -0,0 +1 @@ +var logger = require('react-server').logging.getLogger(__LOGGER__); diff --git a/packages/babel-plugin-react-server/test/fixtures/example/expected.js b/packages/babel-plugin-react-server/test/fixtures/example/expected.js new file mode 100644 index 000000000..1786e179c --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/example/expected.js @@ -0,0 +1 @@ +var logger = require('react-server').logging.getLogger({"name":"babel-plugin-react-server.test.fixtures.example.actual","color":{"server":131,"client":"rgb(127,42,42)"}}); diff --git a/packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/.babelrc b/packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/.babelrc new file mode 100644 index 000000000..e624888ed --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/.babelrc @@ -0,0 +1,5 @@ +{ + "plugins": [ + ["../../../src"] + ] +} diff --git a/packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/actual.js b/packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/actual.js new file mode 100644 index 000000000..4d86c7533 --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/actual.js @@ -0,0 +1,2 @@ +__CHANNEL__ +__CACHE__ diff --git a/packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/expected.js b/packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/expected.js new file mode 100644 index 000000000..93c600a0b --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/reserved-future-tokens/expected.js @@ -0,0 +1,2 @@ +{"name":"babel-plugin-react-server.test.fixtures.reserved-future-tokens.actual","color":{"server":159,"client":"rgb(127,212,212)"}}; +{"name":"babel-plugin-react-server.test.fixtures.reserved-future-tokens.actual","color":{"server":159,"client":"rgb(127,212,212)"}}; diff --git a/packages/babel-plugin-react-server/test/fixtures/trim/.babelrc b/packages/babel-plugin-react-server/test/fixtures/trim/.babelrc new file mode 100644 index 000000000..d6b576f6a --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/trim/.babelrc @@ -0,0 +1,5 @@ +{ + "plugins": [ + ["../../../src", { "trim": "babel-plugin-react-server.test.fixtures." }] + ] +} diff --git a/packages/babel-plugin-react-server/test/fixtures/trim/actual.js b/packages/babel-plugin-react-server/test/fixtures/trim/actual.js new file mode 100644 index 000000000..861cdc1c7 --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/trim/actual.js @@ -0,0 +1 @@ +var logger = require('react-server').logging.getLogger(__LOGGER__); diff --git a/packages/babel-plugin-react-server/test/fixtures/trim/expected.js b/packages/babel-plugin-react-server/test/fixtures/trim/expected.js new file mode 100644 index 000000000..7e6a51df3 --- /dev/null +++ b/packages/babel-plugin-react-server/test/fixtures/trim/expected.js @@ -0,0 +1 @@ +var logger = require('react-server').logging.getLogger({"name":"trim.actual","color":{"server":207,"client":"rgb(212,42,212)"}}); diff --git a/packages/babel-plugin-react-server/test/index.js b/packages/babel-plugin-react-server/test/index.js new file mode 100644 index 000000000..9ee8d81b9 --- /dev/null +++ b/packages/babel-plugin-react-server/test/index.js @@ -0,0 +1,26 @@ +import path from 'path'; +import fs from 'fs'; +import assert from 'assert'; +import { transformFileSync } from 'babel-core'; +import plugin from '../src'; + +function trim(str) { + return str.replace(/^\s+|\s+$/, ''); +} + +describe('React Server transpilation', () => { + const fixturesDir = path.join(__dirname, 'fixtures'); + fs.readdirSync(fixturesDir).map((caseName) => { + it(`should ${caseName.split('-').join(' ')}`, () => { + const fixtureDir = path.join(fixturesDir, caseName); + const actualPath = path.join(fixtureDir, 'actual.js'); + const actual = transformFileSync(actualPath).code; + + const expected = fs.readFileSync( + path.join(fixtureDir, 'expected.js') + ).toString(); + + assert.equal(trim(actual), trim(expected)); + }); + }); +}); diff --git a/packages/babel-preset-react-server/index.js b/packages/babel-preset-react-server/index.js index e75605d2f..d306467c1 100644 --- a/packages/babel-preset-react-server/index.js +++ b/packages/babel-preset-react-server/index.js @@ -1,19 +1,11 @@ module.exports = { plugins: [ - require('babel-plugin-transform-es2015-arrow-functions'), - require('babel-plugin-transform-es2015-block-scoping'), - require('babel-plugin-transform-es2015-classes'), - require('babel-plugin-transform-es2015-computed-properties'), - require('babel-plugin-transform-es2015-constants'), - require('babel-plugin-transform-es2015-destructuring'), - require('babel-plugin-transform-es2015-modules-commonjs'), - require('babel-plugin-transform-es2015-parameters'), - require('babel-plugin-transform-es2015-shorthand-properties'), - require('babel-plugin-transform-es2015-spread'), - require('babel-plugin-transform-es2015-template-literals'), - require('babel-plugin-transform-object-rest-spread'), + require('babel-plugin-react-server'), + require('babel-plugin-transform-runtime'), ], presets: [ + require('babel-preset-es2015'), require('babel-preset-react'), + require('babel-preset-stage-0'), ], } diff --git a/packages/babel-preset-react-server/package.json b/packages/babel-preset-react-server/package.json index 703d9c8d3..10789a263 100644 --- a/packages/babel-preset-react-server/package.json +++ b/packages/babel-preset-react-server/package.json @@ -18,21 +18,15 @@ "author": "Doug Wade ", "license": "Apache License 2.0", "dependencies": { - "babel-plugin-transform-es2015-arrow-functions": "^6.3.13", - "babel-plugin-transform-es2015-block-scoping": "^6.3.13", - "babel-plugin-transform-es2015-classes": "^6.3.13", - "babel-plugin-transform-es2015-computed-properties": "^6.3.13", - "babel-plugin-transform-es2015-constants": "^6.1.4", - "babel-plugin-transform-es2015-destructuring": "^6.3.13", - "babel-plugin-transform-es2015-modules-commonjs": "^6.3.13", - "babel-plugin-transform-es2015-parameters": "^6.3.13", - "babel-plugin-transform-es2015-shorthand-properties": "^6.3.13", - "babel-plugin-transform-es2015-spread": "^6.3.13", - "babel-plugin-transform-es2015-template-literals": "^6.3.13", - "babel-plugin-transform-object-rest-spread": "^6.3.13", - "babel-preset-react": "^6.5.0" + "babel-plugin-transform-runtime": "^6.9.0", + "babel-plugin-react-server": "^0.0.1", + "babel-preset-es2015": "^6.5.0", + "babel-preset-react": "^6.5.0", + "babel-preset-stage-0": "^6.5.0" }, "devDependencies": { + "ava": "^0.15.2", + "babel-core": "^6.10.4", "rimraf": "^2.5.2" } } diff --git a/packages/babel-preset-react-server/test.js b/packages/babel-preset-react-server/test.js new file mode 100644 index 000000000..df93cdaea --- /dev/null +++ b/packages/babel-preset-react-server/test.js @@ -0,0 +1,37 @@ +import test from 'ava'; +import fs from 'fs'; +import { transform } from 'babel-core'; + +test('module can be required', t => { + try { + require('.'); + t.pass(); + } catch (e) { + console.error(e); + t.fail(); + } +}); + +test('transpiles as expected', async t => { + const source = await readFile('tst/source.js'); + const actual = transform(source, { presets: [require('.')] }).code; + const expected = await readFile('tst/expected.js'); + t.is(trim(actual), trim(expected)); +}); + +function readFile(filename) { + return new Promise((resolve, reject) => { + fs.readFile(filename, (err, data) => { + if (err) { + console.error(err); + reject(err); + } else { + resolve(data.toString()); + } + }); + }); +} + +function trim(str) { + return str.replace(/^\s+|\s+$/, ''); +} diff --git a/packages/babel-preset-react-server/tst/expected.js b/packages/babel-preset-react-server/tst/expected.js new file mode 100644 index 000000000..a262de628 --- /dev/null +++ b/packages/babel-preset-react-server/tst/expected.js @@ -0,0 +1,7 @@ +'use strict'; + +var _reactServer = require('react-server'); + +var label = 'foo'; +var logger = _reactServer.logging.getLogger({"name":"unknown","color":{"server":207,"client":"rgb(212,42,212)"}}); +var fooLogger = _reactServer.logging.getLogger({"name":"unknown","color":{"server":207,"client":"rgb(212,42,212)"}}({ label: label })); diff --git a/packages/babel-preset-react-server/tst/source.js b/packages/babel-preset-react-server/tst/source.js new file mode 100644 index 000000000..9217358d9 --- /dev/null +++ b/packages/babel-preset-react-server/tst/source.js @@ -0,0 +1,5 @@ +import {logging} from 'react-server'; + +const label = 'foo'; +const logger = logging.getLogger(__LOGGER__); +const fooLogger = logging.getLogger(__LOGGER__({ label }));