New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementing AST options #1
Changes from 4 commits
0380002
1593578
262c531
c975379
2d8aba1
5f4ac6c
3c6e1a6
5f236b6
e0ee4c8
02d8e83
d534988
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
// @flow | ||
|
||
import { css } from "emotion"; | ||
import { colors } from "./styles"; | ||
import React from "react"; | ||
import ReactJson from "react-json-view"; | ||
import { | ||
flatten, | ||
unflatten, | ||
filterFlatten, | ||
deleteFlatten, | ||
mergeFlatten, | ||
} from "./ASTUtils"; | ||
|
||
type Props = { | ||
className?: string, | ||
src: Object, | ||
}; | ||
|
||
type State = { | ||
src: Object, | ||
flattenSrc: Object, | ||
flattenType: Object, | ||
astOption: { | ||
autofocus: boolean, | ||
location: boolean, | ||
empty: boolean, | ||
type: boolean, | ||
}, | ||
}; | ||
|
||
const OPTION_ORDER = ["autofocus", "location", "empty", "type"]; | ||
|
||
export default class ASTPanel extends React.Component<Props, State> { | ||
state = { | ||
src: {}, | ||
flattenSrc: {}, | ||
flattenType: {}, | ||
astOption: { | ||
autofocus: true, | ||
location: true, | ||
empty: true, | ||
type: true, | ||
}, | ||
}; | ||
|
||
static getDerivedStateFromProps(nextProps: Props, prevState: State) { | ||
const flattenSrc = flatten(nextProps.src); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No harmful to be inside |
||
if (nextProps.src !== prevState.src) { | ||
return { | ||
src: unflatten(flattenSrc), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess it could be just |
||
flattenSrc: flattenSrc, | ||
flattenType: filterFlatten(flattenSrc, "type"), | ||
}; | ||
} | ||
return null; | ||
} | ||
|
||
onOptionSettingCheck(option: string) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suspect they prefer underscored name for member method. |
||
this.setState(prevState => ({ | ||
astOption: { | ||
...prevState.astOption, | ||
[option]: !prevState.astOption[option], | ||
}, | ||
})); | ||
|
||
this.onChangeJson(option); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I always prefer reducing the count of |
||
} | ||
|
||
onChangeJson(option: string) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suspect they prefer underscored name for member method. |
||
const { src, astOption, flattenSrc, flattenType } = this.state; | ||
// const OPTION_ORDER = ["autofocus", "location", "empty", "type"]; | ||
|
||
function triggerAstOutput(type) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
const isShow = astOption[type]; | ||
let newSrc = {}; | ||
const types = { | ||
autofocus: () => {}, | ||
empty: () => {}, | ||
type: () => { | ||
if (isShow) { | ||
newSrc = deleteFlatten(flattenSrc, flattenType); | ||
} else { | ||
newSrc = mergeFlatten(flattenSrc, flattenType); | ||
} | ||
return newSrc; | ||
}, | ||
location: () => { | ||
console.log(isShow, type); | ||
}, | ||
default: () => {}, | ||
}; | ||
return (types[type] || types["default"])(); | ||
} | ||
|
||
const result = triggerAstOutput(option); | ||
this.setState({ flattenSrc: result, src: unflatten(result) }); | ||
} | ||
|
||
render() { | ||
const { src, astOption } = this.state; | ||
const { className = "" } = this.props; | ||
|
||
return ( | ||
<div className={`${styles.panel} ${className}`}> | ||
<div> | ||
{OPTION_ORDER.map(option => { | ||
return ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can reduce line since it has only |
||
<label> | ||
<input | ||
checked={astOption[option]} | ||
type="checkbox" | ||
onChange={() => this.onOptionSettingCheck(option)} | ||
/> | ||
{option} | ||
</label> | ||
); | ||
})} | ||
</div> | ||
{src && ( | ||
<ReactJson | ||
src={src} | ||
style={{ | ||
overflowY: "scroll", | ||
width: "100%", | ||
}} | ||
shouldCollapse={field => field.name !== "root"} | ||
enableClipboard={false} | ||
displayObjectSize={false} | ||
displayDataTypes={false} | ||
/> | ||
)} | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
const styles = { | ||
codeMirror: css({ | ||
display: "block", | ||
height: "100%", | ||
width: "100%", | ||
overflow: "auto", | ||
position: "relative", | ||
}), | ||
// error: css({ | ||
// order: 2, | ||
// backgroundColor: colors.errorBackground, | ||
// borderTop: `1px solid ${colors.errorBorder}`, | ||
// color: colors.errorForeground, | ||
// ...sharedBoxStyles, | ||
// }), | ||
// info: css({ | ||
// order: 1, | ||
// backgroundColor: colors.infoBackground, | ||
// borderTop: `1px solid ${colors.infoBorder}`, | ||
// color: colors.infoForeground, | ||
// ...sharedBoxStyles, | ||
// }), | ||
panel: css({ | ||
height: "100%", | ||
display: "flex", | ||
flexDirection: "column", | ||
justifyContent: "stretch", | ||
overflow: "auto", | ||
}), | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// https://github.com/hughsk/flat/blob/master/index.js | ||
|
||
function isBuffer(obj) { | ||
return ( | ||
obj != null && | ||
obj.constructor != null && | ||
typeof obj.constructor.isBuffer === "function" && | ||
obj.constructor.isBuffer(obj) | ||
); | ||
} | ||
|
||
function flatten(target, opts) { | ||
opts = opts || {}; | ||
|
||
const delimiter = opts.delimiter || "."; | ||
const maxDepth = opts.maxDepth; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need a default value. |
||
const output = {}; | ||
|
||
function step(object, prev, currentDepth) { | ||
currentDepth = currentDepth || 1; | ||
Object.keys(object).forEach(function(key) { | ||
const value = object[key]; | ||
const isarray = opts.safe && Array.isArray(value); | ||
const type = Object.prototype.toString.call(value); | ||
const isbuffer = isBuffer(value); | ||
const isobject = type === "[object Object]" || type === "[object Array]"; | ||
const newKey = prev ? prev + delimiter + key : key; | ||
if ( | ||
!isarray && | ||
!isbuffer && | ||
isobject && | ||
Object.keys(value).length && | ||
(!opts.maxDepth || currentDepth < maxDepth) | ||
) { | ||
return step(value, newKey, currentDepth + 1); | ||
} | ||
output[newKey] = value; | ||
}); | ||
} | ||
|
||
step(target); | ||
|
||
return output; | ||
} | ||
|
||
function unflatten(target, opts) { | ||
opts = opts || {}; | ||
|
||
const delimiter = opts.delimiter || "."; | ||
const overwrite = opts.overwrite || false; | ||
const result = {}; | ||
const isbuffer = isBuffer(target); | ||
if ( | ||
isbuffer || | ||
Object.prototype.toString.call(target) !== "[object Object]" | ||
) { | ||
return target; | ||
} | ||
|
||
// safely ensure that the key is | ||
// an integer. | ||
function getkey(key) { | ||
const parsedKey = Number(key); | ||
|
||
return isNaN(parsedKey) || key.indexOf(".") !== -1 || opts.object | ||
? key | ||
: parsedKey; | ||
} | ||
|
||
const sortedKeys = Object.keys(target).sort(function(keyA, keyB) { | ||
return keyA.length - keyB.length; | ||
}); | ||
|
||
sortedKeys.forEach(function(key) { | ||
const split = key.split(delimiter); | ||
let key1 = getkey(split.shift()); | ||
let key2 = getkey(split[0]); | ||
let recipient = result; | ||
|
||
while (key2 !== undefined) { | ||
const type = Object.prototype.toString.call(recipient[key1]); | ||
const isobject = type === "[object Object]" || type === "[object Array]"; | ||
|
||
// do not write over falsey, non-undefined values if overwrite is false | ||
if (!overwrite && !isobject && typeof recipient[key1] !== "undefined") { | ||
return; | ||
} | ||
|
||
if ((overwrite && !isobject) || (!overwrite && recipient[key1] == null)) { | ||
recipient[key1] = typeof key2 === "number" && !opts.object ? [] : {}; | ||
} | ||
|
||
recipient = recipient[key1]; | ||
if (split.length > 0) { | ||
key1 = getkey(split.shift()); | ||
key2 = getkey(split[0]); | ||
} | ||
} | ||
|
||
// unflatten again for 'messy objects' | ||
recipient[key1] = unflatten(target[key], opts); | ||
}); | ||
|
||
return result; | ||
} | ||
|
||
function filterFlatten(flattenSrc, type) { | ||
const result = Object.keys(flattenSrc) | ||
.filter(key => { | ||
const keys = key.split("."); | ||
return keys.includes(type); | ||
}) | ||
.reduce((object, key) => { | ||
object[key] = flattenSrc[key]; | ||
return object; | ||
}, {}); | ||
return result; | ||
} | ||
|
||
function deleteFlatten(currentSrc, deletedSrc) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO, I would not use |
||
const deletedKeys = Object.keys(deletedSrc); | ||
const result = Object.keys(currentSrc).reduce((object, key) => { | ||
!deletedKeys.includes(key) ? (object[key] = currentSrc[key]) : null; | ||
return object; | ||
}, {}); | ||
return result; | ||
} | ||
|
||
function mergeFlatten(currentSrc, nextSrc) { | ||
return { | ||
...currentSrc, | ||
...nextSrc, | ||
}; | ||
} | ||
|
||
export { flatten, unflatten, filterFlatten, deleteFlatten, mergeFlatten }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,7 +35,7 @@ import { | |
import WorkerApi from "./WorkerApi"; | ||
import scopedEval from "./scopedEval"; | ||
import { colors, media } from "./styles"; | ||
import ReactJson from "react-json-view"; | ||
import ASTPanel from "./ASTPanel"; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't mean about above code example. |
||
import type { | ||
BabelPresets, | ||
|
@@ -248,17 +248,7 @@ class Repl extends React.Component<Props, State> { | |
placeholder="Write code here" | ||
/> | ||
{state.ast ? ( | ||
<ReactJson | ||
src={state.astContext} | ||
style={{ | ||
overflowY: "scroll", | ||
width: "100%", | ||
}} | ||
shouldCollapse={field => field.name !== "root"} | ||
enableClipboard={false} | ||
displayObjectSize={false} | ||
displayDataTypes={false} | ||
/> | ||
<ASTPanel src={state.astContext} /> | ||
) : ( | ||
<CodeMirrorPanel | ||
className={styles.codeMirrorPanel} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
astOptions
would be better name.