prettier/website/playground/Playground.js

282 lines
9.0 KiB
JavaScript
Raw Normal View History

2018-04-12 00:22:03 +03:00
import React from "react";
2018-04-12 21:09:04 +03:00
import { Button, ClipboardButton, LinkButton } from "./buttons";
2018-04-12 00:22:03 +03:00
import EditorState from "./EditorState";
import { DebugPanel, InputPanel, OutputPanel } from "./panels";
2018-04-12 04:28:50 +03:00
import PrettierFormat from "./PrettierFormat";
2018-04-12 19:27:34 +03:00
import { shallowEqual } from "./helpers";
import * as urlHash from "./urlHash";
import formatMarkdown from "./markdown";
2018-04-19 20:26:18 +03:00
import * as util from "./util";
import getCodeSample from "./codeSamples";
2018-04-12 18:16:16 +03:00
import { Sidebar, SidebarCategory } from "./sidebar/components";
2018-04-13 00:09:37 +03:00
import SidebarOptions from "./sidebar/SidebarOptions";
2018-04-20 17:13:09 +03:00
import Option from "./sidebar/options";
2018-04-12 18:16:16 +03:00
import { Checkbox } from "./sidebar/inputs";
const CATEGORIES_ORDER = [
"Global",
"Common",
"JavaScript",
"Markdown",
"HTML",
"Special"
];
2018-04-20 17:13:09 +03:00
const ENABLED_OPTIONS = [
"parser",
"printWidth",
"tabWidth",
"useTabs",
"semi",
"singleQuote",
"bracketSpacing",
"jsxSingleQuote",
2018-04-20 17:13:09 +03:00
"jsxBracketSameLine",
"quoteProps",
2018-04-20 17:13:09 +03:00
"arrowParens",
"trailingComma",
"proseWrap",
"htmlWhitespaceSensitivity",
2018-04-20 17:13:09 +03:00
"insertPragma",
"requirePragma"
];
2018-04-12 18:16:16 +03:00
2018-04-12 00:22:03 +03:00
class Playground extends React.Component {
2018-04-17 22:42:03 +03:00
constructor(props) {
2018-04-12 00:22:03 +03:00
super();
2018-04-12 19:27:34 +03:00
const original = urlHash.read();
2018-04-17 22:42:03 +03:00
2018-04-20 17:13:09 +03:00
const defaultOptions = util.getDefaults(
props.availableOptions,
ENABLED_OPTIONS
);
2018-04-17 22:42:03 +03:00
const options = Object.assign(defaultOptions, original.options);
const content = original.content || getCodeSample(options.parser);
this.state = { content, options };
2018-04-17 22:42:03 +03:00
2018-04-12 00:22:03 +03:00
this.handleOptionValueChange = this.handleOptionValueChange.bind(this);
this.setContent = content => this.setState({ content });
2018-04-12 17:51:49 +03:00
this.clearContent = this.setContent.bind(this, "");
2018-04-17 22:42:03 +03:00
this.resetOptions = () => this.setState({ options: defaultOptions });
2018-04-20 17:13:09 +03:00
2018-04-20 17:50:36 +03:00
this.enabledOptions = orderOptions(props.availableOptions, ENABLED_OPTIONS);
2018-04-20 17:13:09 +03:00
this.rangeStartOption = props.availableOptions.find(
opt => opt.name === "rangeStart"
);
this.rangeEndOption = props.availableOptions.find(
opt => opt.name === "rangeEnd"
);
2018-04-12 00:22:03 +03:00
}
2018-04-12 19:27:34 +03:00
componentDidUpdate(_, prevState) {
const { content, options } = this.state;
if (
!shallowEqual(prevState.options, this.state.options) ||
prevState.content !== content
) {
urlHash.replace({ content, options });
}
}
2018-04-12 00:22:03 +03:00
handleOptionValueChange(option, value) {
2018-04-19 20:46:29 +03:00
this.setState(state => {
2018-04-20 17:13:09 +03:00
const options = Object.assign({}, state.options);
2018-04-20 17:13:09 +03:00
if (option.type === "int" && isNaN(value)) {
delete options[option.name];
} else {
options[option.name] = value;
}
const content =
state.content === "" ||
state.content === getCodeSample(state.options.parser)
? getCodeSample(options.parser)
: state.content;
return { options, content };
2018-04-19 20:46:29 +03:00
});
2018-04-12 00:22:03 +03:00
}
2018-04-17 19:40:55 +03:00
getMarkdown(formatted, reformatted, full) {
2018-04-17 22:42:03 +03:00
const { content, options } = this.state;
const { availableOptions, version } = this.props;
2018-04-17 19:40:55 +03:00
return formatMarkdown(
content,
2018-04-17 19:40:55 +03:00
formatted,
reformatted || "",
version,
window.location.href,
options,
2018-04-19 20:26:18 +03:00
util.buildCliArgs(availableOptions, options),
2018-04-17 19:40:55 +03:00
full
);
}
2018-04-12 00:22:03 +03:00
render() {
2018-04-20 17:50:36 +03:00
const { worker } = this.props;
2018-04-17 22:42:03 +03:00
const { content, options } = this.state;
2018-04-12 00:22:03 +03:00
return (
2018-04-17 22:42:03 +03:00
<EditorState>
{editorState => (
<PrettierFormat
2018-04-17 23:29:44 +03:00
worker={worker}
code={content}
2018-04-17 22:42:03 +03:00
options={options}
debugAst={editorState.showAst}
debugDoc={editorState.showDoc}
2018-04-20 15:54:15 +03:00
reformat={editorState.showSecondFormat}
2018-04-17 22:42:03 +03:00
>
2018-04-19 20:46:29 +03:00
{({ formatted, debug }) => (
2018-04-17 22:42:03 +03:00
<React.Fragment>
<div className="editors-container">
<Sidebar visible={editorState.showSidebar}>
<SidebarOptions
categories={CATEGORIES_ORDER}
2018-04-20 17:50:36 +03:00
availableOptions={this.enabledOptions}
2018-04-17 22:42:03 +03:00
optionValues={options}
onOptionValueChange={this.handleOptionValueChange}
/>
2018-04-20 17:13:09 +03:00
<SidebarCategory title="Range">
<label>
The selected range will be highlighted in yellow in the
input editor
</label>
<Option
option={this.rangeStartOption}
value={options.rangeStart}
onChange={this.handleOptionValueChange}
/>
<Option
option={this.rangeEndOption}
value={options.rangeEnd}
overrideMax={content.length}
onChange={this.handleOptionValueChange}
/>
</SidebarCategory>
2018-04-17 22:42:03 +03:00
<SidebarCategory title="Debug">
<Checkbox
label="show AST"
checked={editorState.showAst}
onChange={editorState.toggleAst}
2018-04-17 16:28:35 +03:00
/>
2018-04-17 22:42:03 +03:00
<Checkbox
label="show doc"
checked={editorState.showDoc}
onChange={editorState.toggleDoc}
/>
<Checkbox
label="show second format"
checked={editorState.showSecondFormat}
onChange={editorState.toggleSecondFormat}
2018-04-12 21:09:04 +03:00
/>
2018-04-17 22:42:03 +03:00
</SidebarCategory>
<div className="sub-options">
<Button onClick={this.resetOptions}>
Reset to defaults
</Button>
</div>
</Sidebar>
<div className="editors">
<InputPanel
2018-04-19 20:26:18 +03:00
mode={util.getCodemirrorMode(options.parser)}
2018-04-20 00:57:11 +03:00
ruler={options.printWidth}
2018-04-17 22:42:03 +03:00
value={content}
codeSample={getCodeSample(options.parser)}
2018-04-20 17:13:09 +03:00
overlayStart={options.rangeStart}
overlayEnd={options.rangeEnd}
2018-04-17 22:42:03 +03:00
onChange={this.setContent}
/>
{editorState.showAst ? (
2018-04-19 20:46:29 +03:00
<DebugPanel value={debug.ast || ""} />
2018-04-17 22:42:03 +03:00
) : null}
{editorState.showDoc ? (
2018-04-19 20:46:29 +03:00
<DebugPanel value={debug.doc || ""} />
2018-04-17 22:42:03 +03:00
) : null}
<OutputPanel
2018-04-19 20:26:18 +03:00
mode={util.getCodemirrorMode(options.parser)}
2018-04-17 22:42:03 +03:00
value={formatted}
2018-04-20 00:57:11 +03:00
ruler={options.printWidth}
2018-04-17 22:42:03 +03:00
/>
{editorState.showSecondFormat ? (
2018-04-12 21:09:04 +03:00
<OutputPanel
2018-04-19 20:26:18 +03:00
mode={util.getCodemirrorMode(options.parser)}
2018-04-19 20:46:29 +03:00
value={getSecondFormat(formatted, debug.reformatted)}
2018-04-20 00:57:11 +03:00
ruler={options.printWidth}
2018-04-12 21:09:04 +03:00
/>
2018-04-17 22:42:03 +03:00
) : null}
2018-04-17 16:28:35 +03:00
</div>
2018-04-17 22:42:03 +03:00
</div>
<div className="bottom-bar">
<div className="bottom-bar-buttons">
<Button onClick={editorState.toggleSidebar}>
{editorState.showSidebar ? "Hide" : "Show"} options
</Button>
<Button onClick={this.clearContent}>Clear</Button>
<ClipboardButton copy={JSON.stringify(options, null, 2)}>
Copy config JSON
</ClipboardButton>
2018-04-17 16:28:35 +03:00
</div>
2018-04-17 22:42:03 +03:00
<div className="bottom-bar-buttons bottom-bar-buttons-right">
2018-04-17 23:29:44 +03:00
<ClipboardButton copy={window.location.href}>
2018-04-17 22:42:03 +03:00
Copy link
</ClipboardButton>
<ClipboardButton
2018-04-19 20:46:29 +03:00
copy={() =>
this.getMarkdown(formatted, debug.reformatted)
}
2018-04-17 22:42:03 +03:00
>
Copy markdown
</ClipboardButton>
<LinkButton
href={getReportLink(
2018-04-19 20:46:29 +03:00
this.getMarkdown(formatted, debug.reformatted, true)
2018-04-17 22:42:03 +03:00
)}
target="_blank"
rel="noopener"
>
Report issue
</LinkButton>
</div>
</div>
</React.Fragment>
)}
</PrettierFormat>
)}
</EditorState>
2018-04-12 00:22:03 +03:00
);
}
}
2018-04-20 17:50:36 +03:00
function orderOptions(availableOptions, order) {
const optionsByName = {};
for (const option of availableOptions) {
optionsByName[option.name] = option;
}
return order.map(name => optionsByName[name]);
}
2018-04-17 19:40:55 +03:00
function getReportLink(reportBody) {
return `https://github.com/prettier/prettier/issues/new?body=${encodeURIComponent(
reportBody
)}`;
}
function getSecondFormat(formatted, reformatted) {
return formatted === ""
? ""
: formatted === reformatted
2018-11-07 04:12:25 +03:00
? "✓ Second format is unchanged."
: reformatted;
2018-04-17 19:40:55 +03:00
}
2018-04-12 00:22:03 +03:00
export default Playground;