WIP: integration with prettier (#469)

* add basic format with basic parser

* remove format loading

* change formatCode to be sync

* prettier adjustments

* prettier our code

* move prettify into settings menu
main
Farzad YZ 6 years ago committed by Michael Fix
parent 86be3aae35
commit 1747534921

@ -73,13 +73,13 @@ class Editor extends React.Component {
online: Boolean(window && window.navigator && window.navigator.onLine) online: Boolean(window && window.navigator && window.navigator.onLine)
}) })
window.addEventListener('offline', this.setOffline); window.addEventListener('offline', this.setOffline)
window.addEventListener('online', this.setOnline); window.addEventListener('online', this.setOnline)
} }
componentWillUnmount() { componentWillUnmount() {
window.removeEventListener('offline', this.setOffline); window.removeEventListener('offline', this.setOffline)
window.removeEventListener('online', this.setOnline); window.removeEventListener('online', this.setOnline)
} }
componentDidUpdate() { componentDidUpdate() {
@ -101,7 +101,7 @@ class Editor extends React.Component {
if (isPNG) { if (isPNG) {
document.querySelectorAll('.CodeMirror-line > span > span').forEach(n => { document.querySelectorAll('.CodeMirror-line > span > span').forEach(n => {
if (n.innerText && n.innerText.match(/%\S\S/)) { if (n.innerText && n.innerText.match(/%\S\S/)) {
n.innerText = encodeURIComponent(n.innerText); n.innerText = encodeURIComponent(n.innerText)
} }
}) })
} }
@ -245,7 +245,8 @@ class Editor extends React.Component {
resetDefaultSettings={this.resetDefaultSettings} resetDefaultSettings={this.resetDefaultSettings}
/> />
<div className="buttons"> <div className="buttons">
{this.props.tweet && this.state.online && ( {this.props.tweet &&
this.state.online && (
<Button <Button
className="tweetButton" className="tweetButton"
onClick={this.upload} onClick={this.upload}
@ -298,16 +299,16 @@ class Editor extends React.Component {
} }
function formatTimestamp() { function formatTimestamp() {
const timezoneOffset = (new Date()).getTimezoneOffset() * 60000 const timezoneOffset = new Date().getTimezoneOffset() * 60000
const timeString = (new Date(Date.now() - timezoneOffset)).toISOString() const timeString = new Date(Date.now() - timezoneOffset)
.toISOString()
.slice(0, 19) .slice(0, 19)
.replace(/:/g, '-') .replace(/:/g, '-')
.replace('T', '_') .replace('T', '_')
return timeString; return timeString
} }
function isImage(file) { function isImage(file) {
return file.type.split('/')[0] === 'image' return file.type.split('/')[0] === 'image'
} }

@ -9,8 +9,8 @@ const Header = ({ enableHeroText }) => (
</a> </a>
{enableHeroText ? ( {enableHeroText ? (
<h2 className="mt3"> <h2 className="mt3">
Create and share beautiful images of your source code.<br /> Start typing or drop a file Create and share beautiful images of your source code.
into the text area to get started. <br /> Start typing or drop a file into the text area to get started.
</h2> </h2>
) : null} ) : null}
</div> </div>

@ -36,7 +36,7 @@ export default () => {
<meta name="og:image" content="/static/banner.png" /> <meta name="og:image" content="/static/banner.png" />
<meta name="theme-color" content="#121212" /> <meta name="theme-color" content="#121212" />
<title>Carbon</title> <title>Carbon</title>
<link rel='manifest' href='/static/manifest.json' /> <link rel="manifest" href="/static/manifest.json" />
<link rel="shortcut icon" href="/static/favicon.ico" /> <link rel="shortcut icon" href="/static/favicon.ico" />
<link rel="stylesheet" href="/_next/static/style.css" /> <link rel="stylesheet" href="/_next/static/style.css" />
<link <link

@ -8,7 +8,9 @@ import Slider from './Slider'
import Toggle from './Toggle' import Toggle from './Toggle'
import WindowPointer from './WindowPointer' import WindowPointer from './WindowPointer'
import Collapse from './Collapse' import Collapse from './Collapse'
import { COLORS } from '../lib/constants' import { COLORS } from '../lib/constants'
import { formatCode } from '../lib/util'
class Settings extends React.Component { class Settings extends React.Component {
constructor(props) { constructor(props) {
@ -17,6 +19,7 @@ class Settings extends React.Component {
isVisible: false isVisible: false
} }
this.toggle = this.toggle.bind(this) this.toggle = this.toggle.bind(this)
this.format = this.format.bind(this)
} }
toggle() { toggle() {
@ -27,6 +30,15 @@ class Settings extends React.Component {
this.setState({ isVisible: false }) this.setState({ isVisible: false })
} }
format() {
try {
const newCode = formatCode(this.props.code)
this.props.onChange('code', newCode)
} catch (e) {
// pass, create a toast here in the future.
}
}
render() { render() {
return ( return (
<div className="settings-container"> <div className="settings-container">
@ -123,8 +135,10 @@ class Settings extends React.Component {
selected={this.props.exportSize || '2x'} selected={this.props.exportSize || '2x'}
onChange={this.props.onChange.bind(null, 'exportSize')} onChange={this.props.onChange.bind(null, 'exportSize')}
/> />
<Toggle label="Prettify code" center={true} enabled={false} onChange={this.format} />
<Toggle <Toggle
label="Reset settings" label={<center className="red">Reset settings</center>}
center={true}
enabled={false} enabled={false}
onChange={this.props.resetDefaultSettings} onChange={this.props.resetDefaultSettings}
/> />
@ -186,6 +200,10 @@ class Settings extends React.Component {
.settings-settings > :global(.collapse) { .settings-settings > :global(.collapse) {
border-bottom: none; border-bottom: none;
} }
.red {
color: red;
}
`} `}
</style> </style>
</div> </div>

@ -13,7 +13,7 @@ export default class extends React.Component {
render() { render() {
const minValue = this.props.minValue || 0 const minValue = this.props.minValue || 0
const maxValue = this.props.maxValue || 100 const maxValue = this.props.maxValue || 100
const step = 'step' in this.props ? this.props.step : 1; const step = 'step' in this.props ? this.props.step : 1
return ( return (
<div className="slider"> <div className="slider">

@ -26,7 +26,8 @@ module.exports = browser => async (req, res) => {
filter: n => { filter: n => {
// %[00 -> 19] cause failures // %[00 -> 19] cause failures
if ( if (
n.innerText && n.innerText.match(/%\S\S/) && n.innerText &&
n.innerText.match(/%\S\S/) &&
n.className && n.className &&
n.className.startsWith('cm-') // is CodeMirror primitive string n.className.startsWith('cm-') // is CodeMirror primitive string
) { ) {

@ -52,9 +52,8 @@ const reverseMappings = mappings.map(mapping =>
export const serializeState = state => { export const serializeState = state => {
const stateString = encodeURIComponent(JSON.stringify(state)) const stateString = encodeURIComponent(JSON.stringify(state))
return encodeURIComponent(typeof window !== 'undefined' return encodeURIComponent(
? btoa(stateString) typeof window !== 'undefined' ? btoa(stateString) : Buffer.from(stateString).toString('base64')
: Buffer.from(stateString).toString('base64')
) )
} }

@ -1,4 +1,6 @@
import morph from 'morphmorph' import morph from 'morphmorph'
import prettier from 'prettier/standalone'
import babylonParser from 'prettier/parser-babylon'
const KEY = 'CARBON_STATE' const KEY = 'CARBON_STATE'
@ -40,3 +42,11 @@ export const fileToDataURL = blob =>
reader.onload = e => res(e.target.result) reader.onload = e => res(e.target.result)
reader.readAsDataURL(blob) reader.readAsDataURL(blob)
}) })
export const formatCode = code =>
prettier.format(code, {
parser: 'babylon',
plugins: [babylonParser],
semi: false,
singleQuote: true
})

Loading…
Cancel
Save