Worked out react bundle (not yet working though)

This commit is contained in:
jos 2016-12-26 10:18:26 +01:00
parent 785ab5205c
commit 2e434f49f9
15 changed files with 250 additions and 168 deletions

1
.gitignore vendored
View File

@ -2,5 +2,6 @@
dist dist
downloads downloads
node_modules node_modules
flow-typed
*.zip *.zip
npm-debug.log npm-debug.log

View File

@ -1,94 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>React component | JSONEditor</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.4.4/babel.min.js"></script>
</head>
<body>
<p>
This demo shows how to load JSONEditor as a React Component
</p>
<div id="root"></div>
<!-- load JSONEditor -->
<script src="../dist/jsoneditor.js"></script>
<script>
// FIXME: should use JSONEditor source code instead of bundled version (multiple versions of React can give conflicts)
// use React and ReactDOM as embedded in the library
const React = jsoneditor.React
const ReactDOM = jsoneditor.ReactDOM
</script>
<script type="text/babel">
// FIXME: should use JSONEditor source code instead of bundled version (multiple versions of React can give conflicts)
// Note that in a full React application, the editor would be loaded as:
// import {JSONEditor} from 'jsoneditor'
const JSONEditor = jsoneditor.JSONEditor
const json = {
'array': [1, 2, 3],
'boolean': true,
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
}
class App extends React.Component {
constructor (props) {
super(props)
this.state = {
text: JSON.stringify(json, null, 2)
}
this.onChange = this.onChange.bind(this)
this.onChangeText = this.onChangeText.bind(this)
}
render () {
return <JSONEditor
mode="code"
modes={['text', 'code', 'tree', 'form', 'view']}
text={this.state.text}
onChange={this.onChange}
onChangeText={this.onChangeText}
/>
}
onChange (json) {
console.log('onChange', json)
}
onChangeText (text) {
console.log('onChangeText', text)
this.setState({ text })
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
</script>
<script>
Array.prototype.slice
.call(document.querySelectorAll('script[type="text/babel"]'))
.forEach(function(script) {
var el = document.createElement('script');
el.innerHTML = Babel.transform(script.innerText, { presets: ['es2015', 'react'] }).code;
script.parentNode.insertBefore(el, script);
});
</script>
</body>
</html>

15
examples/react_demo/.gitignore vendored Executable file
View File

@ -0,0 +1,15 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
node_modules
# testing
coverage
# production
build
# misc
.DS_Store
.env
npm-debug.log

3
examples/react_demo/README.md Executable file
View File

@ -0,0 +1,3 @@
# JSONEditor React demo
TODO: describe the demo

View File

@ -0,0 +1,18 @@
{
"name": "react_demo",
"version": "0.1.0",
"private": true,
"devDependencies": {
"react-scripts": "0.8.4"
},
"dependencies": {
"react": "15.4.1",
"react-dom": "15.4.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}

View File

@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>React demo | JSONeditor</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

View File

52
examples/react_demo/src/App.js Executable file
View File

@ -0,0 +1,52 @@
import React, { Component } from 'react'
import './App.css'
// Load the react version of JSONEditor
//
// When installed via npm, import as:
//
// import JSONEditor from 'jsoneditor/react'
//
import JSONEditor from '../../../react'
const json = {
'array': [1, 2, 3],
'boolean': true,
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
}
class App extends Component {
state = {
text: JSON.stringify(json)
}
render() {
return (
<div className="App">
<JSONEditor
mode="tree"
modes={['text', 'code', 'tree', 'form', 'view']}
text={this.state.text}
onChange={this.onChange}
onChangeText={this.onChangeText}
/>
</div>
)
}
onChange = (json) => {
console.log('onChange', json)
}
onChangeText = (text) => {
console.log('onChangeText', text)
this.setState({ text })
}
}
export default App

View File

@ -0,0 +1,5 @@
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}

View File

@ -0,0 +1,9 @@
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './index.css'
ReactDOM.render(
<App />,
document.getElementById('root')
)

View File

@ -1,13 +1,14 @@
var fs = require('fs') const fs = require('fs')
var gulp = require('gulp') const gulp = require('gulp')
var gutil = require('gulp-util') const gulpMultiProcess = require('gulp-multi-process')
var shell = require('gulp-shell') const gutil = require('gulp-util')
var mkdirp = require('mkdirp') const shell = require('gulp-shell')
var webpack = require('webpack') const mkdirp = require('mkdirp')
var browserSync = require('browser-sync').create() const webpack = require('webpack')
const browserSync = require('browser-sync').create()
var WATCH = 'watch' const WATCH = 'watch'
var WATCHING = process.argv[2] === WATCH const WATCHING = process.argv[2] === WATCH
if (WATCHING) { if (WATCHING) {
gutil.log('Watching src/*.') gutil.log('Watching src/*.')
@ -16,29 +17,44 @@ if (WATCHING) {
gutil.log('Also, ./dist/minimalist code is not updated on changes.') gutil.log('Also, ./dist/minimalist code is not updated on changes.')
} }
var NAME = 'jsoneditor' const NAME = 'jsoneditor.js'
var NAME_MINIMALIST = 'jsoneditor-minimalist' const NAME_MINIMALIST = 'jsoneditor-minimalist.js'
var ENTRY = './src/index.js' const NAME_REACT = 'jsoneditor-react.js'
var HEADER = './src/header.js' const NAME_REACT_MINIMALIST = 'jsoneditor-react-minimalist.js'
var DIST = './dist' const ENTRY = './src/index.js'
var EMPTY = __dirname + '/src/utils/empty.js' const ENTRY_REACT = './src/components/JSONEditor.js'
const HEADER = './src/header.js'
const DIST = './dist'
const EMPTY = __dirname + '/src/utils/empty.js'
// generate banner with today's date and correct version // generate banner with today's date and correct version
function createBanner() { function createBanner() {
var today = gutil.date(new Date(), 'yyyy-mm-dd') // today, formatted as yyyy-mm-dd const today = gutil.date(new Date(), 'yyyy-mm-dd') // today, formatted as yyyy-mm-dd
var version = require('./package.json').version // math.js version const version = require('./package.json').version // math.js version
return String(fs.readFileSync(HEADER)) return String(fs.readFileSync(HEADER))
.replace('@@date', today) .replace('@@date', today)
.replace('@@version', version) .replace('@@version', version)
} }
var bannerPlugin = new webpack.BannerPlugin(createBanner(), { const bannerPlugin = new webpack.BannerPlugin(createBanner(), {
entryOnly: true, entryOnly: true,
raw: true raw: true
}) })
var loaders = [ const minifyPlugin = new webpack.optimize.UglifyJsPlugin()
const excludeAcePlugin = new webpack.NormalModuleReplacementPlugin(new RegExp('/assets/ace$'), EMPTY)
const excludeAjvPlugin = new webpack.NormalModuleReplacementPlugin(new RegExp('^ajv$'), EMPTY)
const productionEnvPlugin = new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
})
const loaders = [
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }, { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' },
{ test: /\.json$/, loader: 'json' }, { test: /\.json$/, loader: 'json' },
{ test: /\.less$/, loaders: '!style!css!less!' }, { test: /\.less$/, loaders: '!style!css!less!' },
@ -46,61 +62,100 @@ var loaders = [
] ]
// create a single instance of the compiler to allow caching // create a single instance of the compiler to allow caching
var plugins = [ const compiler = webpack({
bannerPlugin
]
if (!WATCHING) {
plugins.push(new webpack.optimize.UglifyJsPlugin())
plugins.push(new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}))
}
var compiler = webpack({
entry: ENTRY, entry: ENTRY,
devtool: 'source-map', devtool: 'source-map',
debug: true, debug: true,
cache: true,
bail: true, bail: true,
output: { output: {
library: 'jsoneditor', library: 'jsoneditor',
libraryTarget: 'umd', libraryTarget: 'umd',
path: DIST, path: DIST,
filename: NAME + '.js' filename: NAME
}, },
plugins: plugins, plugins: WATCHING
? [bannerPlugin]
: [bannerPlugin, productionEnvPlugin, minifyPlugin],
module: { module: {
loaders: loaders loaders
}, }
cache: true
}) })
// create a single instance of the compiler to allow caching // create a single instance of the compiler to allow caching
var compilerMinimalist = webpack({ const compilerMinimalist = webpack({
entry: ENTRY, entry: ENTRY,
devtool: 'source-map', devtool: 'source-map',
debug: true, debug: true,
cache: true,
output: { output: {
library: 'jsoneditor', library: 'jsoneditor',
libraryTarget: 'umd', libraryTarget: 'umd',
path: DIST, path: DIST,
filename: NAME_MINIMALIST + '.js' filename: NAME_MINIMALIST
}, },
plugins: [ plugins: [
bannerPlugin, bannerPlugin,
new webpack.NormalModuleReplacementPlugin(new RegExp('/assets/ace$'), EMPTY), productionEnvPlugin,
new webpack.NormalModuleReplacementPlugin(new RegExp('^ajv$'), EMPTY), excludeAcePlugin,
new webpack.optimize.UglifyJsPlugin(), excludeAjvPlugin,
new webpack.DefinePlugin({ minifyPlugin
'process.env': {
NODE_ENV: JSON.stringify('production')
}
})
], ],
module: { module: {
loaders: loaders loaders
}
})
const externals = {
'react': 'commonjs react'
}
// FIXME: get the react bundles working
// create a single instance of the compiler to allow caching
const compilerReact = webpack({
entry: ENTRY_REACT,
devtool: 'source-map',
debug: true,
cache: true,
bail: true,
output: {
path: DIST,
filename: NAME_REACT
}, },
cache: true plugins: [
bannerPlugin,
productionEnvPlugin,
minifyPlugin
],
module: {
loaders
},
externals
})
// FIXME: get the react bundles working
// create a single instance of the compiler to allow caching
const compilerReactMinimalist = webpack({
entry: ENTRY_REACT,
devtool: 'source-map',
debug: true,
cache: true,
bail: true,
output: {
path: DIST,
filename: NAME_REACT_MINIMALIST
},
plugins: [
bannerPlugin,
productionEnvPlugin,
excludeAcePlugin,
excludeAjvPlugin,
minifyPlugin
],
module: {
loaders
},
externals
}) })
function handleCompilerCallback (err, stats) { function handleCompilerCallback (err, stats) {
@ -116,41 +171,38 @@ function handleCompilerCallback (err, stats) {
} }
} }
function createBundleTask (compiler) {
return function (done) {
// update the banner contents (has a date in it which should stay up to date)
bannerPlugin.banner = createBanner()
compiler.run(function (err, stats) {
handleCompilerCallback(err, stats)
done()
})
}
}
// make dist folder // make dist folder
gulp.task('mkdir', function () { gulp.task('mkdir', function () {
mkdirp.sync(DIST) mkdirp.sync(DIST)
}) })
// bundle javascript // bundle javascript
gulp.task('bundle', ['mkdir'], function (done) { gulp.task('bundle', ['mkdir'], createBundleTask(compiler))
// update the banner contents (has a date in it which should stay up to date)
bannerPlugin.banner = createBanner()
compiler.run(function (err, stats) {
handleCompilerCallback(err, stats)
gutil.log('bundled ' + NAME + '.js')
done()
})
})
// bundle minimalist version of javascript // bundle minimalist version of javascript
gulp.task('bundle-minimalist', ['mkdir'], function (done) { gulp.task('bundle-minimalist', ['mkdir'], createBundleTask(compilerMinimalist))
// update the banner contents (has a date in it which should stay up to date)
bannerPlugin.banner = createBanner()
compilerMinimalist.run(function (err, stats) { // bundle react version
handleCompilerCallback(err, stats) gulp.task('bundle-react', ['mkdir'], createBundleTask(compilerReact))
gutil.log('bundled ' + NAME_MINIMALIST + '.js') // bundle react minimalist version
gulp.task('bundle-react-minimalist', ['mkdir'], createBundleTask(compilerReactMinimalist))
done()
})
})
// TODO: zip file using archiver // TODO: zip file using archiver
var pkg = 'jsoneditor-' + require('./package.json').version + '.zip' const pkg = 'jsoneditor-' + require('./package.json').version + '.zip'
gulp.task('zip', shell.task([ gulp.task('zip', shell.task([
'zip ' + pkg + ' ' + 'README.md LICENSE HISTORY.md index.html src dist docs examples -r ' 'zip ' + pkg + ' ' + 'README.md LICENSE HISTORY.md index.html src dist docs examples -r '
])) ]))
@ -177,4 +229,11 @@ gulp.task(WATCH, ['bundle'], function() {
}) })
// The default task (called when you run `gulp`) // The default task (called when you run `gulp`)
gulp.task('default', [ 'bundle', 'bundle-minimalist' ]) gulp.task('default', function(done) {
return gulpMultiProcess([
'bundle',
'bundle-minimalist',
'bundle-react',
'bundle-react-minimalist'
], done);
})

1
index.js Normal file
View File

@ -0,0 +1 @@
module.exports = require('./dist/jsoneditor')

View File

@ -1,7 +1,7 @@
{ {
"name": "jsoneditor", "name": "jsoneditor",
"version": "6.0.0-BETA", "version": "6.0.0-BETA",
"main": "./src/index", "main": "./index.js",
"description": "A web-based tool to view, edit, format, and validate JSON", "description": "A web-based tool to view, edit, format, and validate JSON",
"tags": [ "tags": [
"json", "json",
@ -43,6 +43,7 @@
"flow-bin": "0.36.0", "flow-bin": "0.36.0",
"graceful-fs": "4.1.11", "graceful-fs": "4.1.11",
"gulp": "3.9.1", "gulp": "3.9.1",
"gulp-multi-process": "0.1.0",
"gulp-shell": "0.5.2", "gulp-shell": "0.5.2",
"gulp-util": "3.0.7", "gulp-util": "3.0.7",
"json-loader": "0.5.4", "json-loader": "0.5.4",

1
react.js vendored Normal file
View File

@ -0,0 +1 @@
module.exports = require('./dist/jsoneditor-react')

View File

@ -1,7 +1,6 @@
// @flow // @flow
import { createElement as h, Component, PropTypes } from 'react' import { createElement as h, Component, PropTypes } from 'react'
import { render, unmountComponentAtNode} from 'react-dom'
import CodeMode from './CodeMode' import CodeMode from './CodeMode'
import TextMode from './TextMode' import TextMode from './TextMode'
import TreeMode from './TreeMode' import TreeMode from './TreeMode'