├── .babelrc
├── .gitignore
├── .npmignore
├── README.md
├── package.json
├── source
├── Breadboard.js
├── BreadboardBuild.js
├── ComponentBreadboard.js
├── ConsoleController.js
├── FakeWindow.js
├── Injectors.js
├── MDXBreadboard.js
├── RawBreadboard.js
├── ResponsiveDualModeController.js
├── compose.js
├── index.js
└── util.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["react", "latest"],
3 | "plugins": ["transform-class-properties", "transform-object-rest-spread"]
4 | }
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | lib
3 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | source
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | armo-breadboard
2 | ===============
3 |
4 | [](https://www.npmjs.com/package/armo-breadboard)
5 |
6 | A themeable React component. Use it to edit a live React component's source in real time.
7 |
8 | Used on [reactarmory.com](http://reactarmory.com). **Only use this component to display your own code -- it is not safe for use with publicly submitted code. For public code, use a service like [codepen.io](http://codepen.io).**
9 |
10 | Installation
11 | ------------
12 |
13 | ```bash
14 | yarn add armo-breadboard
15 | ```
16 |
17 | Usage
18 | -----
19 |
20 | There are currently three Breadboard components:
21 |
22 | - `RawBreadboard`
23 |
24 | Expects that the code will call `ReactDOM.render()` itself, with the result placed in `document.getElementById('app')`. Provides global `React` and `ReactDOM` objects.
25 |
26 | - `ComponentBreadboard`
27 |
28 | Expects that a script will import `React`, and export a default Component. Imports and renders the component.
29 |
30 | - `MDXBreadboard`
31 |
32 | Expects a Markdown document and compiles it to a React Component with [mdxc](https://github.com/jamesknelson/mdxc).
33 |
34 | ### Props
35 |
36 | Here is an overview of the props available for all Breadboard components. For full details on each component's available props, see the `propTypes` definition in the source.
37 |
38 | - `defaultSource` ***required***
39 |
40 | The source to execute. Breadboards are uncontrolled; they currently do not emit events when the code updates/renders. PRs to add this functionality would be welcome.
41 |
42 | - `theme` ***required***
43 |
44 | The theme object that actually renders the Breadboard. This is required as the Breadboard components themselves do not generate any HTML. For an example of a Breadboard theme, see the [theme](#themes) section.
45 |
46 | - `require`
47 |
48 | The `require` function that will be used when executing the Breadboard's source. Use this to configure how `import` statements work.
49 |
50 | By default, Breadboard provides a `require` function that just makes `react` available.
51 |
52 | - `defaultMode`
53 |
54 | Specifies the mode that the Breadboard will be in when loaded. Available options are:
55 |
56 | * `source`
57 | * `transformed`
58 | * `view`
59 | * `console`
60 |
61 | - `defaultSecondary`
62 |
63 | If your Breadboard element has enough space, it will split the view into two panels. In this case, the `source` panel will always be displayed. This option chooses a default for the second panel. All options from above are available -- except `source`.
64 |
65 | ### Themes
66 |
67 | Different websites call for default themes. Of course, CSS isn't always sufficient to make the theming changes that you'd like. Because of this, Breadboards do not generate *any* Markup themselves. Instead, they leave the markup generation to you, via *theme objects*.
68 |
69 | For an example of how theming can be used in practice, see [MDXC Playground](dump.jamesknelson.com/mdxc-playground.html). This page uses two Breadboard themes:
70 |
71 | - The "fullscreen" theme renders the document's source on the left, and the full document on the right. *([source](https://github.com/jamesknelson/mdxc-playground/blob/8924c21913ed568fbef8867463af3c10f6230422/source/fullscreenMDXBreadboardTheme.js))*
72 | - The "default" theme is used for embedded examples within the right pane. *([source](https://github.com/jamesknelson/mdxc-playground/blob/8924c21913ed568fbef8867463af3c10f6230422/source/defaultMDXBreadboardTheme.js))*
73 |
74 | The actual options available on a theme object differ between breadboards. For details, you'll currently need to view the source.
75 |
76 | #### Example
77 |
78 | This is an example of a theme for `RawBreadboard` and `ComponentBreadboard` that renders the editor using CodeMirror. This is used on [reactarmory.com](https://reactarmory.com)
79 |
80 | ```jsx
81 | import './defaultBreadboardTheme.less'
82 | import React, { Component, PropTypes } from 'react'
83 | import debounce from 'lodash.debounce'
84 | import codeMirror from 'codemirror'
85 | import createClassNamePrefixer from '../utils/createClassNamePrefixer'
86 |
87 | require("codemirror/mode/jsx/jsx")
88 |
89 |
90 | const cx = createClassNamePrefixer('defaultBreadboardTheme')
91 |
92 |
93 | export default {
94 | maxSinglePaneWidth: 800,
95 |
96 | renderBreadboard: function(props) {
97 | const {
98 | consoleMessages,
99 | transformedSource,
100 | transformError,
101 | executionError,
102 |
103 | renderEditorElement,
104 | renderMountElement,
105 |
106 | modes,
107 | modeActions,
108 |
109 | reactVersion,
110 | appId
111 | } = props
112 |
113 | const activeModeCount = Object.values(modes).reduce((acc, x) => acc + x || 0, 0)
114 |
115 | const sourceLayout = {
116 | position: 'relative',
117 | flexBasis: 600,
118 | flexGrow: 0,
119 | flexShrink: 0,
120 | }
121 | if (activeModeCount === 1) {
122 | sourceLayout.flexShrink = 1
123 | }
124 |
125 | const secondaryLayout = {
126 | position: 'relative',
127 | flexBasis: 600,
128 | flexGrow: 0,
129 | flexShrink: 1,
130 | overflow: 'auto',
131 | }
132 |
133 | return (
134 |
135 | { (consoleMessages.length || activeModeCount == 1) &&
136 |
137 |
138 | { activeModeCount === 1 &&
139 | Source
140 | }
141 | Preview
142 | Console
143 |
144 |
145 | }
146 | { modes.source &&
147 | renderEditorElement({ layout: sourceLayout })
148 | }
149 | { // Always render the preview element, as the user's code may depend
150 | // on it being available. Hide it if it isn't selected.
151 |
152 | {renderMountElement()}
153 |
154 | }
155 | { modes.console && !transformError && !executionError &&
156 |
161 | }
162 | { (transformError || executionError) &&
163 |
164 |
165 | Failed to Compile
166 | {(transformError || executionError).toString()}
167 |
168 |
169 | }
170 |
171 | )
172 | },
173 |
174 | renderEditor: function({ layout, value, onChange }) {
175 | return (
176 |
182 | )
183 | },
184 | }
185 |
186 | const getType = function (el) {
187 | let t = typeof el;
188 |
189 | if (Array.isArray(el)) {
190 | t = "array";
191 | } else if (el === null) {
192 | t = "null";
193 | }
194 |
195 | return t;
196 | };
197 |
198 | // Based on react-playground by Formidable Labs
199 | // See: https://github.com/FormidableLabs/component-playground/blob/master/src/components/es6-preview.jsx
200 | const wrapMap = {
201 | wrapnumber(num) {
202 | return {num} ;
203 | },
204 |
205 | wrapstring(str) {
206 | return {"'" + str + "'"} ;
207 | },
208 |
209 | wrapboolean(bool) {
210 | return {bool ? "true" : "false"} ;
211 | },
212 |
213 | wraparray(arr) {
214 | return (
215 |
216 | {"["}
217 | {arr.map((entry, i) => {
218 | return (
219 |
220 | {wrapMap["wrap" + getType(entry)](entry)}
221 | {i !== arr.length - 1 ? ", " : ""}
222 |
223 | );
224 | })}
225 | {"]"}
226 |
227 | );
228 | },
229 |
230 | wrapobject(obj) {
231 | const pairs = [];
232 | let first = true;
233 |
234 | for (const key in obj) {
235 | pairs.push(
236 |
237 |
238 | {(first ? "" : ", ") + key}
239 |
240 | {": "}
241 | {wrapMap["wrap" + getType(obj[key])](obj[key])}
242 |
243 | );
244 |
245 | first = false;
246 | }
247 |
248 | return {"Object {"}{pairs}{"}"} ;
249 | },
250 |
251 | wrapfunction() {
252 | return {"function"} ;
253 | },
254 |
255 | wrapnull() {
256 | return {"null"} ;
257 | },
258 |
259 | wrapundefined() {
260 | return {"undefined"} ;
261 | }
262 | }
263 |
264 |
265 | function BreadboardConsole({ className, messages, style }) {
266 | return (
267 |
268 | {messages.map(({ type, args }, i) =>
269 |
270 | {args.map((arg, i) =>
271 |
{wrapMap["wrap" + getType(arg)](arg)}
272 | )}
273 |
274 | )}
275 |
276 | )
277 | }
278 |
279 |
280 | function normalizeLineEndings (str) {
281 | if (!str) return str;
282 | return str.replace(/\r\n|\r/g, '\n');
283 | }
284 |
285 | // Based on these two files:
286 | // https://github.com/JedWatson/react-codemirror/blob/master/src/Codemirror.js
287 | // https://github.com/FormidableLabs/component-playground/blob/master/src/components/editor.jsx
288 | class JSXEditor extends Component {
289 | static propTypes = {
290 | theme: PropTypes.string,
291 | readOnly: PropTypes.bool,
292 | value: PropTypes.string,
293 | selectedLines: PropTypes.array,
294 | onChange: PropTypes.func,
295 | style: PropTypes.object,
296 | className: PropTypes.string
297 | }
298 |
299 | static defaultProps = {
300 | theme: "monokai",
301 | }
302 |
303 | state = {
304 | isFocused: false,
305 | }
306 |
307 | constructor(props) {
308 | super(props)
309 |
310 | this.componentWillReceiveProps = debounce(this.componentWillReceiveProps, 0)
311 | }
312 |
313 | componentDidMount() {
314 | const textareaNode = ReactDOM.findDOMNode(this.refs.textarea);
315 | const options = {
316 | mode: "jsx",
317 | lineNumbers: false,
318 | lineWrapping: false,
319 | smartIndent: false,
320 | matchBrackets: true,
321 | theme: this.props.theme,
322 | readOnly: this.props.readOnly,
323 | viewportMargin: Infinity,
324 | }
325 |
326 | this.codeMirror = codeMirror.fromTextArea(textareaNode, options);
327 | this.codeMirror.on('change', this.handleChange);
328 | this.codeMirror.on('focus', this.handleFocus.bind(this, true));
329 | this.codeMirror.on('blur', this.handleFocus.bind(this, false));
330 | this.codeMirror.on('scroll', this.handleScroll);
331 | this.codeMirror.setValue(this.props.defaultValue || this.props.value || '');
332 | }
333 |
334 | componentWillReceiveProps(nextProps) {
335 | if (this.codeMirror && nextProps.value !== undefined && normalizeLineEndings(this.codeMirror.getValue()) !== normalizeLineEndings(nextProps.value)) {
336 | if (this.props.preserveScrollPosition) {
337 | var prevScrollPosition = this.codeMirror.getScrollInfo();
338 | this.codeMirror.setValue(nextProps.value);
339 | this.codeMirror.scrollTo(prevScrollPosition.left, prevScrollPosition.top);
340 | } else {
341 | this.codeMirror.setValue(nextProps.value);
342 | }
343 | }
344 | }
345 |
346 | componentWillUnmount() {
347 | // is there a lighter-weight way to remove the cm instance?
348 | if (this.codeMirror) {
349 | this.codeMirror.toTextArea();
350 | }
351 | }
352 |
353 | highlightSelectedLines = () => {
354 | if (Array.isArray(this.props.selectedLines)) {
355 | this.props.selectedLines.forEach(lineNumber =>
356 | this.codeMirror.addLineClass(lineNumber, "wrap", "CodeMirror-activeline-background"))
357 | }
358 | }
359 |
360 | focus() {
361 | if (this.codeMirror) {
362 | this.codeMirror.focus()
363 | }
364 | }
365 |
366 | render() {
367 | return (
368 |
369 |
374 |
375 | )
376 | }
377 |
378 | handleFocus(isFocused) {
379 | this.setState({ isFocused })
380 | }
381 |
382 | handleChange = (doc, change) => {
383 | if (!this.props.readOnly && this.props.onChange && change.origin !== 'setValue') {
384 | this.props.onChange(doc.getValue())
385 | }
386 | }
387 |
388 | handleScroll = (codeMirror) => {
389 | this.props.onScroll && this.props.onScroll(codeMirror.getScrollInfo())
390 | }
391 | }
392 | ```
393 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "armo-breadboard",
3 | "version": "0.2.5",
4 | "description": "Edit a live React component's source in real time.",
5 | "author": "James K Nelson ",
6 | "license": "MIT",
7 | "main": "lib/index.js",
8 | "scripts": {
9 | "clean": "rimraf lib",
10 | "build:watch": "cross-env BABEL_ENV=commonjs babel --watch --source-maps=inline -d lib/ source/",
11 | "build": "cross-env BABEL_ENV=commonjs babel source --out-dir lib",
12 | "prepublish": "npm run clean && npm run build"
13 | },
14 | "keywords": [
15 | "playground",
16 | "react",
17 | "component",
18 | "breadboard",
19 | "armo",
20 | "live"
21 | ],
22 | "peerDependencies": {
23 | "react": "^15.4.2",
24 | "react-dom": "^15.4.2"
25 | },
26 | "devDependencies": {
27 | "babel-core": "^6.24.0",
28 | "babel-plugin-transform-class-properties": "^6.24.0",
29 | "babel-plugin-transform-es2015-modules-commonjs": "^6.24.0",
30 | "babel-plugin-transform-object-rest-spread": "^6.23.0",
31 | "babel-preset-latest": "^6.24.0",
32 | "cross-env": "^3.1.4"
33 | },
34 | "dependencies": {
35 | "babel-core": "^6.24.0",
36 | "babel-preset-latest": "^6.24.0",
37 | "babel-preset-react": "^6.24.0",
38 | "exenv": "^1.2.1",
39 | "hatt": "^0.2.1",
40 | "hoist-non-react-statics": "^1.2.0",
41 | "mdxc": "^1.0.0-beta.4",
42 | "prop-types": "^15.5.10",
43 | "react-controllers": "^0.1.1",
44 | "resize-observer-polyfill": "^1.4.2"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/source/Breadboard.js:
--------------------------------------------------------------------------------
1 | import ExecutionEnvironment from 'exenv'
2 | import { createController } from 'hatt'
3 | import React, { Component, PropTypes } from 'react'
4 | import ReactDOM from 'react-dom'
5 | import ReactDOMServer from 'react-dom/server'
6 | import ConsoleController from './ConsoleController'
7 | import FakeWindow from './FakeWindow'
8 | import { verifyThemePropTypes, verifyMissingProps, debounce } from './util'
9 |
10 |
11 | function defaultBreadboardRequire(name) {
12 | if (name === 'react') {
13 | return React
14 | }
15 | }
16 |
17 | function defaultRenderToString(source, require, window, props) {
18 | try {
19 | var execute
20 | var exports = {}
21 | var module = { exports: exports }
22 | eval('execute = function execute(module, exports, require, window, console) { '+source+' }')
23 | execute(module, exports, require, window, window.console)
24 | const component = exports.default
25 | return ReactDOMServer.renderToString(React.createElement(component, props))
26 | }
27 | catch (err) {
28 | return err
29 | }
30 | }
31 |
32 | function defaultPrepare(source, require, window) {
33 | try {
34 | const exports = {}
35 | const module = { exports: exports }
36 |
37 | const execute = new Function(
38 | 'window',
39 | 'setTimeout',
40 | 'setInterval',
41 | 'requestAnimationFrame',
42 | 'fetch',
43 | 'History',
44 | 'console',
45 | 'module',
46 | 'exports',
47 | 'require',
48 | source
49 | )
50 | execute(
51 | window,
52 | window.setTimeout,
53 | window.setInterval,
54 | window.requestAnimationFrame,
55 | window.fetch,
56 | window.History,
57 | window.console,
58 | module,
59 | exports,
60 | require,
61 | )
62 |
63 | const component = exports.default
64 |
65 | return (mount, props={}) => {
66 | if (component) {
67 | try {
68 | ReactDOM.render(
69 | React.createElement(component, props),
70 | mount
71 | )
72 | }
73 | catch (err) {
74 | return err
75 | }
76 | }
77 | }
78 | }
79 | catch (err) {
80 | return () => err
81 | }
82 | }
83 |
84 |
85 | export default class Breadboard extends Component {
86 | static propTypes = {
87 | /**
88 | * A string containing the original source. Updates to the source will
89 | * be stored in component state. Updates to `defaultSource` will not be
90 | * reflected once the source has undergone any change.
91 | */
92 | defaultSource: PropTypes.string.isRequired,
93 |
94 | /**
95 | * A Controller output that keeps track of the current visible modes.
96 | * Breadboard will only compile and/or execute code when it is required.
97 | */
98 | modes: PropTypes.object.isRequired,
99 |
100 | /**
101 | * A function that takes the transformed source and returns a function
102 | * that can be used to render a value from the controller to the mount.
103 | */
104 | prepare: PropTypes.func.isRequired,
105 |
106 | /**
107 | * A controller whose state will be injected into the preview element's
108 | * props. If non-existent, we'll assume that our source calls render
109 | * manually.
110 | */
111 | viewController: PropTypes.object,
112 |
113 | /**
114 | * Allows you to configure the editor component. Accepts a function that
115 | * takes a `{ layout, value, onChange }`, and returns an editor element.
116 | */
117 | renderEditorElement: PropTypes.func.isRequired,
118 |
119 | /**
120 | * An optional function that renders the source with a given controller
121 | * state to a string suitable for use with server side rendering.
122 | */
123 | renderToString: PropTypes.func,
124 |
125 | /**
126 | * The function that will be used to handle CommonJS `require()` calls
127 | * within the evaluated code. Defaults to a function that only provides
128 | * the `react` module.
129 | */
130 | require: PropTypes.func,
131 |
132 | /**
133 | * A function that renders the breadboard given a set of state and
134 | * event handlers.
135 | */
136 | theme: PropTypes.func.isRequired,
137 |
138 | /**
139 | * A function that transforms the source before evaluating it.
140 | *
141 | * Transform functions are often pretty heavy, so we don't include anything
142 | * by default.
143 | */
144 | transform: PropTypes.func,
145 | }
146 |
147 | static defaultProps = {
148 | prepare: defaultPrepare,
149 | renderToString: defaultRenderToString,
150 | require: defaultBreadboardRequire,
151 | }
152 |
153 | constructor(props) {
154 | super(props)
155 |
156 | const source = props.defaultSource.replace(/^\n|\n$/g, '')
157 |
158 | this.consoleController = createController(ConsoleController)
159 | this.consoleController.thaw()
160 | this.fakeWindow = new FakeWindow(this.consoleController.get().actions)
161 |
162 | this.debouncedChangeSource = debounce(this.changeSource, 100)
163 |
164 | this.viewController = props.viewController
165 |
166 | const modes = this.props.modes
167 |
168 | this.state = {
169 | consoleMessages: [],
170 | source: source,
171 | editorSource: source,
172 | value: null,
173 | modes: modes,
174 | transformedSource: null,
175 | executableSource: null,
176 | transformError: null,
177 | renderer: null,
178 | executionError: null,
179 | }
180 |
181 | if (ExecutionEnvironment.canUseDOM &&
182 | props.viewController) {
183 | props.viewController.subscribe(this.handleViewUpdate)
184 | }
185 |
186 | const execute = modes.view || modes.console
187 |
188 | if (modes.transformed || execute) {
189 | const { transformedSource, executableSource, error } = this.props.transform(source)
190 |
191 | this.state.transformedSource = transformedSource
192 | this.state.executableSource = executableSource
193 | this.state.transformError = error
194 |
195 | if (execute && executableSource) {
196 | if (props.renderToString) {
197 | this.state.string = props.renderToString(
198 | executableSource,
199 | props.require,
200 | this.fakeWindow.actions,
201 | props.viewController && props.viewController.get()
202 | )
203 | }
204 | if (ExecutionEnvironment.canUseDOM) {
205 | this.fakeWindow.reset()
206 | this.state.renderer = props.prepare(
207 | executableSource,
208 | props.require,
209 | this.fakeWindow.actions,
210 | )
211 | }
212 | }
213 | }
214 |
215 | this.state.consoleMessages = this.consoleController.get().messages
216 | }
217 |
218 | componentDidMount() {
219 | this.consoleController.subscribe(this.handleConsoleChange)
220 |
221 | // Use this instead of the `modes` on state, as if the above
222 | // manageDimensions call has caused a change, it may not have
223 | // propagated through to `this.state` yet.
224 | if (this.props.modes.view) {
225 | const viewController = this.props.viewController
226 | this.execute(viewController && viewController.get())
227 | }
228 | }
229 | componentWillReceiveProps(nextProps) {
230 | if (nextProps.viewController !== this.viewController) {
231 | console.warn('Breadboard does not currently support changes to the `viewController` prop!')
232 | }
233 |
234 | if (nextProps.modes !== this.props.modes) {
235 | this.handleModesChange(nextProps.modes)
236 | }
237 |
238 | if (nextProps.transform !== this.props.transform ||
239 | nextProps.prepare !== this.props.prepare ||
240 | nextProps.require !== this.props.require) {
241 | this.setState(this.transformAndPrepare(this.state.source, nextProps, nextProps.modes) || {})
242 | }
243 | }
244 | componentDidUpdate(prevProps, prevState) {
245 | const modes = this.state.modes
246 | if ((modes.view || modes.console) &&
247 | (this.state.renderer !== prevState.renderer ||
248 | !(prevState.modes.view || prevState.modes.console))) {
249 | try {
250 | ReactDOM.unmountComponentAtNode(this.refs.mount)
251 | }
252 | catch (e) { }
253 | const viewController = this.viewController
254 | this.execute(viewController && viewController.get())
255 | }
256 | }
257 | componentWillUnmount() {
258 | this.consoleController.destroy()
259 | this.fakeWindow.destroy()
260 |
261 | try {
262 | ReactDOM.unmountComponentAtNode(this.refs.mount)
263 | } catch (e) { }
264 | }
265 |
266 | handleModesChange = (modes) => {
267 | const prevModes = this.state.modes
268 | const prevExecute = prevModes.view || prevModes.console
269 | const nextExecute = modes.view || modes.console
270 | const updates = { modes }
271 | if ((!prevModes.transformed && modes.transformed) || (!prevExecute && nextExecute)) {
272 | Object.assign(updates, this.transformAndPrepare(this.state.source, this.props, modes))
273 | }
274 | this.setState(updates)
275 | }
276 |
277 | // Used so to create debouncedChangeSource. This is separate to the event handler
278 | // as React doesn't like us keeping the event objects around for the completion of
279 | // the timeout.
280 | changeSource = (source) => {
281 | if (source !== this.state.source) {
282 | this.setState({
283 | source,
284 | ...this.transformAndPrepare(source, this.props, this.props.modes)
285 | })
286 | }
287 | }
288 |
289 | handleChangeSource = (e) => {
290 | const source = typeof e === 'string' ? e : (e && e.target && e.target.value)
291 | this.setState({ editorSource: source })
292 | this.debouncedChangeSource(source)
293 | }
294 |
295 | handleConsoleChange = ({ messages }) => {
296 | this.setState({
297 | consoleMessages: messages
298 | })
299 | }
300 |
301 | handleViewUpdate = (viewProps) => {
302 | if (this.state.modes.view || this.state.modes.console) {
303 | this.execute(viewProps)
304 | }
305 | }
306 |
307 | renderEditorElement = (themeableProps={}) => {
308 | if (process.env.NODE_ENV !== 'production') {
309 | // Editor components are complicated beings, and probably will feel the
310 | // same way about being "styled" as a dog feels about taking a bath.
311 | //
312 | // If you want to theme your editor, you'll need to do so by passing in
313 | // an already themed editor. The only condition is that it accepts
314 | // layout styles via `style`, a `value` with the current source, and an
315 | // `onChange` callback that notifies us of a new value.
316 | verifyThemePropTypes(themeableProps, {
317 | layout: true,
318 | })
319 | }
320 |
321 | return this.props.renderEditorElement({
322 | layout: themeableProps.layout,
323 | value: this.state.editorSource,
324 | onChange: this.handleChangeSource,
325 | })
326 | }
327 |
328 | renderMountElement = (themeableProps={}) => {
329 | if (process.env.NODE_ENV !== 'production') {
330 | verifyMissingProps(themeableProps, [
331 | 'children',
332 | 'style',
333 | ])
334 | }
335 |
336 | const { layout, ...other } = themeableProps
337 |
338 | return React.cloneElement(this.mountElement, {
339 | ...other,
340 | style: layout
341 | })
342 | }
343 |
344 | render() {
345 | // Generate the mount elememnt here to ensure that the ref attaches to
346 | // this component instance
347 | this.mountElement =
348 | ExecutionEnvironment.canUseDOM
349 | ?
350 | :
351 |
352 | const rootElement = this.props.theme({
353 | consoleMessages: this.state.consoleMessages,
354 | transformedSource: this.state.transformedSource,
355 | transformError: this.state.transformError,
356 | executionError: this.state.executionError,
357 |
358 | renderEditorElement: this.renderEditorElement,
359 | renderMountElement: this.renderMountElement,
360 |
361 | modes: this.state.modes,
362 | modeActions: this.state.modes,
363 | })
364 |
365 | return React.cloneElement(rootElement, { ref: this.setRootElement })
366 | }
367 |
368 | setRootElement = (el) => {
369 | this.rootElement = el
370 | }
371 |
372 | transformAndPrepare(source, props, modes) {
373 | const state = this.state
374 | const execute = modes.view || modes.console
375 |
376 | if (execute || modes.transformed) {
377 | const { transformedSource, executableSource, error } = props.transform(source)
378 | this.fakeWindow.reset()
379 |
380 | if (transformedSource !== state.transformedSource ||
381 | executableSource !== state.executableSource ||
382 | error !== state.transformError) {
383 |
384 | const result = {
385 | transformError: error,
386 | transformedSource,
387 | executableSource,
388 | }
389 |
390 | if (execute && executableSource) {
391 | result.executionError = null
392 | result.renderer = props.prepare(
393 | executableSource,
394 | props.require,
395 | this.fakeWindow.actions,
396 | )
397 | }
398 |
399 | return result
400 | }
401 | }
402 | }
403 |
404 | execute(viewProps) {
405 | if (this.state.renderer) {
406 | const executionError = this.state.renderer(this.refs.mount, viewProps || {})
407 | if (executionError) {
408 | this.setState({ executionError })
409 | }
410 | }
411 | }
412 | }
413 |
--------------------------------------------------------------------------------
/source/BreadboardBuild.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Handle the process of turning sources into a `render` function, memoizing
3 | * transforms and packed strings where appropriate to ensure that things aren't
4 | * needlessly rebuilt.
5 | *
6 | * A single Breadboard contains a single BreadboardBuild object.
7 | */
8 | class BreadboardBuild {
9 | construtor(transforms, require, packer, renderToString) {
10 |
11 | }
12 |
13 | run(sources, shouldPack=true) {
14 | // - if sources are identical to previous sources, and a cached result
15 | // exists, just use it
16 |
17 | // - run transforms on source files based on patterns, memoizing a single
18 | // previous value per file. invalidate any cached packer result
19 |
20 | // - turn the transformed sources into a `render` file using the packer,
21 | // so long as shouldPack is true
22 |
23 | return {
24 | // A `(mountpoint, props) => void` function that renders one frame of
25 | // the app with the given props. This function may be called without
26 | // cleaning up previous frames if the props change.
27 | render,
28 |
29 | // A single string that includes all transformed sources
30 | packedSource,
31 |
32 | // A paused FakeWindow object
33 | fakeWindow,
34 | }
35 | }
36 |
37 | renderToString(sources) {
38 |
39 | }
40 | }
41 |
42 |
43 |
44 | function defaultPack(source, require, window) {
45 | try {
46 | const exports = {}
47 | const module = { exports: exports }
48 |
49 | const execute = new Function(
50 | 'window',
51 | 'setTimeout',
52 | 'setInterval',
53 | 'requestAnimationFrame',
54 | 'fetch',
55 | 'History',
56 | 'console',
57 | 'module',
58 | 'exports',
59 | 'require',
60 | source
61 | )
62 | execute(
63 | window,
64 | window.setTimeout,
65 | window.setInterval,
66 | window.requestAnimationFrame,
67 | window.fetch,
68 | window.History,
69 | window.console,
70 | module,
71 | exports,
72 | require,
73 | )
74 |
75 | const component = exports.default
76 |
77 | return (mount, props={}) => {
78 | if (component) {
79 | try {
80 | ReactDOM.render(
81 | React.createElement(component, props),
82 | mount
83 | )
84 | }
85 | catch (err) {
86 | return err
87 | }
88 | }
89 | }
90 | }
91 | catch (err) {
92 | return () => err
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/source/ComponentBreadboard.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react'
2 | import ReactDOM from 'react-dom'
3 | import Breadboard from './Breadboard'
4 | import ResponsiveDualModeController from './ResponsiveDualModeController'
5 | import { transform } from 'babel-core'
6 | import latestPreset from 'babel-preset-latest'
7 | import reactPreset from 'babel-preset-react'
8 |
9 |
10 | export default class RawBreadboard extends Component {
11 | static propTypes = {
12 | /**
13 | * The default mode to display upon load when the screen only contains
14 | * space for a single pane.
15 | */
16 | defaultMode: PropTypes.oneOf(['source', 'view', 'transformed', 'console']),
17 |
18 | /**
19 | * Selects the secondary pane to display in the case that the user is
20 | * viewing the source pane on a small screen, and then the screen
21 | * expands to allow a second pane.
22 | */
23 | defaultSecondary: PropTypes.oneOf(['view', 'transformed', 'console']).isRequired,
24 |
25 | /**
26 | * The breadboard's theme.
27 | */
28 | theme: PropTypes.shape({
29 | renderBreadboard: PropTypes.func,
30 | renderEditor: PropTypes.func,
31 | }).isRequired,
32 | }
33 |
34 | static defaultProps = {
35 | defaultMode: 'source',
36 | defaultSecondary: 'view',
37 | }
38 |
39 | constructor(props) {
40 | super(props)
41 |
42 | this.modesController = new ResponsiveDualModeController({
43 | maxSinglePaneWidth: props.theme.maxSinglePaneWidth,
44 | defaultSecondary: props.defaultSecondary,
45 | defaultMode: props.defaultMode,
46 | })
47 | }
48 |
49 | componentWillReceiveProps(nextProps) {
50 | if (nextProps.theme.maxSinglePaneWidth !== this.props.theme.maxSinglePaneWidth) {
51 | this.modesController.environmentDidChange({
52 | maxSinglePaneWidth: nextProps.theme.maxSinglePaneWidth,
53 | })
54 | }
55 | }
56 |
57 | renderTheme = (props) => {
58 | return this.props.theme.renderBreadboard(Object.assign({}, props, {
59 | reactVersion: React.version,
60 | appId: this.props.appId,
61 | }))
62 | }
63 |
64 | render() {
65 | const { ...other } = this.props
66 |
67 | return (
68 |
75 | )
76 | }
77 |
78 | transform = (source) => {
79 | let transformed
80 | let error = null
81 |
82 | try {
83 | transformed = transform(source, { presets: [reactPreset, latestPreset] }).code
84 | }
85 | catch (e) {
86 | error = e
87 | }
88 |
89 | return {
90 | transformedSource: transformed,
91 | executableSource: transformed,
92 | error: error,
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/source/ConsoleController.js:
--------------------------------------------------------------------------------
1 | import { Controller } from 'hatt'
2 |
3 | export default class ConsoleController extends Controller {
4 | static actions = {
5 | log(...args) {
6 | this.logMessage('log', ...args)
7 | },
8 | error(...args) {
9 | this.logMessage('error', ...args)
10 | },
11 | warn(...args) {
12 | this.logMessage('warn', ...args)
13 | },
14 |
15 | clear() {
16 | this.setState({ messages: [] })
17 | }
18 | }
19 |
20 | static initialState = {
21 | messages: [],
22 | }
23 |
24 | logMessage(type, ...args) {
25 | this.setState({
26 | messages: this.state.messages.concat({ type, args })
27 | })
28 | }
29 |
30 | output() {
31 | return {
32 | actions: this.actions,
33 | messages: this.state.messages,
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/source/FakeWindow.js:
--------------------------------------------------------------------------------
1 | export default class FakeWindow {
2 | constructor(console) {
3 | this.seq = 1
4 |
5 | this.timeouts = []
6 | this.intervals = []
7 | this.frames = []
8 |
9 | this.actions = {
10 | console: console,
11 |
12 | setTimeout: (cb, ms) => {
13 | const id = window.setTimeout(cb, ms)
14 | this.timeouts.push(id)
15 | return id
16 | },
17 |
18 | setInterval: (cb, ms) => {
19 | const id = window.setInterval(cb, ms)
20 | this.intervals.push(id)
21 | return id
22 | },
23 |
24 | requestAnimationFrame: (cb) => {
25 | const id = window.requestAnimationFrame(cb)
26 | this.frames.push(id)
27 | return id
28 | },
29 |
30 | fetch: (...args) => {
31 | const seq = this.seq
32 | return new Promise((resolve, reject) =>
33 | window.fetch(...args).then(
34 | (...success) => {
35 | if (seq === this.seq) {
36 | resolve(...success)
37 | }
38 | },
39 | (...failure) => {
40 | if (seq === this.seq) {
41 | reject(...failure)
42 | }
43 | }
44 | )
45 | )
46 | },
47 |
48 | History: {},
49 | }
50 | }
51 |
52 | reset() {
53 | for (let timeout of this.timeouts) {
54 | window.clearTimeout(timeout)
55 | }
56 | for (let interval of this.intervals) {
57 | window.clearInterval(interval)
58 | }
59 | for (let frame of this.frames) {
60 | window.cancelAnimationFrame(frame)
61 | }
62 |
63 | this.timeouts.length = 0
64 | this.intervals.length = 0
65 | this.frames.length = 0
66 |
67 | this.actions.console.clear()
68 | this.seq++
69 | }
70 |
71 | destroy() {
72 | this.reset()
73 | this.actions.console = null
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/source/Injectors.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import ReactDOM from 'react-dom'
3 | import ExecutionEnvironment from 'exenv'
4 | import PropTypes from 'prop-types'
5 | import hoistNonReactStatics from 'hoist-non-react-statics'
6 |
7 |
8 | let breadboardResizeObserver
9 | if (ExecutionEnvironment.canUseDOM) {
10 | const ResizeObserver = require('resize-observer-polyfill').default
11 |
12 | class BreadboardResizeObserver {
13 | constructor() {
14 | this.callbacks = new Map
15 | this.observer = new ResizeObserver((entries) => {
16 | for (const entry of entries) {
17 | const callback = this.callbacks.get(entry.target)
18 |
19 | if (callback) {
20 | callback({
21 | height: entry.contentRect.height,
22 | width: entry.contentRect.width,
23 | })
24 | }
25 | }
26 | })
27 | }
28 |
29 | observe(target, callback) {
30 | this.observer.observe(target)
31 | this.callbacks.set(target, callback)
32 | }
33 |
34 | unobserve(target, callback) {
35 | this.observer.unobserve(target)
36 | this.callbacks.delete(target, callback)
37 | }
38 | }
39 |
40 | breadboardResizeObserver = new BreadboardResizeObserver
41 | }
42 |
43 |
44 | /**
45 | * Inject the child element's width and height, as computed by a
46 | * ResizeObserver.
47 | */
48 | export class InjectDimensions extends Component {
49 | static propTypes = {
50 | /**
51 | * The value to use for `height` before we are able to make a measurement.
52 | */
53 | defaultHeight: PropTypes.number,
54 |
55 | /**
56 | * The value to use for `width` before we are able to make a measurement.
57 | */
58 | defaultWidth: PropTypes.number,
59 |
60 | /**
61 | * If a number or `null`, the height will be passed directly to the child
62 | * element instead of being observed.
63 | */
64 | height: PropTypes.number,
65 |
66 | /**
67 | * If a number or `null`, the width will be passed directly to the child
68 | * element instead of being observed.
69 | */
70 | width: PropTypes.number,
71 |
72 | /**
73 | * This component expects a single child that is a React Element.
74 | */
75 | children: PropTypes.element.isRequired,
76 | }
77 |
78 | constructor(props) {
79 | super(props)
80 |
81 | // The dimensions are not defined until we can measure them, or unless
82 | // a fixed value is provided.
83 | this.state = {
84 | observed: false,
85 | height: undefined,
86 | width: undefined,
87 | }
88 | }
89 |
90 | componentDidMount() {
91 | const shouldObserve = this.props.width === undefined || this.props.height === undefined
92 |
93 | if (shouldObserve) {
94 | this.observe()
95 | }
96 | }
97 |
98 | componentWillReceiveProps(nextProps) {
99 | const shouldObserve = nextProps.width === undefined || nextProps.height === undefined
100 |
101 | if (shouldObserve && !this.state.observed) {
102 | this.observe()
103 | }
104 | else if (!shouldObserve && this.state.observed) {
105 | this.unobserve()
106 | this.setState({
107 | observed: false,
108 | })
109 | }
110 | }
111 | componentDidUpdate(prevProps, prevState) {
112 | const shouldObserve = this.props.width === undefined || this.props.height === undefined
113 |
114 | if (this.domNode !== this.state.observed) {
115 | this.unobserve()
116 | if (this.domNode && shouldObserve) {
117 | this.observe()
118 | }
119 | }
120 | }
121 | componentWillUnmount() {
122 | this.unobserve()
123 | }
124 |
125 | shouldComponentUpdate(nextProps, nextState) {
126 | const measuredHeightChanged = nextState.height !== this.state.height
127 | const measuredWidthChanged = nextState.width !== this.state.width
128 |
129 | // don't cause an update when it originated from a resize observation,
130 | // but that observation is overriden by a forced width/height
131 | const insignificantMeasurementOccured =
132 | nextState.observed && this.state.observed &&
133 | (measuredHeightChanged || measuredWidthChanged) &&
134 | !(
135 | (measuredHeightChanged && nextProps.height === undefined) ||
136 | (measuredWidthChanged && nextProps.width === undefined)
137 | )
138 |
139 | return !insignificantMeasurementOccured
140 | }
141 |
142 | render() {
143 | const props = this.props
144 | const state = this.state
145 |
146 | return React.cloneElement(
147 | React.Children.only(props.children),
148 | {
149 | width: state.width === undefined ? props.defaultWidth : state.width,
150 | height: state.height === undefined ? props.defaultHeight : state.height,
151 | ref: this.receiveRef,
152 | }
153 | )
154 | }
155 |
156 | receiveRef = (x) => {
157 | this.domNode = x && ReactDOM.findDOMNode(x)
158 | }
159 |
160 | handleResize = (measured) => {
161 | this.setState({
162 | height: measured.height,
163 | width: measured.width,
164 | })
165 | }
166 |
167 | observe() {
168 | breadboardResizeObserver.observe(this.domNode, this.handleResize)
169 | const measured = this.domNode.getBoundingClientRect()
170 | this.setState({
171 | observed: this.domNode,
172 | height: measured.height,
173 | width: measured.width,
174 | })
175 | }
176 |
177 | unobserve() {
178 | if (this.state.observed) {
179 | breadboardResizeObserver.unobserve(this.state.observed, this.handleResize)
180 | }
181 | }
182 | }
183 |
184 | export function injectDimensions(WrappedComponent) {
185 | function InjectDimensionsWrapper ({ defaultHeight, defaultWidth, height, width, ...other }) {
186 | return React.createElement(InjectDimensions, { defaultHeight, defaultWidth, height, width },
187 | React.createElement(WrappedComponent, other)
188 | )
189 | }
190 |
191 | hoistNonReactStatics(InjectDimensionsWrapper, WrappedComponent)
192 |
193 | return InjectDimensionsWrapper
194 | }
195 |
196 | injectDimensions.withConfiguration = function(forceProps) {
197 | return function injectDimensions(WrappedComponent) {
198 | function InjectDimensionsWrapper (props) {
199 | const { defaultHeight, defaultWidth, height, width, ...other } = Object.assign({}, props, forceProps)
200 |
201 | return React.createElement(InjectDimensions, { defaultHeight, defaultWidth, height, width },
202 | React.createElement(WrappedComponent, other)
203 | )
204 | }
205 |
206 | hoistNonReactStatics(InjectDimensionsWrapper, WrappedComponent)
207 |
208 | return InjectDimensionsWrapper
209 | }
210 | }
--------------------------------------------------------------------------------
/source/MDXBreadboard.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react'
2 | import { Controller, createController } from 'hatt'
3 | import frontMatter from 'front-matter'
4 | import MDXC from 'mdxc'
5 | import { transform } from 'babel-core'
6 | import latestPreset from 'babel-preset-latest'
7 | import ResponsiveDualModeController from './ResponsiveDualModeController'
8 | import Breadboard from './Breadboard'
9 |
10 |
11 | const wrappedMDXC = new MDXC({
12 | linkify: true,
13 | typographer: true,
14 | highlight: false,
15 | })
16 | const unwrappedMDXC = new MDXC({
17 | linkify: true,
18 | typographer: true,
19 | highlight: false,
20 | unwrapped: true,
21 | })
22 |
23 |
24 | class ViewController extends Controller {
25 | static actions = {
26 | setValue(e) {
27 | this.setState({
28 | value: e.target.value,
29 | })
30 | },
31 | }
32 |
33 | static initialState = {
34 | value: null,
35 | }
36 |
37 | output() {
38 | return {
39 | ...this.env,
40 | value: this.state.value,
41 | onChange: this.actions.setValue,
42 | }
43 | }
44 | }
45 |
46 |
47 | export default class MDXBreadboard extends Component {
48 | static propTypes = {
49 | /**
50 | * The default mode to display upon load when the screen only contains
51 | * space for a single pane.
52 | */
53 | defaultMode: PropTypes.oneOf(['source', 'view', 'transformed', 'console']),
54 |
55 | /**
56 | * Selects the secondary pane to display in the case that the user is
57 | * viewing the source pane on a small screen, and then the screen
58 | * expands to allow a second pane.
59 | */
60 | defaultSecondary: PropTypes.oneOf(['view', 'transformed', 'console']).isRequired,
61 |
62 | /**
63 | * Configures whether the wrapper code will be displayed within the
64 | * transformed view.
65 | */
66 | defaultUnwrapped: PropTypes.bool,
67 |
68 | /**
69 | * Allows you to configure the factories of the rendered MDXDocument
70 | * object.
71 | */
72 | factories: PropTypes.object,
73 |
74 | /**
75 | * A function that renders the breadboard given a set of state and
76 | * event handlers.
77 | */
78 | theme: PropTypes.shape({
79 | renderBreadboard: PropTypes.func,
80 | renderCode: PropTypes.func,
81 | renderEditor: PropTypes.func,
82 | }),
83 | }
84 |
85 | static defaultProps = {
86 | defaultMode: 'source',
87 | defaultSecondary: 'view',
88 | defaultUnwrapped: false,
89 | }
90 |
91 | constructor(props) {
92 | super(props)
93 |
94 | this.modesController = new ResponsiveDualModeController({
95 | maxSinglePaneWidth: props.theme.maxSinglePaneWidth,
96 | defaultSecondary: props.defaultSecondary,
97 | defaultMode: props.defaultMode,
98 | })
99 |
100 | this.viewController = createController(ViewController, {
101 | factories: {
102 | ...this.props.factories,
103 | codeBlock: this.renderCodeBlock,
104 | },
105 | })
106 |
107 | this.state = {
108 | unwrapped: this.props.defaultUnwrapped,
109 | transform: this.transform.bind(this, this.props.defaultUnwrapped)
110 | }
111 | }
112 |
113 | componentWillReceiveProps(nextProps) {
114 | if (nextProps.theme.maxSinglePaneWidth !== this.props.theme.maxSinglePaneWidth) {
115 | this.modesController.environmentDidChange({
116 | maxSinglePaneWidth: nextProps.theme.maxSinglePaneWidth,
117 | })
118 | }
119 | if (nextProps.factories !== this.props.factories) {
120 | this.viewController.setEnv({
121 | factories: {
122 | ...this.props.factories,
123 | codeBlock: this.renderCodeBlock,
124 | },
125 | })
126 | }
127 | }
128 |
129 | componentWillUnmount() {
130 | this.viewController.destroy()
131 | }
132 |
133 | renderCodeBlock = (props, children) => {
134 | const language = props.className.replace(/^language-/, '')
135 | let renderBreadboard
136 |
137 | if (language.slice(0, 3) === 'mdx') {
138 | const optionStrings = language.slice(4).replace(/^\{|\s|\}$/g, '').split(',')
139 | const options = {}
140 | for (let str of optionStrings) {
141 | if (str.indexOf('=') === -1) {
142 | options[str] = true
143 | }
144 | else {
145 | const parts = str.split('=')
146 | options[parts[0]] = parts[1]
147 | }
148 | }
149 | renderBreadboard = (themeProps) =>
150 |
158 | }
159 |
160 | return this.props.theme.renderCode({ language, renderBreadboard, source: children })
161 | }
162 |
163 | renderTheme = (props) => {
164 | return this.props.theme.renderBreadboard(Object.assign({}, props, {
165 | defaultMode: this.props.defaultMode,
166 | defaultSecondary: this.props.defaultSecondary,
167 |
168 | unwrapped: this.state.unwrapped,
169 | onToggleWrapped: this.toggleWrapped,
170 | }))
171 | }
172 |
173 | render() {
174 | const { factories, defaultUnwrapped, ...other } = this.props
175 |
176 | return (
177 |
185 | )
186 | }
187 |
188 | toggleWrapped = () => {
189 | const newUnwrapped = !this.state.unwrapped
190 |
191 | this.setState({
192 | unwrapped: newUnwrapped,
193 | transform: this.transform.bind(this, newUnwrapped)
194 | })
195 | }
196 |
197 | transform = (unwrapped, source) => {
198 | const result = {}
199 | const data = frontMatter(source)
200 | const es6 = wrappedMDXC.render(data.body)
201 | const pretty = unwrapped ? unwrappedMDXC.render(data.body) : es6
202 | let runnableCode
203 | let error = null
204 | try {
205 | runnableCode = transform(es6, { presets: [latestPreset] }).code
206 | }
207 | catch (e) {
208 | error = e
209 | }
210 |
211 | return {
212 | transformedSource: pretty,
213 | executableSource: runnableCode,
214 | error,
215 | }
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/source/RawBreadboard.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react'
2 | import ReactDOM from 'react-dom'
3 | import Breadboard from './Breadboard'
4 | import { injectDimensions } from './Injectors'
5 | import ResponsiveDualModeController from './ResponsiveDualModeController'
6 | import { controlledBy } from 'react-controllers'
7 | import compose from './compose'
8 | import { transform } from 'babel-core'
9 | import latestPreset from 'babel-preset-latest'
10 | import reactPreset from 'babel-preset-react'
11 |
12 |
13 | function rawPrepare(source, require, window) {
14 | try {
15 | const exports = {}
16 | const module = { exports: exports }
17 |
18 | const execute = new Function(
19 | 'window',
20 | 'setTimeout',
21 | 'setInterval',
22 | 'requestAnimationFrame',
23 | 'fetch',
24 | 'History',
25 | 'console',
26 | 'module',
27 | 'exports',
28 | 'require',
29 | 'breadboard',
30 | 'React',
31 | 'ReactDOM',
32 | '__MOUNT__',
33 | source
34 | )
35 |
36 | return (mount, props={}) => {
37 | try {
38 | execute(
39 | window,
40 | window.setTimeout,
41 | window.setInterval,
42 | window.requestAnimationFrame,
43 | window.fetch,
44 | window.History,
45 | window.console,
46 | module,
47 | exports,
48 | require,
49 | props,
50 | React,
51 | ReactDOM,
52 | mount
53 | )
54 | }
55 | catch (err) {
56 | return err
57 | }
58 | }
59 | }
60 | catch (err) {
61 | return () => err
62 | }
63 | }
64 |
65 |
66 | const decorate = compose(
67 | injectDimensions.withConfiguration({ height: null }),
68 | controlledBy({ modes: ResponsiveDualModeController })
69 | )
70 |
71 | export default decorate(class RawBreadboard extends Component {
72 | static propTypes = {
73 | /**
74 | * When this id is used in a `document.getElementById` call, the entire
75 | * call will be replaced with the mountpoint's element. Note that this
76 | * means previews cannot be generated server-side.
77 | */
78 | appId: PropTypes.string.isRequired,
79 |
80 | /**
81 | * The breadboard's theme.
82 | */
83 | theme: PropTypes.shape({
84 | renderBreadboard: PropTypes.func,
85 | renderEditor: PropTypes.func,
86 | }).isRequired,
87 | }
88 |
89 | static defaultProps = {
90 | appId: 'app',
91 | }
92 |
93 | renderTheme = (props) => {
94 | return this.props.theme.renderBreadboard(Object.assign({}, props, {
95 | reactVersion: React.version,
96 | appId: this.props.appId,
97 | }))
98 | }
99 |
100 | render() {
101 | return (
102 |
110 | )
111 | }
112 |
113 | transform = (source) => {
114 | let transformed
115 | let error = null
116 |
117 | const appPattern = new RegExp(`document\\s*.\\s*getElementById\\s*\\(\\s*['"]${this.props.appId}['"]\\s*\\)`, 'g')
118 | const sourceWithAppId = source.replace(appPattern, ' __MOUNT__ ')
119 |
120 | try {
121 | transformed = transform(sourceWithAppId, { presets: [reactPreset, latestPreset] }).code
122 | }
123 | catch (e) {
124 | error = e
125 | }
126 |
127 | return {
128 | transformedSource: transformed,
129 | executableSource: transformed,
130 | error: error,
131 | }
132 | }
133 | })
--------------------------------------------------------------------------------
/source/ResponsiveDualModeController.js:
--------------------------------------------------------------------------------
1 | import { PureController } from 'react-controllers'
2 |
3 |
4 | export default class ResponsiveDualModeController extends PureController {
5 | static defaultProps = {
6 | /**
7 | * Selects the secondary pane to display in the case that the user is
8 | * viewing the source pane on a small screen, and then the screen
9 | * expands to allow a second pane.
10 | */
11 | defaultSecondary: 'view',
12 |
13 | /**
14 | * The default mode to display upon load when the screen only contains
15 | * space for a single pane.
16 | */
17 | defaultMode: 'source',
18 |
19 | /**
20 | * The maximum width for which only a single pane will be used.
21 | */
22 | maxSinglePaneWidth: 999,
23 | }
24 |
25 | static actions = {
26 | selectMode(mode) {
27 | this.setState({ primary: mode })
28 | },
29 | selectTransformed() {
30 | this.setState({ primary: 'transformed' })
31 | },
32 | selectView() {
33 | this.setState({ primary: 'view' })
34 | },
35 | selectConsole() {
36 | this.setState({ primary: 'console' })
37 | },
38 | selectSource() {
39 | this.setState({ primary: 'source' })
40 | },
41 | }
42 |
43 | constructor(props) {
44 | super(props)
45 |
46 | this.state = {
47 | primary: props.defaultMode,
48 | }
49 | }
50 |
51 | output() {
52 | const props = this.props
53 | const primary = this.state.primary
54 | const modes = {}
55 |
56 | if (props.width !== undefined && props.width <= props.maxSinglePaneWidth) {
57 | modes[primary] = true
58 | }
59 | else {
60 | modes['source'] = true
61 | modes[primary === 'source' ? props.defaultSecondary : primary] = true
62 | }
63 |
64 | return Object.assign(modes, this.actions)
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/source/compose.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2015-present Dan Abramov
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 |
13 | */
14 |
15 | export default function compose(...funcs) {
16 | if (funcs.length === 0) {
17 | return arg => arg
18 | }
19 |
20 | if (funcs.length === 1) {
21 | return funcs[0]
22 | }
23 |
24 | return funcs.reduce((a, b) => (...args) => a(b(...args)))
25 | }
--------------------------------------------------------------------------------
/source/index.js:
--------------------------------------------------------------------------------
1 | export { default as Breadboard } from './Breadboard'
2 | export { default as RawBreadboard } from './RawBreadboard'
3 | export { default as ComponentBreadboard } from './ComponentBreadboard'
4 | export { default as MDXBreadboard } from './MDXBreadboard'
5 | export { default as ResponsiveDualModeController } from './ResponsiveDualModeController'
6 |
--------------------------------------------------------------------------------
/source/util.js:
--------------------------------------------------------------------------------
1 | export function verifyThemePropTypes(props, propTypes) {
2 | // TODO.
3 | }
4 |
5 | export function verifyMissingProps(props, propNames) {
6 | // TODO.
7 | }
8 |
9 | // Returns a function, that, as long as it continues to be invoked, will not
10 | // be triggered. The function will be called after it stops being called for
11 | // N milliseconds. If `immediate` is passed, trigger the function on the
12 | // leading edge, instead of the trailing.
13 | // https://davidwalsh.name/javascript-debounce-function
14 | export function debounce(func, wait, immediate) {
15 | var timeout;
16 | return function() {
17 | var context = this, args = arguments;
18 | var later = function() {
19 | timeout = null;
20 | if (!immediate) func.apply(context, args);
21 | };
22 | var callNow = immediate && !timeout;
23 | clearTimeout(timeout);
24 | timeout = setTimeout(later, wait);
25 | if (callNow) func.apply(context, args);
26 | };
27 | };
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | ansi-regex@^2.0.0:
6 | version "2.1.1"
7 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
8 |
9 | ansi-styles@^2.2.1:
10 | version "2.2.1"
11 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
12 |
13 | argparse@^1.0.7:
14 | version "1.0.9"
15 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
16 | dependencies:
17 | sprintf-js "~1.0.2"
18 |
19 | asap@~2.0.3:
20 | version "2.0.5"
21 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"
22 |
23 | babel-code-frame@^6.22.0:
24 | version "6.22.0"
25 | resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
26 | dependencies:
27 | chalk "^1.1.0"
28 | esutils "^2.0.2"
29 | js-tokens "^3.0.0"
30 |
31 | babel-core@^6.24.0, babel-core@^6.24.1:
32 | version "6.24.1"
33 | resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.1.tgz#8c428564dce1e1f41fb337ec34f4c3b022b5ad83"
34 | dependencies:
35 | babel-code-frame "^6.22.0"
36 | babel-generator "^6.24.1"
37 | babel-helpers "^6.24.1"
38 | babel-messages "^6.23.0"
39 | babel-register "^6.24.1"
40 | babel-runtime "^6.22.0"
41 | babel-template "^6.24.1"
42 | babel-traverse "^6.24.1"
43 | babel-types "^6.24.1"
44 | babylon "^6.11.0"
45 | convert-source-map "^1.1.0"
46 | debug "^2.1.1"
47 | json5 "^0.5.0"
48 | lodash "^4.2.0"
49 | minimatch "^3.0.2"
50 | path-is-absolute "^1.0.0"
51 | private "^0.1.6"
52 | slash "^1.0.0"
53 | source-map "^0.5.0"
54 |
55 | babel-generator@^6.24.1:
56 | version "6.24.1"
57 | resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.1.tgz#e715f486c58ded25649d888944d52aa07c5d9497"
58 | dependencies:
59 | babel-messages "^6.23.0"
60 | babel-runtime "^6.22.0"
61 | babel-types "^6.24.1"
62 | detect-indent "^4.0.0"
63 | jsesc "^1.3.0"
64 | lodash "^4.2.0"
65 | source-map "^0.5.0"
66 | trim-right "^1.0.1"
67 |
68 | babel-helper-builder-binary-assignment-operator-visitor@^6.24.1:
69 | version "6.24.1"
70 | resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664"
71 | dependencies:
72 | babel-helper-explode-assignable-expression "^6.24.1"
73 | babel-runtime "^6.22.0"
74 | babel-types "^6.24.1"
75 |
76 | babel-helper-builder-react-jsx@^6.24.1:
77 | version "6.24.1"
78 | resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.24.1.tgz#0ad7917e33c8d751e646daca4e77cc19377d2cbc"
79 | dependencies:
80 | babel-runtime "^6.22.0"
81 | babel-types "^6.24.1"
82 | esutils "^2.0.0"
83 |
84 | babel-helper-call-delegate@^6.24.1:
85 | version "6.24.1"
86 | resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d"
87 | dependencies:
88 | babel-helper-hoist-variables "^6.24.1"
89 | babel-runtime "^6.22.0"
90 | babel-traverse "^6.24.1"
91 | babel-types "^6.24.1"
92 |
93 | babel-helper-define-map@^6.24.1:
94 | version "6.24.1"
95 | resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz#7a9747f258d8947d32d515f6aa1c7bd02204a080"
96 | dependencies:
97 | babel-helper-function-name "^6.24.1"
98 | babel-runtime "^6.22.0"
99 | babel-types "^6.24.1"
100 | lodash "^4.2.0"
101 |
102 | babel-helper-explode-assignable-expression@^6.24.1:
103 | version "6.24.1"
104 | resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa"
105 | dependencies:
106 | babel-runtime "^6.22.0"
107 | babel-traverse "^6.24.1"
108 | babel-types "^6.24.1"
109 |
110 | babel-helper-function-name@^6.24.1:
111 | version "6.24.1"
112 | resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
113 | dependencies:
114 | babel-helper-get-function-arity "^6.24.1"
115 | babel-runtime "^6.22.0"
116 | babel-template "^6.24.1"
117 | babel-traverse "^6.24.1"
118 | babel-types "^6.24.1"
119 |
120 | babel-helper-get-function-arity@^6.24.1:
121 | version "6.24.1"
122 | resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d"
123 | dependencies:
124 | babel-runtime "^6.22.0"
125 | babel-types "^6.24.1"
126 |
127 | babel-helper-hoist-variables@^6.24.1:
128 | version "6.24.1"
129 | resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76"
130 | dependencies:
131 | babel-runtime "^6.22.0"
132 | babel-types "^6.24.1"
133 |
134 | babel-helper-optimise-call-expression@^6.24.1:
135 | version "6.24.1"
136 | resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
137 | dependencies:
138 | babel-runtime "^6.22.0"
139 | babel-types "^6.24.1"
140 |
141 | babel-helper-regex@^6.24.1:
142 | version "6.24.1"
143 | resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz#d36e22fab1008d79d88648e32116868128456ce8"
144 | dependencies:
145 | babel-runtime "^6.22.0"
146 | babel-types "^6.24.1"
147 | lodash "^4.2.0"
148 |
149 | babel-helper-remap-async-to-generator@^6.24.1:
150 | version "6.24.1"
151 | resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b"
152 | dependencies:
153 | babel-helper-function-name "^6.24.1"
154 | babel-runtime "^6.22.0"
155 | babel-template "^6.24.1"
156 | babel-traverse "^6.24.1"
157 | babel-types "^6.24.1"
158 |
159 | babel-helper-replace-supers@^6.24.1:
160 | version "6.24.1"
161 | resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a"
162 | dependencies:
163 | babel-helper-optimise-call-expression "^6.24.1"
164 | babel-messages "^6.23.0"
165 | babel-runtime "^6.22.0"
166 | babel-template "^6.24.1"
167 | babel-traverse "^6.24.1"
168 | babel-types "^6.24.1"
169 |
170 | babel-helpers@^6.24.1:
171 | version "6.24.1"
172 | resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
173 | dependencies:
174 | babel-runtime "^6.22.0"
175 | babel-template "^6.24.1"
176 |
177 | babel-messages@^6.23.0:
178 | version "6.23.0"
179 | resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
180 | dependencies:
181 | babel-runtime "^6.22.0"
182 |
183 | babel-plugin-check-es2015-constants@^6.22.0:
184 | version "6.22.0"
185 | resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
186 | dependencies:
187 | babel-runtime "^6.22.0"
188 |
189 | babel-plugin-syntax-async-functions@^6.8.0:
190 | version "6.13.0"
191 | resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
192 |
193 | babel-plugin-syntax-class-properties@^6.8.0:
194 | version "6.13.0"
195 | resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
196 |
197 | babel-plugin-syntax-exponentiation-operator@^6.8.0:
198 | version "6.13.0"
199 | resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
200 |
201 | babel-plugin-syntax-flow@^6.18.0:
202 | version "6.18.0"
203 | resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d"
204 |
205 | babel-plugin-syntax-jsx@^6.18.0, babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0:
206 | version "6.18.0"
207 | resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
208 |
209 | babel-plugin-syntax-object-rest-spread@^6.8.0:
210 | version "6.13.0"
211 | resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
212 |
213 | babel-plugin-syntax-trailing-function-commas@^6.22.0:
214 | version "6.22.0"
215 | resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
216 |
217 | babel-plugin-transform-async-to-generator@^6.24.1:
218 | version "6.24.1"
219 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
220 | dependencies:
221 | babel-helper-remap-async-to-generator "^6.24.1"
222 | babel-plugin-syntax-async-functions "^6.8.0"
223 | babel-runtime "^6.22.0"
224 |
225 | babel-plugin-transform-class-properties@^6.24.0:
226 | version "6.24.1"
227 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac"
228 | dependencies:
229 | babel-helper-function-name "^6.24.1"
230 | babel-plugin-syntax-class-properties "^6.8.0"
231 | babel-runtime "^6.22.0"
232 | babel-template "^6.24.1"
233 |
234 | babel-plugin-transform-es2015-arrow-functions@^6.22.0:
235 | version "6.22.0"
236 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
237 | dependencies:
238 | babel-runtime "^6.22.0"
239 |
240 | babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
241 | version "6.22.0"
242 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141"
243 | dependencies:
244 | babel-runtime "^6.22.0"
245 |
246 | babel-plugin-transform-es2015-block-scoping@^6.24.1:
247 | version "6.24.1"
248 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz#76c295dc3a4741b1665adfd3167215dcff32a576"
249 | dependencies:
250 | babel-runtime "^6.22.0"
251 | babel-template "^6.24.1"
252 | babel-traverse "^6.24.1"
253 | babel-types "^6.24.1"
254 | lodash "^4.2.0"
255 |
256 | babel-plugin-transform-es2015-classes@^6.24.1:
257 | version "6.24.1"
258 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
259 | dependencies:
260 | babel-helper-define-map "^6.24.1"
261 | babel-helper-function-name "^6.24.1"
262 | babel-helper-optimise-call-expression "^6.24.1"
263 | babel-helper-replace-supers "^6.24.1"
264 | babel-messages "^6.23.0"
265 | babel-runtime "^6.22.0"
266 | babel-template "^6.24.1"
267 | babel-traverse "^6.24.1"
268 | babel-types "^6.24.1"
269 |
270 | babel-plugin-transform-es2015-computed-properties@^6.24.1:
271 | version "6.24.1"
272 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
273 | dependencies:
274 | babel-runtime "^6.22.0"
275 | babel-template "^6.24.1"
276 |
277 | babel-plugin-transform-es2015-destructuring@^6.22.0:
278 | version "6.23.0"
279 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
280 | dependencies:
281 | babel-runtime "^6.22.0"
282 |
283 | babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
284 | version "6.24.1"
285 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
286 | dependencies:
287 | babel-runtime "^6.22.0"
288 | babel-types "^6.24.1"
289 |
290 | babel-plugin-transform-es2015-for-of@^6.22.0:
291 | version "6.23.0"
292 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
293 | dependencies:
294 | babel-runtime "^6.22.0"
295 |
296 | babel-plugin-transform-es2015-function-name@^6.24.1:
297 | version "6.24.1"
298 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
299 | dependencies:
300 | babel-helper-function-name "^6.24.1"
301 | babel-runtime "^6.22.0"
302 | babel-types "^6.24.1"
303 |
304 | babel-plugin-transform-es2015-literals@^6.22.0:
305 | version "6.22.0"
306 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e"
307 | dependencies:
308 | babel-runtime "^6.22.0"
309 |
310 | babel-plugin-transform-es2015-modules-amd@^6.24.1:
311 | version "6.24.1"
312 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
313 | dependencies:
314 | babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
315 | babel-runtime "^6.22.0"
316 | babel-template "^6.24.1"
317 |
318 | babel-plugin-transform-es2015-modules-commonjs@^6.24.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
319 | version "6.24.1"
320 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz#d3e310b40ef664a36622200097c6d440298f2bfe"
321 | dependencies:
322 | babel-plugin-transform-strict-mode "^6.24.1"
323 | babel-runtime "^6.22.0"
324 | babel-template "^6.24.1"
325 | babel-types "^6.24.1"
326 |
327 | babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
328 | version "6.24.1"
329 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
330 | dependencies:
331 | babel-helper-hoist-variables "^6.24.1"
332 | babel-runtime "^6.22.0"
333 | babel-template "^6.24.1"
334 |
335 | babel-plugin-transform-es2015-modules-umd@^6.24.1:
336 | version "6.24.1"
337 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
338 | dependencies:
339 | babel-plugin-transform-es2015-modules-amd "^6.24.1"
340 | babel-runtime "^6.22.0"
341 | babel-template "^6.24.1"
342 |
343 | babel-plugin-transform-es2015-object-super@^6.24.1:
344 | version "6.24.1"
345 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
346 | dependencies:
347 | babel-helper-replace-supers "^6.24.1"
348 | babel-runtime "^6.22.0"
349 |
350 | babel-plugin-transform-es2015-parameters@^6.24.1:
351 | version "6.24.1"
352 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
353 | dependencies:
354 | babel-helper-call-delegate "^6.24.1"
355 | babel-helper-get-function-arity "^6.24.1"
356 | babel-runtime "^6.22.0"
357 | babel-template "^6.24.1"
358 | babel-traverse "^6.24.1"
359 | babel-types "^6.24.1"
360 |
361 | babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
362 | version "6.24.1"
363 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
364 | dependencies:
365 | babel-runtime "^6.22.0"
366 | babel-types "^6.24.1"
367 |
368 | babel-plugin-transform-es2015-spread@^6.22.0:
369 | version "6.22.0"
370 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1"
371 | dependencies:
372 | babel-runtime "^6.22.0"
373 |
374 | babel-plugin-transform-es2015-sticky-regex@^6.24.1:
375 | version "6.24.1"
376 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
377 | dependencies:
378 | babel-helper-regex "^6.24.1"
379 | babel-runtime "^6.22.0"
380 | babel-types "^6.24.1"
381 |
382 | babel-plugin-transform-es2015-template-literals@^6.22.0:
383 | version "6.22.0"
384 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d"
385 | dependencies:
386 | babel-runtime "^6.22.0"
387 |
388 | babel-plugin-transform-es2015-typeof-symbol@^6.22.0:
389 | version "6.23.0"
390 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
391 | dependencies:
392 | babel-runtime "^6.22.0"
393 |
394 | babel-plugin-transform-es2015-unicode-regex@^6.24.1:
395 | version "6.24.1"
396 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
397 | dependencies:
398 | babel-helper-regex "^6.24.1"
399 | babel-runtime "^6.22.0"
400 | regexpu-core "^2.0.0"
401 |
402 | babel-plugin-transform-exponentiation-operator@^6.24.1:
403 | version "6.24.1"
404 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
405 | dependencies:
406 | babel-helper-builder-binary-assignment-operator-visitor "^6.24.1"
407 | babel-plugin-syntax-exponentiation-operator "^6.8.0"
408 | babel-runtime "^6.22.0"
409 |
410 | babel-plugin-transform-flow-strip-types@^6.22.0:
411 | version "6.22.0"
412 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf"
413 | dependencies:
414 | babel-plugin-syntax-flow "^6.18.0"
415 | babel-runtime "^6.22.0"
416 |
417 | babel-plugin-transform-object-rest-spread@^6.24.0:
418 | version "6.23.0"
419 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921"
420 | dependencies:
421 | babel-plugin-syntax-object-rest-spread "^6.8.0"
422 | babel-runtime "^6.22.0"
423 |
424 | babel-plugin-transform-react-display-name@^6.23.0:
425 | version "6.23.0"
426 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.23.0.tgz#4398910c358441dc4cef18787264d0412ed36b37"
427 | dependencies:
428 | babel-runtime "^6.22.0"
429 |
430 | babel-plugin-transform-react-jsx-self@^6.22.0:
431 | version "6.22.0"
432 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e"
433 | dependencies:
434 | babel-plugin-syntax-jsx "^6.8.0"
435 | babel-runtime "^6.22.0"
436 |
437 | babel-plugin-transform-react-jsx-source@^6.22.0:
438 | version "6.22.0"
439 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6"
440 | dependencies:
441 | babel-plugin-syntax-jsx "^6.8.0"
442 | babel-runtime "^6.22.0"
443 |
444 | babel-plugin-transform-react-jsx@^6.23.0, babel-plugin-transform-react-jsx@^6.24.1:
445 | version "6.24.1"
446 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3"
447 | dependencies:
448 | babel-helper-builder-react-jsx "^6.24.1"
449 | babel-plugin-syntax-jsx "^6.8.0"
450 | babel-runtime "^6.22.0"
451 |
452 | babel-plugin-transform-regenerator@^6.24.1:
453 | version "6.24.1"
454 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz#b8da305ad43c3c99b4848e4fe4037b770d23c418"
455 | dependencies:
456 | regenerator-transform "0.9.11"
457 |
458 | babel-plugin-transform-strict-mode@^6.24.1:
459 | version "6.24.1"
460 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758"
461 | dependencies:
462 | babel-runtime "^6.22.0"
463 | babel-types "^6.24.1"
464 |
465 | babel-preset-es2015@^6.24.1:
466 | version "6.24.1"
467 | resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
468 | dependencies:
469 | babel-plugin-check-es2015-constants "^6.22.0"
470 | babel-plugin-transform-es2015-arrow-functions "^6.22.0"
471 | babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
472 | babel-plugin-transform-es2015-block-scoping "^6.24.1"
473 | babel-plugin-transform-es2015-classes "^6.24.1"
474 | babel-plugin-transform-es2015-computed-properties "^6.24.1"
475 | babel-plugin-transform-es2015-destructuring "^6.22.0"
476 | babel-plugin-transform-es2015-duplicate-keys "^6.24.1"
477 | babel-plugin-transform-es2015-for-of "^6.22.0"
478 | babel-plugin-transform-es2015-function-name "^6.24.1"
479 | babel-plugin-transform-es2015-literals "^6.22.0"
480 | babel-plugin-transform-es2015-modules-amd "^6.24.1"
481 | babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
482 | babel-plugin-transform-es2015-modules-systemjs "^6.24.1"
483 | babel-plugin-transform-es2015-modules-umd "^6.24.1"
484 | babel-plugin-transform-es2015-object-super "^6.24.1"
485 | babel-plugin-transform-es2015-parameters "^6.24.1"
486 | babel-plugin-transform-es2015-shorthand-properties "^6.24.1"
487 | babel-plugin-transform-es2015-spread "^6.22.0"
488 | babel-plugin-transform-es2015-sticky-regex "^6.24.1"
489 | babel-plugin-transform-es2015-template-literals "^6.22.0"
490 | babel-plugin-transform-es2015-typeof-symbol "^6.22.0"
491 | babel-plugin-transform-es2015-unicode-regex "^6.24.1"
492 | babel-plugin-transform-regenerator "^6.24.1"
493 |
494 | babel-preset-es2016@^6.24.1:
495 | version "6.24.1"
496 | resolved "https://registry.yarnpkg.com/babel-preset-es2016/-/babel-preset-es2016-6.24.1.tgz#f900bf93e2ebc0d276df9b8ab59724ebfd959f8b"
497 | dependencies:
498 | babel-plugin-transform-exponentiation-operator "^6.24.1"
499 |
500 | babel-preset-es2017@^6.24.1:
501 | version "6.24.1"
502 | resolved "https://registry.yarnpkg.com/babel-preset-es2017/-/babel-preset-es2017-6.24.1.tgz#597beadfb9f7f208bcfd8a12e9b2b29b8b2f14d1"
503 | dependencies:
504 | babel-plugin-syntax-trailing-function-commas "^6.22.0"
505 | babel-plugin-transform-async-to-generator "^6.24.1"
506 |
507 | babel-preset-flow@^6.23.0:
508 | version "6.23.0"
509 | resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d"
510 | dependencies:
511 | babel-plugin-transform-flow-strip-types "^6.22.0"
512 |
513 | babel-preset-latest@^6.24.0:
514 | version "6.24.1"
515 | resolved "https://registry.yarnpkg.com/babel-preset-latest/-/babel-preset-latest-6.24.1.tgz#677de069154a7485c2d25c577c02f624b85b85e8"
516 | dependencies:
517 | babel-preset-es2015 "^6.24.1"
518 | babel-preset-es2016 "^6.24.1"
519 | babel-preset-es2017 "^6.24.1"
520 |
521 | babel-preset-react@^6.24.0:
522 | version "6.24.1"
523 | resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380"
524 | dependencies:
525 | babel-plugin-syntax-jsx "^6.3.13"
526 | babel-plugin-transform-react-display-name "^6.23.0"
527 | babel-plugin-transform-react-jsx "^6.24.1"
528 | babel-plugin-transform-react-jsx-self "^6.22.0"
529 | babel-plugin-transform-react-jsx-source "^6.22.0"
530 | babel-preset-flow "^6.23.0"
531 |
532 | babel-register@^6.24.1:
533 | version "6.24.1"
534 | resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.1.tgz#7e10e13a2f71065bdfad5a1787ba45bca6ded75f"
535 | dependencies:
536 | babel-core "^6.24.1"
537 | babel-runtime "^6.22.0"
538 | core-js "^2.4.0"
539 | home-or-tmp "^2.0.0"
540 | lodash "^4.2.0"
541 | mkdirp "^0.5.1"
542 | source-map-support "^0.4.2"
543 |
544 | babel-runtime@^6.18.0, babel-runtime@^6.22.0:
545 | version "6.23.0"
546 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b"
547 | dependencies:
548 | core-js "^2.4.0"
549 | regenerator-runtime "^0.10.0"
550 |
551 | babel-template@^6.24.1:
552 | version "6.24.1"
553 | resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.24.1.tgz#04ae514f1f93b3a2537f2a0f60a5a45fb8308333"
554 | dependencies:
555 | babel-runtime "^6.22.0"
556 | babel-traverse "^6.24.1"
557 | babel-types "^6.24.1"
558 | babylon "^6.11.0"
559 | lodash "^4.2.0"
560 |
561 | babel-traverse@^6.24.1:
562 | version "6.24.1"
563 | resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.24.1.tgz#ab36673fd356f9a0948659e7b338d5feadb31695"
564 | dependencies:
565 | babel-code-frame "^6.22.0"
566 | babel-messages "^6.23.0"
567 | babel-runtime "^6.22.0"
568 | babel-types "^6.24.1"
569 | babylon "^6.15.0"
570 | debug "^2.2.0"
571 | globals "^9.0.0"
572 | invariant "^2.2.0"
573 | lodash "^4.2.0"
574 |
575 | babel-types@^6.19.0, babel-types@^6.24.1:
576 | version "6.24.1"
577 | resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975"
578 | dependencies:
579 | babel-runtime "^6.22.0"
580 | esutils "^2.0.2"
581 | lodash "^4.2.0"
582 | to-fast-properties "^1.0.1"
583 |
584 | babylon@^6.11.0, babylon@^6.15.0:
585 | version "6.17.1"
586 | resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.1.tgz#17f14fddf361b695981fe679385e4f1c01ebd86f"
587 |
588 | balanced-match@^0.4.1:
589 | version "0.4.2"
590 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
591 |
592 | brace-expansion@^1.1.7:
593 | version "1.1.7"
594 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
595 | dependencies:
596 | balanced-match "^0.4.1"
597 | concat-map "0.0.1"
598 |
599 | chalk@^1.1.0:
600 | version "1.1.3"
601 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
602 | dependencies:
603 | ansi-styles "^2.2.1"
604 | escape-string-regexp "^1.0.2"
605 | has-ansi "^2.0.0"
606 | strip-ansi "^3.0.0"
607 | supports-color "^2.0.0"
608 |
609 | commander@^2.9.0:
610 | version "2.9.0"
611 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
612 | dependencies:
613 | graceful-readlink ">= 1.0.0"
614 |
615 | concat-map@0.0.1:
616 | version "0.0.1"
617 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
618 |
619 | convert-source-map@^1.1.0:
620 | version "1.5.0"
621 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5"
622 |
623 | core-js@^1.0.0:
624 | version "1.2.7"
625 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
626 |
627 | core-js@^2.4.0:
628 | version "2.4.1"
629 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
630 |
631 | cross-env@^3.1.4:
632 | version "3.2.4"
633 | resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-3.2.4.tgz#9e0585f277864ed421ce756f81a980ff0d698aba"
634 | dependencies:
635 | cross-spawn "^5.1.0"
636 | is-windows "^1.0.0"
637 |
638 | cross-spawn@^5.1.0:
639 | version "5.1.0"
640 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
641 | dependencies:
642 | lru-cache "^4.0.1"
643 | shebang-command "^1.2.0"
644 | which "^1.2.9"
645 |
646 | debug@^2.1.1, debug@^2.2.0:
647 | version "2.6.8"
648 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
649 | dependencies:
650 | ms "2.0.0"
651 |
652 | detect-indent@^4.0.0:
653 | version "4.0.0"
654 | resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
655 | dependencies:
656 | repeating "^2.0.0"
657 |
658 | encoding@^0.1.11:
659 | version "0.1.12"
660 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
661 | dependencies:
662 | iconv-lite "~0.4.13"
663 |
664 | entities@~1.1.1:
665 | version "1.1.1"
666 | resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
667 |
668 | escape-string-regexp@^1.0.2:
669 | version "1.0.5"
670 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
671 |
672 | esprima@^3.1.1:
673 | version "3.1.3"
674 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
675 |
676 | esutils@^2.0.0, esutils@^2.0.2:
677 | version "2.0.2"
678 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
679 |
680 | exenv@^1.2.1:
681 | version "1.2.2"
682 | resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
683 |
684 | fbjs@^0.8.9:
685 | version "0.8.12"
686 | resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.12.tgz#10b5d92f76d45575fd63a217d4ea02bea2f8ed04"
687 | dependencies:
688 | core-js "^1.0.0"
689 | isomorphic-fetch "^2.1.1"
690 | loose-envify "^1.0.0"
691 | object-assign "^4.1.0"
692 | promise "^7.1.1"
693 | setimmediate "^1.0.5"
694 | ua-parser-js "^0.7.9"
695 |
696 | front-matter@^2.1.2:
697 | version "2.1.2"
698 | resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-2.1.2.tgz#f75983b9f2f413be658c93dfd7bd8ce4078f5cdb"
699 | dependencies:
700 | js-yaml "^3.4.6"
701 |
702 | globals@^9.0.0:
703 | version "9.17.0"
704 | resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286"
705 |
706 | "graceful-readlink@>= 1.0.0":
707 | version "1.0.1"
708 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
709 |
710 | has-ansi@^2.0.0:
711 | version "2.0.0"
712 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
713 | dependencies:
714 | ansi-regex "^2.0.0"
715 |
716 | hatt@^0.2.1:
717 | version "0.2.1"
718 | resolved "https://registry.yarnpkg.com/hatt/-/hatt-0.2.1.tgz#89e20c396268520883c62e50f3d2f60431402c45"
719 |
720 | hoist-non-react-statics@^1.2.0:
721 | version "1.2.0"
722 | resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
723 |
724 | home-or-tmp@^2.0.0:
725 | version "2.0.0"
726 | resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
727 | dependencies:
728 | os-homedir "^1.0.0"
729 | os-tmpdir "^1.0.1"
730 |
731 | iconv-lite@~0.4.13:
732 | version "0.4.17"
733 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d"
734 |
735 | invariant@^2.2.0:
736 | version "2.2.2"
737 | resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
738 | dependencies:
739 | loose-envify "^1.0.0"
740 |
741 | is-finite@^1.0.0:
742 | version "1.0.2"
743 | resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
744 | dependencies:
745 | number-is-nan "^1.0.0"
746 |
747 | is-stream@^1.0.1:
748 | version "1.1.0"
749 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
750 |
751 | is-windows@^1.0.0:
752 | version "1.0.1"
753 | resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9"
754 |
755 | isexe@^2.0.0:
756 | version "2.0.0"
757 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
758 |
759 | isomorphic-fetch@^2.1.1:
760 | version "2.2.1"
761 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
762 | dependencies:
763 | node-fetch "^1.0.1"
764 | whatwg-fetch ">=0.10.0"
765 |
766 | js-tokens@^3.0.0:
767 | version "3.0.1"
768 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
769 |
770 | js-yaml@^3.4.6:
771 | version "3.8.4"
772 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6"
773 | dependencies:
774 | argparse "^1.0.7"
775 | esprima "^3.1.1"
776 |
777 | jsesc@^1.3.0:
778 | version "1.3.0"
779 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
780 |
781 | jsesc@~0.5.0:
782 | version "0.5.0"
783 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
784 |
785 | json5@^0.5.0:
786 | version "0.5.1"
787 | resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
788 |
789 | linkify-it@^2.0.0:
790 | version "2.0.3"
791 | resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f"
792 | dependencies:
793 | uc.micro "^1.0.1"
794 |
795 | lodash@^4.2.0:
796 | version "4.17.4"
797 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
798 |
799 | loose-envify@^1.0.0, loose-envify@^1.3.1:
800 | version "1.3.1"
801 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
802 | dependencies:
803 | js-tokens "^3.0.0"
804 |
805 | lru-cache@^4.0.1:
806 | version "4.0.2"
807 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e"
808 | dependencies:
809 | pseudomap "^1.0.1"
810 | yallist "^2.0.0"
811 |
812 | markdown-it@^8.2.2:
813 | version "8.3.1"
814 | resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.3.1.tgz#2f4b622948ccdc193d66f3ca2d43125ac4ac7323"
815 | dependencies:
816 | argparse "^1.0.7"
817 | entities "~1.1.1"
818 | linkify-it "^2.0.0"
819 | mdurl "^1.0.1"
820 | uc.micro "^1.0.3"
821 |
822 | mdurl@^1.0.1:
823 | version "1.0.1"
824 | resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
825 |
826 | mdxc@^1.0.0-beta.4:
827 | version "1.0.0-beta.6"
828 | resolved "https://registry.yarnpkg.com/mdxc/-/mdxc-1.0.0-beta.6.tgz#9a3588db717a34bdc4006db9eb069125d411d8c5"
829 | dependencies:
830 | babel-core "^6.24.0"
831 | babel-plugin-syntax-jsx "^6.18.0"
832 | babel-plugin-transform-react-jsx "^6.23.0"
833 | commander "^2.9.0"
834 | front-matter "^2.1.2"
835 | markdown-it "^8.2.2"
836 | parsimmon "^1.2.0"
837 | slugify "^1.1.0"
838 |
839 | minimatch@^3.0.2:
840 | version "3.0.4"
841 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
842 | dependencies:
843 | brace-expansion "^1.1.7"
844 |
845 | minimist@0.0.8:
846 | version "0.0.8"
847 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
848 |
849 | mkdirp@^0.5.1:
850 | version "0.5.1"
851 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
852 | dependencies:
853 | minimist "0.0.8"
854 |
855 | ms@2.0.0:
856 | version "2.0.0"
857 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
858 |
859 | node-fetch@^1.0.1:
860 | version "1.6.3"
861 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
862 | dependencies:
863 | encoding "^0.1.11"
864 | is-stream "^1.0.1"
865 |
866 | number-is-nan@^1.0.0:
867 | version "1.0.1"
868 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
869 |
870 | object-assign@^4.1.0:
871 | version "4.1.1"
872 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
873 |
874 | os-homedir@^1.0.0:
875 | version "1.0.2"
876 | resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
877 |
878 | os-tmpdir@^1.0.1:
879 | version "1.0.2"
880 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
881 |
882 | parsimmon@^1.2.0:
883 | version "1.2.0"
884 | resolved "https://registry.yarnpkg.com/parsimmon/-/parsimmon-1.2.0.tgz#3ed4ae6c8913066969f3faeafe39961fdcadf399"
885 |
886 | path-is-absolute@^1.0.0:
887 | version "1.0.1"
888 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
889 |
890 | private@^0.1.6:
891 | version "0.1.7"
892 | resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1"
893 |
894 | promise@^7.1.1:
895 | version "7.1.1"
896 | resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf"
897 | dependencies:
898 | asap "~2.0.3"
899 |
900 | prop-types@^15.5.10:
901 | version "15.5.10"
902 | resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154"
903 | dependencies:
904 | fbjs "^0.8.9"
905 | loose-envify "^1.3.1"
906 |
907 | pseudomap@^1.0.1:
908 | version "1.0.2"
909 | resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
910 |
911 | react-controllers@^0.1.1:
912 | version "0.1.1"
913 | resolved "https://registry.yarnpkg.com/react-controllers/-/react-controllers-0.1.1.tgz#162dbc50255fb26a63b2756c5a78e749d71325c4"
914 | dependencies:
915 | hoist-non-react-statics "^1.2.0"
916 | prop-types "^15.5.10"
917 |
918 | regenerate@^1.2.1:
919 | version "1.3.2"
920 | resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
921 |
922 | regenerator-runtime@^0.10.0:
923 | version "0.10.5"
924 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
925 |
926 | regenerator-transform@0.9.11:
927 | version "0.9.11"
928 | resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.11.tgz#3a7d067520cb7b7176769eb5ff868691befe1283"
929 | dependencies:
930 | babel-runtime "^6.18.0"
931 | babel-types "^6.19.0"
932 | private "^0.1.6"
933 |
934 | regexpu-core@^2.0.0:
935 | version "2.0.0"
936 | resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240"
937 | dependencies:
938 | regenerate "^1.2.1"
939 | regjsgen "^0.2.0"
940 | regjsparser "^0.1.4"
941 |
942 | regjsgen@^0.2.0:
943 | version "0.2.0"
944 | resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
945 |
946 | regjsparser@^0.1.4:
947 | version "0.1.5"
948 | resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
949 | dependencies:
950 | jsesc "~0.5.0"
951 |
952 | repeating@^2.0.0:
953 | version "2.0.1"
954 | resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
955 | dependencies:
956 | is-finite "^1.0.0"
957 |
958 | resize-observer-polyfill@^1.4.2:
959 | version "1.4.2"
960 | resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.4.2.tgz#a37198e6209e888acb1532a9968e06d38b6788e5"
961 |
962 | setimmediate@^1.0.5:
963 | version "1.0.5"
964 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
965 |
966 | shebang-command@^1.2.0:
967 | version "1.2.0"
968 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
969 | dependencies:
970 | shebang-regex "^1.0.0"
971 |
972 | shebang-regex@^1.0.0:
973 | version "1.0.0"
974 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
975 |
976 | slash@^1.0.0:
977 | version "1.0.0"
978 | resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
979 |
980 | slugify@^1.1.0:
981 | version "1.1.0"
982 | resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.1.0.tgz#7e5b0938d52b5efab1878247ef0f6a4f05db7ee0"
983 |
984 | source-map-support@^0.4.2:
985 | version "0.4.15"
986 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1"
987 | dependencies:
988 | source-map "^0.5.6"
989 |
990 | source-map@^0.5.0, source-map@^0.5.6:
991 | version "0.5.6"
992 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
993 |
994 | sprintf-js@~1.0.2:
995 | version "1.0.3"
996 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
997 |
998 | strip-ansi@^3.0.0:
999 | version "3.0.1"
1000 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
1001 | dependencies:
1002 | ansi-regex "^2.0.0"
1003 |
1004 | supports-color@^2.0.0:
1005 | version "2.0.0"
1006 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
1007 |
1008 | to-fast-properties@^1.0.1:
1009 | version "1.0.3"
1010 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
1011 |
1012 | trim-right@^1.0.1:
1013 | version "1.0.1"
1014 | resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
1015 |
1016 | ua-parser-js@^0.7.9:
1017 | version "0.7.12"
1018 | resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
1019 |
1020 | uc.micro@^1.0.1, uc.micro@^1.0.3:
1021 | version "1.0.3"
1022 | resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192"
1023 |
1024 | whatwg-fetch@>=0.10.0:
1025 | version "2.0.3"
1026 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
1027 |
1028 | which@^1.2.9:
1029 | version "1.2.14"
1030 | resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5"
1031 | dependencies:
1032 | isexe "^2.0.0"
1033 |
1034 | yallist@^2.0.0:
1035 | version "2.1.2"
1036 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
1037 |
--------------------------------------------------------------------------------