copy buttons + version link at the top
parent
1c8dd0c1e7
commit
94b5ab4d6e
|
@ -1,9 +1,10 @@
|
|||
import React from "react";
|
||||
|
||||
import { Button, LinkButton } from "./buttons";
|
||||
import { Button, ClipboardButton, LinkButton } from "./buttons";
|
||||
import EditorState from "./EditorState";
|
||||
import { DebugPanel, InputPanel, OutputPanel } from "./panels";
|
||||
import PrettierFormat from "./PrettierFormat";
|
||||
import VersionLink from "./VersionLink";
|
||||
import { shallowEqual } from "./helpers";
|
||||
import * as urlHash from "./urlHash";
|
||||
import formatMarkdown from "./markdown";
|
||||
|
@ -92,94 +93,121 @@ class Playground extends React.Component {
|
|||
if (!loaded) return "Loading...";
|
||||
|
||||
return (
|
||||
<EditorState>
|
||||
{editorState => (
|
||||
<div className="playground-container">
|
||||
<div className="editors-container">
|
||||
<Sidebar visible={editorState.showSidebar}>
|
||||
{categorizeOptions(
|
||||
availableOptions,
|
||||
(category, categoryOptions) => (
|
||||
<SidebarCategory key={category} title={category}>
|
||||
{categoryOptions.map(option => (
|
||||
<Option
|
||||
key={option.name}
|
||||
option={option}
|
||||
value={options[option.name]}
|
||||
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}
|
||||
/>
|
||||
</SidebarCategory>
|
||||
<div className="sub-options">
|
||||
<Button onClick={this.resetOptions}>Reset to defaults</Button>
|
||||
</div>
|
||||
</Sidebar>
|
||||
<PrettierFormat
|
||||
worker={this._worker}
|
||||
code={content}
|
||||
options={options}
|
||||
debugAst={editorState.showAst}
|
||||
debugDoc={editorState.showDoc}
|
||||
>
|
||||
{({ formatted, debugAst, debugDoc }) => (
|
||||
<div className="editors">
|
||||
<InputPanel
|
||||
mode={getCodemirrorMode(options.parser)}
|
||||
rulerColumn={options.printWidth}
|
||||
value={content}
|
||||
onChange={this.setContent}
|
||||
<React.Fragment>
|
||||
<VersionLink version={this.state.version} />
|
||||
<EditorState>
|
||||
{editorState => (
|
||||
<div className="playground-container">
|
||||
<div className="editors-container">
|
||||
<Sidebar visible={editorState.showSidebar}>
|
||||
{categorizeOptions(
|
||||
availableOptions,
|
||||
(category, categoryOptions) => (
|
||||
<SidebarCategory key={category} title={category}>
|
||||
{categoryOptions.map(option => (
|
||||
<Option
|
||||
key={option.name}
|
||||
option={option}
|
||||
value={options[option.name]}
|
||||
onChange={this.handleOptionValueChange}
|
||||
/>
|
||||
))}
|
||||
</SidebarCategory>
|
||||
)
|
||||
)}
|
||||
<SidebarCategory title="Debug">
|
||||
<Checkbox
|
||||
label="show AST"
|
||||
checked={editorState.showAst}
|
||||
onChange={editorState.toggleAst}
|
||||
/>
|
||||
{editorState.showAst ? (
|
||||
<DebugPanel value={debugAst} />
|
||||
) : null}
|
||||
{editorState.showDoc ? (
|
||||
<DebugPanel value={debugDoc} />
|
||||
) : null}
|
||||
<OutputPanel
|
||||
mode={getCodemirrorMode(options.parser)}
|
||||
value={formatted}
|
||||
rulerColumn={options.printWidth}
|
||||
<Checkbox
|
||||
label="show doc"
|
||||
checked={editorState.showDoc}
|
||||
onChange={editorState.toggleDoc}
|
||||
/>
|
||||
</SidebarCategory>
|
||||
<div className="sub-options">
|
||||
<Button onClick={this.resetOptions}>
|
||||
Reset to defaults
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</PrettierFormat>
|
||||
</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>
|
||||
</Sidebar>
|
||||
<PrettierFormat
|
||||
worker={this._worker}
|
||||
code={content}
|
||||
options={options}
|
||||
debugAst={editorState.showAst}
|
||||
debugDoc={editorState.showDoc}
|
||||
>
|
||||
{({ formatted, debugAst, debugDoc }) => (
|
||||
<div className="editors">
|
||||
<InputPanel
|
||||
mode={getCodemirrorMode(options.parser)}
|
||||
rulerColumn={options.printWidth}
|
||||
value={content}
|
||||
onChange={this.setContent}
|
||||
/>
|
||||
{editorState.showAst ? (
|
||||
<DebugPanel value={debugAst} />
|
||||
) : null}
|
||||
{editorState.showDoc ? (
|
||||
<DebugPanel value={debugDoc} />
|
||||
) : null}
|
||||
<OutputPanel
|
||||
mode={getCodemirrorMode(options.parser)}
|
||||
value={formatted}
|
||||
rulerColumn={options.printWidth}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</PrettierFormat>
|
||||
</div>
|
||||
<div className="bottom-bar-buttons bottom-bar-buttons-right">
|
||||
<Button>Copy link</Button>
|
||||
<Button>Copy markdown</Button>
|
||||
<LinkButton href="#" target="_blank" rel="noopener">
|
||||
Report issue
|
||||
</LinkButton>
|
||||
<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>
|
||||
</div>
|
||||
<div className="bottom-bar-buttons bottom-bar-buttons-right">
|
||||
<ClipboardButton clipboardValue={window.location.href}>
|
||||
Copy link
|
||||
</ClipboardButton>
|
||||
<Button>Copy markdown</Button>
|
||||
<LinkButton href="#" target="_blank" rel="noopener">
|
||||
Report issue
|
||||
</LinkButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</EditorState>
|
||||
)}
|
||||
</EditorState>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function createVersionLink(version) {
|
||||
const link = document.createElement("a");
|
||||
const match = version.match(/^\d+\.\d+\.\d+-pr.(\d+)$/);
|
||||
if (match) {
|
||||
link.href = "https://github.com/prettier/prettier/pull/" + match[1];
|
||||
link.textContent = `PR #${match[1]}`;
|
||||
} else {
|
||||
if (version.match(/\.0$/)) {
|
||||
link.href =
|
||||
"https://github.com/prettier/prettier/releases/tag/" + version;
|
||||
} else {
|
||||
link.href =
|
||||
"https://github.com/prettier/prettier/blob/master/CHANGELOG.md#" +
|
||||
version.replace(/\./g, "");
|
||||
}
|
||||
link.textContent = `v${version}`;
|
||||
}
|
||||
return link;
|
||||
}
|
||||
|
||||
function categorizeOptions(availableOptions, render) {
|
||||
const optionsByCategory = availableOptions.reduce((acc, option) => {
|
||||
let options;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
const root = document.getElementById("version");
|
||||
|
||||
export default function({ version }) {
|
||||
const match = version.match(/^\d+\.\d+\.\d+-.(\d+)$/);
|
||||
let href;
|
||||
if (match) {
|
||||
href = `pull/${match[1]}`;
|
||||
} else if (version.match(/\.0$/)) {
|
||||
href = `releases/tag/${version}`;
|
||||
} else {
|
||||
href = `blob/master/CHANGELOG.md#${version.replace(/\./g, "")}`;
|
||||
}
|
||||
return ReactDOM.createPortal(
|
||||
<a
|
||||
href={`https://github.com/prettier/prettier/${href}`}
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
{match ? `PR #${match[1]}` : `v${version}`}
|
||||
</a>,
|
||||
root
|
||||
);
|
||||
}
|
|
@ -1,9 +1,51 @@
|
|||
import React from "react";
|
||||
import ClipboardJS from "clipboard";
|
||||
|
||||
export function Button(props) {
|
||||
return <button type="button" className="btn" {...props} />;
|
||||
}
|
||||
export const Button = React.forwardRef((props, ref) => (
|
||||
<button type="button" className="btn" ref={ref} {...props} />
|
||||
));
|
||||
|
||||
export function LinkButton(props) {
|
||||
return <a className="btn" $ {...props} />;
|
||||
return <a className="btn" {...props} />;
|
||||
}
|
||||
|
||||
export class ClipboardButton extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = { showTooltip: false, tooltipText: "" };
|
||||
this.timer = null;
|
||||
this.ref = React.createRef();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.clipboard = new ClipboardJS(this.ref.current, {
|
||||
text: () => this.props.clipboardValue
|
||||
});
|
||||
this.clipboard.on("success", () => this.showTooltip("Copied!"));
|
||||
this.clipboard.on("error", () => this.showTooltip("Press ctrl+c to copy"));
|
||||
}
|
||||
|
||||
showTooltip(text) {
|
||||
this.setState({ showTooltip: true, tooltipText: text }, () => {
|
||||
if (this.timer) clearTimeout(this.timer);
|
||||
this.timer = setTimeout(() => {
|
||||
this.timer = null;
|
||||
this.setState({ showTooltip: false });
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const rest = Object.assign({}, this.props);
|
||||
delete rest.children;
|
||||
|
||||
return (
|
||||
<Button ref={this.ref} {...rest}>
|
||||
{this.state.showTooltip ? (
|
||||
<span className="tooltip">{this.state.tooltipText}</span>
|
||||
) : null}
|
||||
{this.props.children}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ module.exports = {
|
|||
]
|
||||
},
|
||||
externals: {
|
||||
clipboard: 'ClipboardJS',
|
||||
codemirror: "CodeMirror",
|
||||
react: "React",
|
||||
"react-dom": "ReactDOM"
|
||||
|
|
Loading…
Reference in New Issue