Playground: Fix "Report issue" 414 bug (#6409)

master
Ivan Pazhitnykh 2019-08-30 23:30:36 +03:00 committed by Simon Lydell
parent 2523a017aa
commit 223443c057
2 changed files with 140 additions and 129 deletions

View File

@ -1,6 +1,6 @@
import React from "react"; import React from "react";
import { Button, ClipboardButton, LinkButton } from "./buttons"; import { Button, ClipboardButton } from "./buttons";
import EditorState from "./EditorState"; import EditorState from "./EditorState";
import { DebugPanel, InputPanel, OutputPanel } from "./panels"; import { DebugPanel, InputPanel, OutputPanel } from "./panels";
import PrettierFormat from "./PrettierFormat"; import PrettierFormat from "./PrettierFormat";
@ -42,6 +42,10 @@ const ENABLED_OPTIONS = [
"requirePragma", "requirePragma",
"vueIndentScriptAndStyle" "vueIndentScriptAndStyle"
]; ];
const ISSUES_URL = "https://github.com/prettier/prettier/issues/new?body=";
const MAX_LENGTH = 8000 - ISSUES_URL.length; // it seems that GitHub limit is 8195
const COPY_MESSAGE =
"<!-- The issue body has been saved to the clipboard. Please paste it after this line! 👇 -->\n";
class Playground extends React.Component { class Playground extends React.Component {
constructor(props) { constructor(props) {
@ -135,131 +139,144 @@ class Playground extends React.Component {
debugDoc={editorState.showDoc} debugDoc={editorState.showDoc}
reformat={editorState.showSecondFormat} reformat={editorState.showSecondFormat}
> >
{({ formatted, debug }) => ( {({ formatted, debug }) => {
<React.Fragment> const fullReport = this.getMarkdown(
<div className="editors-container"> formatted,
<Sidebar visible={editorState.showSidebar}> debug.reformatted,
<SidebarOptions true
categories={CATEGORIES_ORDER} );
availableOptions={this.enabledOptions} const showFullReport =
optionValues={options} encodeURIComponent(fullReport).length < MAX_LENGTH;
onOptionValueChange={this.handleOptionValueChange} return (
/> <React.Fragment>
<SidebarCategory title="Range"> <div className="editors-container">
<label> <Sidebar visible={editorState.showSidebar}>
The selected range will be highlighted in yellow in the <SidebarOptions
input editor categories={CATEGORIES_ORDER}
</label> availableOptions={this.enabledOptions}
<Option optionValues={options}
option={this.rangeStartOption} onOptionValueChange={this.handleOptionValueChange}
value={options.rangeStart}
onChange={this.handleOptionValueChange}
/> />
<Option <SidebarCategory title="Range">
option={this.rangeEndOption} <label>
value={options.rangeEnd} The selected range will be highlighted in yellow in
overrideMax={content.length} the input editor
onChange={this.handleOptionValueChange} </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>
<SidebarCategory title="Debug">
<Checkbox
label="show AST"
checked={editorState.showAst}
onChange={editorState.toggleAst}
/>
<Checkbox
label="show doc"
checked={editorState.showDoc}
onChange={editorState.toggleDoc}
/>
<Checkbox
label="show second format"
checked={editorState.showSecondFormat}
onChange={editorState.toggleSecondFormat}
/>
</SidebarCategory>
<div className="sub-options">
<Button onClick={this.resetOptions}>
Reset to defaults
</Button>
</div>
</Sidebar>
<div className="editors">
<InputPanel
mode={util.getCodemirrorMode(options.parser)}
ruler={options.printWidth}
value={content}
codeSample={getCodeSample(options.parser)}
overlayStart={options.rangeStart}
overlayEnd={options.rangeEnd}
onChange={this.setContent}
/> />
</SidebarCategory> {editorState.showAst ? (
<SidebarCategory title="Debug"> <DebugPanel value={debug.ast || ""} />
<Checkbox ) : null}
label="show AST" {editorState.showDoc ? (
checked={editorState.showAst} <DebugPanel value={debug.doc || ""} />
onChange={editorState.toggleAst} ) : null}
/>
<Checkbox
label="show doc"
checked={editorState.showDoc}
onChange={editorState.toggleDoc}
/>
<Checkbox
label="show second format"
checked={editorState.showSecondFormat}
onChange={editorState.toggleSecondFormat}
/>
</SidebarCategory>
<div className="sub-options">
<Button onClick={this.resetOptions}>
Reset to defaults
</Button>
</div>
</Sidebar>
<div className="editors">
<InputPanel
mode={util.getCodemirrorMode(options.parser)}
ruler={options.printWidth}
value={content}
codeSample={getCodeSample(options.parser)}
overlayStart={options.rangeStart}
overlayEnd={options.rangeEnd}
onChange={this.setContent}
/>
{editorState.showAst ? (
<DebugPanel value={debug.ast || ""} />
) : null}
{editorState.showDoc ? (
<DebugPanel value={debug.doc || ""} />
) : null}
<OutputPanel
mode={util.getCodemirrorMode(options.parser)}
value={formatted}
ruler={options.printWidth}
/>
{editorState.showSecondFormat ? (
<OutputPanel <OutputPanel
mode={util.getCodemirrorMode(options.parser)} mode={util.getCodemirrorMode(options.parser)}
value={getSecondFormat(formatted, debug.reformatted)} value={formatted}
ruler={options.printWidth} ruler={options.printWidth}
/> />
) : null} {editorState.showSecondFormat ? (
<OutputPanel
mode={util.getCodemirrorMode(options.parser)}
value={getSecondFormat(formatted, debug.reformatted)}
ruler={options.printWidth}
/>
) : null}
</div>
</div> </div>
</div> <div className="bottom-bar">
<div className="bottom-bar"> <div className="bottom-bar-buttons">
<div className="bottom-bar-buttons"> <Button onClick={editorState.toggleSidebar}>
<Button onClick={editorState.toggleSidebar}> {editorState.showSidebar ? "Hide" : "Show"} options
{editorState.showSidebar ? "Hide" : "Show"} options </Button>
</Button> <Button onClick={this.clearContent}>Clear</Button>
<Button onClick={this.clearContent}>Clear</Button> <ClipboardButton
<ClipboardButton copy={JSON.stringify(
copy={JSON.stringify( // Remove `parser` since people usually paste this
// Remove `parser` since people usually paste this // into their .prettierrc and specifying a toplevel
// into their .prettierrc and specifying a toplevel // parser there is an anti-pattern. Note:
// parser there is an anti-pattern. Note: // `JSON.stringify` omits keys whose values are
// `JSON.stringify` omits keys whose values are // `undefined`.
// `undefined`. Object.assign({}, options, { parser: undefined }),
Object.assign({}, options, { parser: undefined }), null,
null, 2
2 )}
)} >
> Copy config JSON
Copy config JSON </ClipboardButton>
</ClipboardButton> </div>
<div className="bottom-bar-buttons bottom-bar-buttons-right">
<ClipboardButton copy={window.location.href}>
Copy link
</ClipboardButton>
<ClipboardButton
copy={() =>
this.getMarkdown(formatted, debug.reformatted)
}
>
Copy markdown
</ClipboardButton>
<a
href={getReportLink(
showFullReport ? fullReport : COPY_MESSAGE
)}
target="_blank"
rel="noopener noreferrer"
>
<ClipboardButton
copy={() => (showFullReport ? "" : fullReport)}
>
Report issue
</ClipboardButton>
</a>
</div>
</div> </div>
<div className="bottom-bar-buttons bottom-bar-buttons-right"> </React.Fragment>
<ClipboardButton copy={window.location.href}> );
Copy link }}
</ClipboardButton>
<ClipboardButton
copy={() =>
this.getMarkdown(formatted, debug.reformatted)
}
>
Copy markdown
</ClipboardButton>
<LinkButton
href={getReportLink(
this.getMarkdown(formatted, debug.reformatted, true)
)}
target="_blank"
rel="noopener"
>
Report issue
</LinkButton>
</div>
</div>
</React.Fragment>
)}
</PrettierFormat> </PrettierFormat>
)} )}
</EditorState> </EditorState>
@ -277,9 +294,7 @@ function orderOptions(availableOptions, order) {
} }
function getReportLink(reportBody) { function getReportLink(reportBody) {
return `https://github.com/prettier/prettier/issues/new?body=${encodeURIComponent( return `${ISSUES_URL}${encodeURIComponent(reportBody)}`;
reportBody
)}`;
} }
function getSecondFormat(formatted, reformatted) { function getSecondFormat(formatted, reformatted) {

View File

@ -5,10 +5,6 @@ export const Button = React.forwardRef((props, ref) => (
<button type="button" className="btn" ref={ref} {...props} /> <button type="button" className="btn" ref={ref} {...props} />
)); ));
export function LinkButton(props) {
return <a className="btn" {...props} />;
}
export class ClipboardButton extends React.Component { export class ClipboardButton extends React.Component {
constructor() { constructor() {
super(); super();
@ -41,16 +37,16 @@ export class ClipboardButton extends React.Component {
} }
render() { render() {
const { children } = this.props;
const { showTooltip, tooltipText } = this.state;
const rest = Object.assign({}, this.props); const rest = Object.assign({}, this.props);
delete rest.children; delete rest.children;
delete rest.copy; delete rest.copy;
return ( return (
<Button ref={this.ref} {...rest}> <Button ref={this.ref} {...rest}>
{this.state.showTooltip ? ( {showTooltip ? <span className="tooltip">{tooltipText}</span> : null}
<span className="tooltip">{this.state.tooltipText}</span> {children}
) : null}
{this.props.children}
</Button> </Button>
); );
} }