Add prettier

main
Andrew Dassonville 7 years ago committed by Jake Dexheimer
parent 6b1e0aedaa
commit 7e69ca2897

@ -0,0 +1,4 @@
{
singleQuote: true,
printWidth: 100
}

@ -0,0 +1,10 @@
language: node_js
node_js: stable
cache:
yarn: true
directories:
- node_modules
install:
- yarn
script:
- yarn lint

@ -1,12 +1,18 @@
import React from 'react'
import { COLORS } from '../lib/constants'
import React from 'react';
import { COLORS } from '../lib/constants';
export default (props) => (
<button onClick={props.onClick} style={Object.assign({
export default props => (
<button
onClick={props.onClick}
style={Object.assign(
{
background: COLORS.BLACK,
color: props.color,
border: `0.5px solid ${props.color}`
}, props.style)}>
},
props.style
)}
>
<span>{props.title}</span>
<style jsx>{`
button {
@ -24,4 +30,4 @@ export default (props) => (
}
`}</style>
</button>
)
);

@ -1,14 +1,14 @@
import { EOL } from 'os'
import * as hljs from 'highlight.js'
import React from 'react'
import domtoimage from 'dom-to-image'
import CodeMirror from 'react-codemirror'
import Spinner from 'react-spinner'
import toHash from 'tohash'
import WindowControls from '../components/WindowControls'
import { COLORS, DEFAULT_LANGUAGE, LANGUAGES } from '../lib/constants'
const LANGUAGE_HASH = toHash(LANGUAGES, 'module')
import { EOL } from 'os';
import * as hljs from 'highlight.js';
import React from 'react';
import domtoimage from 'dom-to-image';
import CodeMirror from 'react-codemirror';
import Spinner from 'react-spinner';
import toHash from 'tohash';
import WindowControls from '../components/WindowControls';
import { COLORS, DEFAULT_LANGUAGE, LANGUAGES } from '../lib/constants';
const LANGUAGE_HASH = toHash(LANGUAGES, 'module');
const DEFAULT_SETTINGS = {
paddingVertical: '50px',
@ -18,56 +18,56 @@ const DEFAULT_SETTINGS = {
background: '#fed0ec',
theme: 'seti',
language: DEFAULT_LANGUAGE
}
};
class Carbon extends React.Component {
constructor(props) {
super(props)
super(props);
this.state = {
loading: true,
language: props.config.language,
}
language: props.config.language
};
this.handleLanguageChange = this.handleLanguageChange.bind(this)
this.codeUpdated = this.codeUpdated.bind(this)
this.handleLanguageChange = this.handleLanguageChange.bind(this);
this.codeUpdated = this.codeUpdated.bind(this);
}
componentDidMount() {
this.setState({
loading: false
})
});
this.handleLanguageChange(this.props.children)
this.handleLanguageChange(this.props.children);
}
componentWillReceiveProps(newProps) {
this.handleLanguageChange(newProps.children, { customProps: newProps })
this.handleLanguageChange(newProps.children, { customProps: newProps });
}
codeUpdated(newCode) {
this.handleLanguageChange(newCode)
this.props.updateCode(newCode)
this.handleLanguageChange(newCode);
this.props.updateCode(newCode);
}
handleLanguageChange(newCode, config) {
const props = (config && config.customProps) || this.props
const props = (config && config.customProps) || this.props;
if (props.config.language === 'auto') {
// try to set the language
const detectedLanguage = hljs.highlightAuto(newCode).language
const languageModule = LANGUAGE_HASH[detectedLanguage]
const detectedLanguage = hljs.highlightAuto(newCode).language;
const languageModule = LANGUAGE_HASH[detectedLanguage];
if (languageModule) {
this.setState({ language: languageModule.module })
this.setState({ language: languageModule.module });
}
} else {
this.setState({ language: props.config.language })
this.setState({ language: props.config.language });
}
}
render() {
const config = Object.assign(DEFAULT_SETTINGS, this.props.config)
const config = Object.assign(DEFAULT_SETTINGS, this.props.config);
const options = {
lineNumbers: false,
@ -76,32 +76,35 @@ class Carbon extends React.Component {
scrollBarStyle: null,
viewportMargin: Infinity,
lineWrapping: true
}
};
// create styles
const containerStyle = {
background: config.background,
padding: `${config.paddingVertical} ${config.paddingHorizontal}`
}
};
// set content to spinner if loading, else editor
let content = (
<div>
<Spinner />
<style jsx>{`
<style jsx>
{`
div {
height: 352px;
}
`}
</style>
</div>
)
);
if (this.state.loading === false) {
content = (
<div id="container" style={containerStyle}>
{config.windowControls ? <WindowControls theme={config.windowTheme} /> : null}
<CodeMirror
className={`CodeMirror__container window-theme__${config.windowTheme} ${config.dropShadow ? 'dropshadow' : ''}`}
className={`CodeMirror__container window-theme__${config.windowTheme} ${config.dropShadow
? 'dropshadow'
: ''}`}
onChange={this.codeUpdated}
value={this.props.children}
options={options}
@ -147,7 +150,7 @@ class Carbon extends React.Component {
}
`}</style>
</div>
)
);
}
return (
@ -162,8 +165,8 @@ class Carbon extends React.Component {
}
`}</style>
</div>
)
);
}
}
export default Carbon
export default Carbon;

@ -1,27 +1,27 @@
import React from 'react'
import enhanceWithClickOutside from 'react-click-outside'
import { TwitterPicker } from 'react-color'
import WindowPointer from './WindowPointer'
import { COLORS } from '../lib/constants'
import React from 'react';
import enhanceWithClickOutside from 'react-click-outside';
import { TwitterPicker } from 'react-color';
import WindowPointer from './WindowPointer';
import { COLORS } from '../lib/constants';
class ColorPicker extends React.Component {
constructor() {
super()
this.state = { isVisible: false }
this.toggle = this.toggle.bind(this)
this.handlePickColor = this.handlePickColor.bind(this)
super();
this.state = { isVisible: false };
this.toggle = this.toggle.bind(this);
this.handlePickColor = this.handlePickColor.bind(this);
}
toggle() {
this.setState({ isVisible: !this.state.isVisible })
this.setState({ isVisible: !this.state.isVisible });
}
handleClickOutside() {
this.setState({ isVisible: false })
this.setState({ isVisible: false });
}
handlePickColor(color) {
this.props.onChange(color.hex)
this.props.onChange(color.hex);
}
render() {
@ -31,11 +31,15 @@ class ColorPicker extends React.Component {
<div className="colorpicker-label">
<span>BG</span>
</div>
<div className="bg-color" style={{background: this.props.bg}} onClick={this.toggle}></div>
<div className="bg-color" style={{ background: this.props.bg }} onClick={this.toggle} />
</div>
<div className="colorpicker-picker" hidden={!this.state.isVisible}>
<WindowPointer fromLeft="15px" />
<TwitterPicker color={this.props.bg} onChangeComplete={this.handlePickColor} triangle="hide" />
<TwitterPicker
color={this.props.bg}
onChangeComplete={this.handlePickColor}
triangle="hide"
/>
</div>
<style jsx>{`
.colorpicker-container {
@ -79,11 +83,11 @@ class ColorPicker extends React.Component {
width: 278px !important;
border: 0.5px solid ${COLORS.SECONDARY} !important;
border-radius: 3px !important;
background: #1A1A1A !important;
background: #1a1a1a !important;
}
.colorpicker-picker > :global(div > div:nth-child(3) > div:nth-child(11)) {
background: #1A1A1A !important;
background: #1a1a1a !important;
border: 0.5px solid ${COLORS.SECONDARY} !important;
border-right: none !important;
border-radius: 3px 0 0 3px !important;
@ -100,8 +104,8 @@ class ColorPicker extends React.Component {
}
`}</style>
</div>
)
);
}
}
export default enhanceWithClickOutside(ColorPicker)
export default enhanceWithClickOutside(ColorPicker);

@ -1,29 +1,29 @@
import React from 'react'
import enhanceWithClickOutside from 'react-click-outside'
import ArrowDown from './svg/Arrowdown'
import Checkmark from './svg/Checkmark'
import { COLORS } from '../lib/constants'
import React from 'react';
import enhanceWithClickOutside from 'react-click-outside';
import ArrowDown from './svg/Arrowdown';
import Checkmark from './svg/Checkmark';
import { COLORS } from '../lib/constants';
class Dropdown extends React.Component {
constructor(props) {
super()
super();
this.state = {
isVisible: false,
selected: props.selected || props.list[0]
}
this.select = this.select.bind(this)
this.toggle = this.toggle.bind(this)
};
this.select = this.select.bind(this);
this.toggle = this.toggle.bind(this);
}
select(item) {
if (this.state.selected !== item) {
this.props.onChange(item)
this.setState({ selected: item })
this.props.onChange(item);
this.setState({ selected: item });
}
}
toggle() {
this.setState({ isVisible: !this.state.isVisible })
this.setState({ isVisible: !this.state.isVisible });
}
handleClickOutside() {
@ -52,23 +52,29 @@ class Dropdown extends React.Component {
}
`}</style>
</div>
))
));
}
render() {
// find longest list value in number of characters
const MIN_WIDTH = this.props.list.reduce((max, { name }) =>
(name.length > max ? name.length : max), 0)
const MIN_WIDTH = this.props.list.reduce(
(max, { name }) => (name.length > max ? name.length : max),
0
);
return (
<div className="dropdown-container" style={{ minWidth: MIN_WIDTH * 16 }} onClick={this.toggle}>
<div
className="dropdown-container"
style={{ minWidth: MIN_WIDTH * 16 }}
onClick={this.toggle}
>
<div className={`dropdown-display ${this.state.isVisible ? 'is-visible' : ''}`}>
<span>{this.state.selected.name}</span>
<div className="arrow-down"><ArrowDown /></div>
<div className="arrow-down">
<ArrowDown />
</div>
<div className="dropdown-list">
{ this.renderListItems() }
</div>
<div className="dropdown-list">{this.renderListItems()}</div>
<style jsx>{`
.arrow-down {
position: absolute;
@ -115,8 +121,8 @@ class Dropdown extends React.Component {
}
`}</style>
</div>
)
);
}
}
export default enhanceWithClickOutside(Dropdown)
export default enhanceWithClickOutside(Dropdown);

@ -1,15 +1,27 @@
import React from 'react'
import Link from 'next/link'
import { COLORS } from '../lib/constants'
import React from 'react';
import Link from 'next/link';
import { COLORS } from '../lib/constants';
const Footer = (props) => (
const Footer = props => (
<div className="mt3">
<div className="mt3">
<Link href="/about"><a className="link">about</a></Link>
<a className="link" href="https://github.com/dawnlabs/carbon/issues/new">send feedback</a>
<a className="link" href="https://github.com/dawnlabs/carbon">source</a>
<Link href="/about">
<a className="link">about</a>
</Link>
<a className="link" href="https://github.com/dawnlabs/carbon/issues/new">
send feedback
</a>
<a className="link" href="https://github.com/dawnlabs/carbon">
source
</a>
</div>
<div className="mt3 mb2">
a project by{' '}
<a className="dawn-link" href="https://dawnlabs.io">
Dawn Labs
</a>{' '}
¬
</div>
<div className="mt3 mb2">a project by <a className="dawn-link" href="https://dawnlabs.io">Dawn Labs</a> ¬</div>
<style jsx>{`
div > div {
text-align: center;
@ -35,6 +47,6 @@ const Footer = (props) => (
}
`}</style>
</div>
)
);
export default Footer
export default Footer;

@ -1,11 +1,18 @@
import React from 'react'
import Logo from './svg/Logo'
import React from 'react';
import Logo from './svg/Logo';
const Header = ({ enableHeroText }) => (
<div className="header mb4">
<div className="header-content">
<a href="/"><Logo /></a>
{ enableHeroText ? (<h2 className="mt3">Create and share beautiful images of your source code.<br/> Start typing, or drop a file into the text area to get started.</h2>) : null }
<a href="/">
<Logo />
</a>
{enableHeroText ? (
<h2 className="mt3">
Create and share beautiful images of your source code.<br /> Start typing, or drop a file
into the text area to get started.
</h2>
) : null}
</div>
<style jsx>{`
.header {
@ -27,6 +34,6 @@ const Header = ({ enableHeroText }) => (
}
`}</style>
</div>
)
);
export default Header
export default Header;

@ -0,0 +1,22 @@
import React from 'react';
import { Controls, ControlsBW } from './svg/Controls';
export default ({ language }) => (
<div className="language">
{language.name}
<style jsx>
{`
.language {
position: absolute;
top: 7px;
right: 7px;
background: rgba(0, 0, 0, 0.3);
font-size: 12px;
padding: 5px;
border-radius: 3px;
z-index: 1;
}
`}
</style>
</div>
);

@ -1,7 +1,7 @@
import Head from 'next/head'
import { THEMES_ARRAY, COLORS } from '../lib/constants'
import Reset from './style/Reset'
import Typography from './style/Typography'
import Head from 'next/head';
import { THEMES_ARRAY, COLORS } from '../lib/constants';
import Reset from './style/Reset';
import Typography from './style/Typography';
export default () => (
<div className="meta">
@ -9,21 +9,38 @@ export default () => (
<meta charSet="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Carbon is the easiest way to create and share beautiful images of your source code." />
<meta
name="description"
content="Carbon is the easiest way to create and share beautiful images of your source code."
/>
<meta name="application-name" content="Carbon" />
<meta name="twitter:title" content="Carbon" />
<meta name="twitter:description" content="Carbon is the easiest way to create and share beautiful images of your source code." />
<meta
name="twitter:description"
content="Carbon is the easiest way to create and share beautiful images of your source code."
/>
<meta name="og:title" content="Carbon" />
<meta name="og:description" content="Carbon is the easiest way to create and share beautiful images of your source code." />
<meta
name="og:description"
content="Carbon is the easiest way to create and share beautiful images of your source code."
/>
<meta name="og:image" content="/static/banner.png" />
<title>Carbon</title>
<link rel="shortcut icon" href="/static/favicon.ico" />
<link rel="stylesheet" href='//cdnjs.cloudflare.com/ajax/libs/codemirror/5.26.0/codemirror.min.css' />
{
THEMES_ARRAY.map((theme, i) => (
<link key={i} rel="stylesheet" href={theme.link || `//cdnjs.cloudflare.com/ajax/libs/codemirror/5.30.0/theme/${theme.id}.min.css`}/>
))
<link
rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.26.0/codemirror.min.css"
/>
{THEMES_ARRAY.map((theme, i) => (
<link
key={i}
rel="stylesheet"
href={
theme.link ||
`//cdnjs.cloudflare.com/ajax/libs/codemirror/5.30.0/theme/${theme.id}.min.css`
}
/>
))}
<link rel="stylesheet" href="//cdn.jsdelivr.net/font-hack/2.020/css/hack-extended.min.css" />
<link rel="stylesheet" type="text/css" href="/static/react-spinner.css" />
</Head>
@ -35,4 +52,4 @@ export default () => (
}
`}</style>
</div>
)
);

@ -22,6 +22,6 @@ const Overlay = props => (
}
`}</style>
</div>
)
);
export default Overlay
export default Overlay;

@ -1,15 +1,13 @@
import React from 'react'
import Meta from './Meta'
import Header from './Header'
import Footer from './Footer'
import React from 'react';
import Meta from './Meta';
import Header from './Header';
import Footer from './Footer';
export default ({ children, enableHeroText }) => (
<div className="main mt4 mb4">
<Meta />
<Header enableHeroText={enableHeroText} />
<div className="page">
{ children }
</div>
<div className="page">{children}</div>
<Footer />
@ -22,4 +20,4 @@ export default ({ children, enableHeroText }) => (
}
`}</style>
</div>
)
);

@ -1,48 +1,61 @@
import React from 'react'
import enhanceWithClickOutside from 'react-click-outside'
import SettingsIcon from './svg/Settings'
import ThemeSelect from './ThemeSelect'
import Slider from './Slider'
import Toggle from './Toggle'
import React from 'react';
import enhanceWithClickOutside from 'react-click-outside';
import SettingsIcon from './svg/Settings';
import ThemeSelect from './ThemeSelect';
import Slider from './Slider';
import Toggle from './Toggle';
import WindowPointer from './WindowPointer';
import { COLORS } from '../lib/constants'
import { COLORS } from '../lib/constants';
class Settings extends React.Component {
constructor(props) {
super()
super();
this.state = {
isVisible: false
}
this.toggle = this.toggle.bind(this)
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({ isVisible: !this.state.isVisible })
this.setState({ isVisible: !this.state.isVisible });
}
handleClickOutside() {
this.setState({ isVisible: false })
this.setState({ isVisible: false });
}
render() {
return (
<div className="settings-container">
<div className={`settings-display ${this.state.isVisible ? 'is-visible' : ''}`} onClick={this.toggle}>
<div
className={`settings-display ${this.state.isVisible ? 'is-visible' : ''}`}
onClick={this.toggle}
>
<SettingsIcon />
</div>
<div className="settings-settings">
<WindowPointer fromLeft="15px" />
<ThemeSelect onChange={this.props.onChange.bind(null, 'windowTheme')} />
<Toggle label="Drop shadow"
<Toggle
label="Drop shadow"
enabled={this.props.enabled.dropShadow}
onChange={this.props.onChange.bind(null, 'dropShadow')}
/>
<Toggle label="Window controls"
<Toggle
label="Window controls"
enabled={this.props.enabled.windowControls}
onChange={this.props.onChange.bind(null, 'windowControls')}
/>
<Slider label="Padding (vertical)" initialValue={16} onChange={this.props.onChange.bind(null, 'paddingVertical')}/>
<Slider label="Padding (horizontal)" initialValue={32} onChange={this.props.onChange.bind(null, 'paddingHorizontal')}/>
<Slider
label="Padding (vertical)"
initialValue={16}
onChange={this.props.onChange.bind(null, 'paddingVertical')}
/>
<Slider
label="Padding (horizontal)"
initialValue={32}
onChange={this.props.onChange.bind(null, 'paddingHorizontal')}
/>
</div>
<style jsx>{`
.settings-container {
@ -93,11 +106,10 @@ class Settings extends React.Component {
.settings-settings > :global(div):first-child {
border-bottom: none;
}
`}</style>
</div>
)
);
}
}
export default enhanceWithClickOutside(Settings)
export default enhanceWithClickOutside(Settings);

@ -1,27 +1,38 @@
import React from 'react'
import React from 'react';
export default class extends React.Component {
constructor(props) {
super()
this.state = { value: props.initialValue || 0 }
this.handleChange = this.handleChange.bind(this)
super();
this.state = { value: props.initialValue || 0 };
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.setState({ value: e.target.value }, () => {
this.props.onChange(`${this.state.value}px`)
})
this.props.onChange(`${this.state.value}px`);
});
}
render() {
const minValue = this.props.minValue || 0
const maxValue = this.props.maxValue || 100
const minValue = this.props.minValue || 0;
const maxValue = this.props.maxValue || 100;
return (
<div className="slider">
<span className="label">{this.props.label}</span>
<input type="range" defaultValue={this.state.value} onChange={this.handleChange} min={minValue} max={maxValue} />
<div className="slider-bg" style={{ transform: `translate3d(${(this.state.value * 1.0 / maxValue) * 100}%, 0px, 0px)` }}></div>
<input
type="range"
defaultValue={this.state.value}
onChange={this.handleChange}
min={minValue}
max={maxValue}
/>
<div
className="slider-bg"
style={{
transform: `translate3d(${this.state.value * 1.0 / maxValue * 100}%, 0px, 0px)`
}}
/>
<style jsx>{`
.slider {
position: relative;
@ -57,9 +68,8 @@ export default class extends React.Component {
width: 100%;
background: rgba(255, 255, 255, 0.165);
}
`}</style>
</div>
)
);
}
}

@ -1,30 +1,30 @@
import React from 'react'
import { None, BW, Sharp } from './svg/WindowThemes'
import { COLORS } from '../lib/constants'
import React from 'react';
import { None, BW, Sharp } from './svg/WindowThemes';
import { COLORS } from '../lib/constants';
const WINDOW_THEMES_MAP = { none: None, sharp: Sharp, bw: BW }
export const WINDOW_THEMES = Object.keys(WINDOW_THEMES_MAP)
const WINDOW_THEMES_MAP = { none: None, sharp: Sharp, bw: BW };
export const WINDOW_THEMES = Object.keys(WINDOW_THEMES_MAP);
export default class extends React.Component {
constructor(props) {
super()
this.state = { selected: props.selected || WINDOW_THEMES[0] }
this.select = this.select.bind(this)
super();
this.state = { selected: props.selected || WINDOW_THEMES[0] };
this.select = this.select.bind(this);
}
select(theme) {
if (this.state.selected !== theme) {
this.props.onChange(theme)
this.setState({ selected: theme })
this.props.onChange(theme);
this.setState({ selected: theme });
}
}
renderThemes() {
return WINDOW_THEMES.map((theme, i) => {
const Img = WINDOW_THEMES_MAP[theme]
const Img = WINDOW_THEMES_MAP[theme];
return (
<div
className={`theme ${this.state.selected === theme ? "selected" : ""}`}
className={`theme ${this.state.selected === theme ? 'selected' : ''}`}
key={i}
onClick={this.select.bind(null, theme)}
>
@ -45,17 +45,15 @@ export default class extends React.Component {
}
`}</style>
</div>
)
})
);
});
}
render() {
return (
<div className="window-theme">
<span className="label">Window Theme</span>
<div className="themes">
{ this.renderThemes() }
</div>
<div className="themes">{this.renderThemes()}</div>
<style jsx>{`
.window-theme {
padding: 8px;
@ -73,6 +71,6 @@ export default class extends React.Component {
}
`}</style>
</div>
)
);
}
}

@ -1,17 +1,17 @@
import React from 'react'
import Checkmark from './svg/Checkmark'
import React from 'react';
import Checkmark from './svg/Checkmark';
export default class extends React.Component {
constructor(props) {
super()
this.state = { isEnabled: props.enabled || false }
this.toggle = this.toggle.bind(this)
super();
this.state = { isEnabled: props.enabled || false };
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({ isEnabled: !this.state.isEnabled }, () => {
this.props.onChange(this.state.isEnabled)
})
this.props.onChange(this.state.isEnabled);
});
}
render() {
@ -30,6 +30,6 @@ export default class extends React.Component {
}
`}</style>
</div>
)
);
}
}

@ -1,5 +1,5 @@
import React from 'react'
const Toolbar = (props) => (
import React from 'react';
const Toolbar = props => (
<div id="toolbar">
{props.children}
<style jsx>{`
@ -23,6 +23,6 @@ const Toolbar = (props) => (
}
`}</style>
</div>
)
);
export default Toolbar
export default Toolbar;

@ -1,10 +1,11 @@
import React from 'react'
import { Controls, ControlsBW } from './svg/Controls'
import React from 'react';
import { Controls, ControlsBW } from './svg/Controls';
export default ({ theme }) => (
<div className="window-controls">
{theme === 'bw' ? <ControlsBW /> : <Controls />}
<style jsx>{`
<style jsx>
{`
div {
margin-top: -24px;
position: relative;
@ -15,4 +16,4 @@ export default ({ theme }) => (
`}
</style>
</div>
)
);

@ -1,4 +1,4 @@
import React from 'react'
import React from 'react';
export default ({ fromLeft }) => (
<div style={{ left: fromLeft }}>
@ -16,4 +16,4 @@ export default ({ fromLeft }) => (
}
`}</style>
</div>
)
);

@ -1,25 +1,93 @@
import { COLORS } from '../../lib/constants'
import { COLORS } from '../../lib/constants';
export default () =>
export default () => (
<style jsx global>{`
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
@ -30,18 +98,31 @@ export default () =>
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
display: block;
}
ol, ul {
ol,
ul {
list-style: none;
}
blockquote, q {
blockquote,
q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
blockquote:before,
blockquote:after,
q:before,
q:after {
content: '';
content: none;
}
@ -57,12 +138,7 @@ export default () =>
text-rendering: optimizeLegibility;
background: ${COLORS.BLACK};
color: white;
font-family: -apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
Ubuntu,
"Helvetica Neue",
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Ubuntu, 'Helvetica Neue',
sans-serif;
font-weight: 400;
font-style: normal;
@ -73,9 +149,16 @@ export default () =>
min-height: 704px;
}
* { box-sizing: border-box; }
* {
box-sizing: border-box;
}
h1, h2, h3, h4, h5, h6 {
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 500;
}
@ -86,7 +169,7 @@ export default () =>
}
*::selection {
background: rgba(255,255,255,.99);
background: rgba(255, 255, 255, 0.99);
color: #121212;
}
@ -94,7 +177,11 @@ export default () =>
color: #fff;
text-decoration: none;
padding-bottom: 3px;
background: linear-gradient(to right, rgba(255,255,255, 0.7) 0%, rgba(255,255,255, 0.7) 100%);
background: linear-gradient(
to right,
rgba(255, 255, 255, 0.7) 0%,
rgba(255, 255, 255, 0.7) 100%
);
background-size: 1px 1px;
background-position: 0 100%;
background-repeat: repeat-x;
@ -105,3 +192,4 @@ export default () =>
background: none;
}
`}</style>
);

@ -1,4 +1,4 @@
export default () =>
export default () => (
<style jsx global>{`
/* https://github.com/jxnblk/type-system
Brent Jackson
@ -10,7 +10,7 @@ export default () =>
--h2: 2.25rem;
--h3: 1.5rem;
--h4: 1.125rem;
--h5: .75rem;
--h5: 0.75rem;
--lh: calc(4/3);
--mx: 32em;
@ -19,7 +19,7 @@ export default () =>
--m2: calc(4/3 * 1em);
--m3: calc(8/3 * 1em);
--m4: calc(16/3 * 1em);
--x1: .5rem;
--x1: 0.5rem;
--x2: 1rem;
--x3: 2rem;
--x4: 4rem;
@ -33,61 +33,146 @@ export default () =>
margin: 2rem 0;
}
h1, h2, h3 {
h1,
h2,
h3 {
margin-top: var(--m1);
margin-bottom: 0;
}
h4, h5, h6,
p, dl, ol, ul, blockquote {
h4,
h5,
h6,
p,
dl,
ol,
ul,
blockquote {
margin-top: var(--m2);
margin-bottom: var(--m2);
}
h1 { font-size: var(--h2) }
h2, h3 { font-size: var(--h3) }
h4 { font-size: var(--h4) }
h5, h6 { font-size: var(--h5) }
h1 {
font-size: var(--h2);
}
h2,
h3 {
font-size: var(--h3);
}
h4 {
font-size: var(--h4);
}
h5,
h6 {
font-size: var(--h5);
}
.h0 { font-size: var(--h0) }
.h1 { font-size: var(--h1) }
.h2 { font-size: var(--h2) }
.h3 { font-size: var(--h3) }
.h4 { font-size: var(--h4) }
.h5 { font-size: var(--h5) }
.h6 { font-size: var(--h5) }
.h0 {
font-size: var(--h0);
}
.h1 {
font-size: var(--h1);
}
.h2 {
font-size: var(--h2);
}
.h3 {
font-size: var(--h3);
}
.h4 {
font-size: var(--h4);
}
.h5 {
font-size: var(--h5);
}
.h6 {
font-size: var(--h5);
}
@media screen and (min-width: 40em) {
.xh0 { font-size: var(--h0) }
.xh1 { font-size: var(--h1) }
.xh2 { font-size: var(--h2) }
.xh3 { font-size: var(--h3) }
.xh4 { font-size: var(--h4) }
.xh5 { font-size: var(--h5) }
.xh6 { font-size: var(--h5) }
.xh0 {
font-size: var(--h0);
}
.xh1 {
font-size: var(--h1);
}
.xh2 {
font-size: var(--h2);
}
.xh3 {
font-size: var(--h3);
}
.xh4 {
font-size: var(--h4);
}
.xh5 {
font-size: var(--h5);
}
.xh6 {
font-size: var(--h5);
}
}
.lh1 { line-height: 1 }
.lh1 {
line-height: 1;
}
/* h0, h1, h3 */
.lh2 { line-height: calc(7/6 * 1em) }
.lh2 {
line-height: calc(7/6 * 1em);
}
/* For body copy */
.lh3 { line-height: calc(16/9 * 1em) }
.lh3 {
line-height: calc(16/9 * 1em);
}
.mt0 { margin-top: 0 }
.mb0 { margin-bottom: 0 }
.mt1 { margin-top: var(--x1) }
.mb1 { margin-bottom: var(--x1) }
.mt2 { margin-top: var(--x2) }
.mb2 { margin-bottom: var(--x2) }
.mt3 { margin-top: var(--x3) }
.mb3 { margin-bottom: var(--x3) }
.mt4 { margin-top: var(--x4) }
.mb4 { margin-bottom: var(--x4) }
.mt5 { margin-top: var(--x5) }
.mb5 { margin-bottom: var(--x5) }
.mt6 { margin-top: var(--x6) }
.mb6 { margin-bottom: var(--x6) }
.mt0 {
margin-top: 0;
}
.mb0 {
margin-bottom: 0;
}
.mt1 {
margin-top: var(--x1);
}
.mb1 {
margin-bottom: var(--x1);
}
.mt2 {
margin-top: var(--x2);
}
.mb2 {
margin-bottom: var(--x2);
}
.mt3 {
margin-top: var(--x3);
}
.mb3 {
margin-bottom: var(--x3);
}
.mt4 {
margin-top: var(--x4);
}
.mb4 {
margin-bottom: var(--x4);
}
.mt5 {
margin-top: var(--x5);
}
.mb5 {
margin-bottom: var(--x5);
}
.mt6 {
margin-top: var(--x6);
}
.mb6 {
margin-bottom: var(--x6);
}
.mx { max-width: var(--mx) }
.bold { font-weight: bold }
.mx {
max-width: var(--mx);
}
.bold {
font-weight: bold;
}
`}</style>
);

@ -1,7 +1,12 @@
import React from 'react'
import React from 'react';
export default () => (
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="6" viewBox="0 0 10 6">
<path fill="#fff" fillRule="evenodd" d="M93.7890633,17.6396882 L97.4926052,14.0851393 C97.6061243,13.9716202 97.7196417,13.9716202 97.8331608,14.0851393 L98.4929872,14.723681 C98.6065063,14.8372001 98.6065063,14.9507175 98.4929872,15.0642366 L93.9593411,19.4063203 C93.9167714,19.4488899 93.8600127,19.4701744 93.7890633,19.4701744 C93.7181138,19.4701744 93.6613552,19.4488899 93.6187855,19.4063203 L89.0851393,15.0642366 C88.9716202,14.9507175 88.9716202,14.8372001 89.0851393,14.723681 L89.7449658,14.0851393 C89.8584849,13.9716202 89.9720022,13.9716202 90.0855213,14.0851393 L93.7890633,17.6396882 Z" transform="translate(-89 -14)"/>
<path
fill="#fff"
fillRule="evenodd"
d="M93.7890633,17.6396882 L97.4926052,14.0851393 C97.6061243,13.9716202 97.7196417,13.9716202 97.8331608,14.0851393 L98.4929872,14.723681 C98.6065063,14.8372001 98.6065063,14.9507175 98.4929872,15.0642366 L93.9593411,19.4063203 C93.9167714,19.4488899 93.8600127,19.4701744 93.7890633,19.4701744 C93.7181138,19.4701744 93.6613552,19.4488899 93.6187855,19.4063203 L89.0851393,15.0642366 C88.9716202,14.9507175 88.9716202,14.8372001 89.0851393,14.723681 L89.7449658,14.0851393 C89.8584849,13.9716202 89.9720022,13.9716202 90.0855213,14.0851393 L93.7890633,17.6396882 Z"
transform="translate(-89 -14)"
/>
</svg>
)
);

@ -1,7 +1,11 @@
import React from 'react'
import React from 'react';
export default () => (
<svg xmlns="http://www.w3.org/2000/svg" width="9" height="8" viewBox="0 0 9 7">
<polygon fill="#FFFFFF" fillRule="evenodd" points="2.852 5.016 8.275 0 9 .67 2.852 6.344 0 3.711 .713 3.042"/>
<polygon
fill="#FFFFFF"
fillRule="evenodd"
points="2.852 5.016 8.275 0 9 .67 2.852 6.344 0 3.711 .713 3.042"
/>
</svg>
)
);

@ -1,4 +1,4 @@
import React from 'react'
import React from 'react';
export const Controls = () => (
<svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14">
@ -8,7 +8,7 @@ export const Controls = () => (
<circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" strokeWidth=".5" />
</g>
</svg>
)
);
export const ControlsBW = () => (
<svg xmlns="http://www.w3.org/2000/svg" width="54" height="16" viewBox="0 0 54 14">
@ -18,4 +18,4 @@ export const ControlsBW = () => (
<circle cx="46" cy="6" r="6" />
</g>
</svg>
)
);

File diff suppressed because one or more lines are too long

@ -1,7 +1,12 @@
import React from 'react'
import React from 'react';
export default () => (
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 18 18">
<path fill="#fff" fillRule="evenodd" d="M206.532032,366.702224 L208.523318,368.142728 C208.69279,368.3122 208.721035,368.509915 208.608053,368.735877 L206.786238,371.74399 C206.673257,371.969953 206.503788,372.040565 206.277825,371.955829 L203.989964,371.066106 C203.283831,371.546276 202.775423,371.842848 202.464724,371.955829 L202.125782,374.286058 C202.069291,374.51202 201.913944,374.625 201.659736,374.625 L198.058474,374.625 C197.804266,374.625 197.648919,374.51202 197.592428,374.286058 L197.253486,371.955829 C196.829806,371.786357 196.321398,371.489786 195.728246,371.066106 L193.440385,371.955829 C193.214422,372.068811 193.044953,371.998198 192.931972,371.74399 L191.110157,368.735877 C190.96893,368.481669 190.997175,368.283955 191.194892,368.142728 L193.101443,366.702224 C193.101443,366.617488 193.094382,366.476263 193.080259,366.278546 C193.066136,366.080828 193.059075,365.925481 193.059075,365.8125 C193.059075,365.699519 193.066136,365.544172 193.080259,365.346454 C193.094382,365.148737 193.101443,365.007512 193.101443,364.922776 L191.152525,363.482272 C190.983053,363.3128 190.954808,363.115085 191.067789,362.889123 L192.889604,359.88101 C193.002585,359.655047 193.172055,359.584435 193.398017,359.669171 L195.685878,360.558894 C196.392011,360.078724 196.90042,359.782152 197.211118,359.669171 L197.550061,357.338942 C197.606551,357.11298 197.761898,357 198.016106,357 L201.617368,357 C201.871576,357 202.026923,357.11298 202.083414,357.338942 L202.379988,359.669171 C202.803668,359.838643 203.312077,360.135214 203.905229,360.558894 L206.150722,359.669171 C206.376684,359.556189 206.560276,359.626802 206.701503,359.88101 L208.523318,362.889123 C208.664544,363.143331 208.6363,363.341045 208.438582,363.482272 L206.532032,364.922776 C206.532032,365.007512 206.539093,365.148737 206.553216,365.346454 C206.567338,365.544172 206.5744,365.699519 206.5744,365.8125 C206.5744,366.23618 206.560277,366.532752 206.532032,366.702224 Z M199.795553,368.905349 C200.671159,368.905349 201.419649,368.608777 202.041046,368.015625 C202.662443,367.422473 202.973138,366.688105 202.973138,365.8125 C202.973138,364.936895 202.662443,364.202527 202.041046,363.609375 C201.419649,363.016223 200.671159,362.719651 199.795553,362.719651 C198.919948,362.719651 198.178519,363.016223 197.571244,363.609375 C196.96397,364.202527 196.660337,364.936895 196.660337,365.8125 C196.660337,366.688105 196.96397,367.422473 197.571244,368.015625 C198.178519,368.608777 198.919948,368.905349 199.795553,368.905349 Z" transform="translate(-191 -357)"/>
<path
fill="#fff"
fillRule="evenodd"
d="M206.532032,366.702224 L208.523318,368.142728 C208.69279,368.3122 208.721035,368.509915 208.608053,368.735877 L206.786238,371.74399 C206.673257,371.969953 206.503788,372.040565 206.277825,371.955829 L203.989964,371.066106 C203.283831,371.546276 202.775423,371.842848 202.464724,371.955829 L202.125782,374.286058 C202.069291,374.51202 201.913944,374.625 201.659736,374.625 L198.058474,374.625 C197.804266,374.625 197.648919,374.51202 197.592428,374.286058 L197.253486,371.955829 C196.829806,371.786357 196.321398,371.489786 195.728246,371.066106 L193.440385,371.955829 C193.214422,372.068811 193.044953,371.998198 192.931972,371.74399 L191.110157,368.735877 C190.96893,368.481669 190.997175,368.283955 191.194892,368.142728 L193.101443,366.702224 C193.101443,366.617488 193.094382,366.476263 193.080259,366.278546 C193.066136,366.080828 193.059075,365.925481 193.059075,365.8125 C193.059075,365.699519 193.066136,365.544172 193.080259,365.346454 C193.094382,365.148737 193.101443,365.007512 193.101443,364.922776 L191.152525,363.482272 C190.983053,363.3128 190.954808,363.115085 191.067789,362.889123 L192.889604,359.88101 C193.002585,359.655047 193.172055,359.584435 193.398017,359.669171 L195.685878,360.558894 C196.392011,360.078724 196.90042,359.782152 197.211118,359.669171 L197.550061,357.338942 C197.606551,357.11298 197.761898,357 198.016106,357 L201.617368,357 C201.871576,357 202.026923,357.11298 202.083414,357.338942 L202.379988,359.669171 C202.803668,359.838643 203.312077,360.135214 203.905229,360.558894 L206.150722,359.669171 C206.376684,359.556189 206.560276,359.626802 206.701503,359.88101 L208.523318,362.889123 C208.664544,363.143331 208.6363,363.341045 208.438582,363.482272 L206.532032,364.922776 C206.532032,365.007512 206.539093,365.148737 206.553216,365.346454 C206.567338,365.544172 206.5744,365.699519 206.5744,365.8125 C206.5744,366.23618 206.560277,366.532752 206.532032,366.702224 Z M199.795553,368.905349 C200.671159,368.905349 201.419649,368.608777 202.041046,368.015625 C202.662443,367.422473 202.973138,366.688105 202.973138,365.8125 C202.973138,364.936895 202.662443,364.202527 202.041046,363.609375 C201.419649,363.016223 200.671159,362.719651 199.795553,362.719651 C198.919948,362.719651 198.178519,363.016223 197.571244,363.609375 C196.96397,364.202527 196.660337,364.936895 196.660337,365.8125 C196.660337,366.688105 196.96397,367.422473 197.571244,368.015625 C198.178519,368.608777 198.919948,368.905349 199.795553,368.905349 Z"
transform="translate(-191 -357)"
/>
</svg>
)
);

@ -1,7 +1,13 @@
import React from 'react'
import React from 'react';
export const Sharp = () => (
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 81 81" xmlnsXlink="http://www.w3.org/1999/xlink">
<svg
xmlns="http://www.w3.org/2000/svg"
width="50"
height="50"
viewBox="0 0 81 81"
xmlnsXlink="http://www.w3.org/1999/xlink"
>
<defs>
<rect id="a" width="81" height="81" rx="3" />
</defs>
@ -11,18 +17,46 @@ export const Sharp = () => (
</mask>
<use fill="#616161" xlinkHref="#a" />
<g transform="translate(16 32)" mask="url(#b)">
<path fill="#000000" fillRule="nonzero" d="M66.0458013,46.1092762 C66.0458013,48.3193105 64.2622787,50.1077029 62.050805,50.1077029 L0.174089069,50.1077029 L0.174089069,6.16868499 C0.174089069,0.174657534 0.174089069,0.174657534 0.174089069,0.174657534 L66.0458013,0.174657534 L66.0458013,46.1092762 Z"/>
<path
fill="#000000"
fillRule="nonzero"
d="M66.0458013,46.1092762 C66.0458013,48.3193105 64.2622787,50.1077029 62.050805,50.1077029 L0.174089069,50.1077029 L0.174089069,6.16868499 C0.174089069,0.174657534 0.174089069,0.174657534 0.174089069,0.174657534 L66.0458013,0.174657534 L66.0458013,46.1092762 Z"
/>
<g transform="translate(19.96 15.27)">
<ellipse cx="7.045" cy="7.048" fill="#FF5E55" fillRule="nonzero" stroke="#E0443E" strokeWidth=".5" rx="7.045" ry="7.048"/>
<ellipse cx="30.526" cy="7.048" fill="#FFC02C" fillRule="nonzero" stroke="#DEA123" strokeWidth=".5" rx="7.045" ry="7.048"/>
<ellipse
cx="7.045"
cy="7.048"
fill="#FF5E55"
fillRule="nonzero"
stroke="#E0443E"
strokeWidth=".5"
rx="7.045"
ry="7.048"
/>
<ellipse
cx="30.526"
cy="7.048"
fill="#FFC02C"
fillRule="nonzero"
stroke="#DEA123"
strokeWidth=".5"
rx="7.045"
ry="7.048"
/>
</g>
</g>
</g>
</svg>
)
);
export const BW = () => (
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 81 81" xmlnsXlink="http://www.w3.org/1999/xlink">
<svg
xmlns="http://www.w3.org/2000/svg"
width="50"
height="50"
viewBox="0 0 81 81"
xmlnsXlink="http://www.w3.org/1999/xlink"
>
<defs>
<rect id="a" width="81" height="81" rx="3" />
</defs>
@ -32,7 +66,12 @@ export const BW = () => (
</mask>
<use fill="#616161" xlinkHref="#a" />
<g transform="translate(17 33)" mask="url(#b)">
<path fill="#000000" stroke="#FFFFFF" strokeWidth="2" d="M65.0458013,49.1077029 C66.0458013,49.1077029 0.174089069,49.1077029 0.174089069,49.1077029 L0.174089069,5.16868499 C0.174089069,2.41055979 2.40986586,0.174657534 5.17268563,0.174657534 L65.0458013,0.174657534 L65.0458013,49.1077029 Z"/>
<path
fill="#000000"
stroke="#FFFFFF"
strokeWidth="2"
d="M65.0458013,49.1077029 C66.0458013,49.1077029 0.174089069,49.1077029 0.174089069,49.1077029 L0.174089069,5.16868499 C0.174089069,2.41055979 2.40986586,0.174657534 5.17268563,0.174657534 L65.0458013,0.174657534 L65.0458013,49.1077029 Z"
/>
<g fillRule="nonzero" stroke="#878787" transform="translate(18.96 14.27)">
<ellipse cx="7.045" cy="7.048" rx="7.045" ry="7.048" />
<ellipse cx="30.526" cy="7.048" rx="7.045" ry="7.048" />
@ -40,10 +79,16 @@ export const BW = () => (
</g>
</g>
</svg>
)
);
export const None = () => (
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 81 81" xmlnsXlink="http://www.w3.org/1999/xlink">
<svg
xmlns="http://www.w3.org/2000/svg"
width="50"
height="50"
viewBox="0 0 81 81"
xmlnsXlink="http://www.w3.org/1999/xlink"
>
<defs>
<rect id="a" width="81" height="81" rx="3" />
</defs>
@ -53,7 +98,11 @@ export const None = () => (
</mask>
<use fill="#616161" xlinkHref="#a" />
<g transform="translate(16 32)" mask="url(#b)">
<path fill="#000000" fillRule="nonzero" d="M66.0458013,46.1092762 C66.0458013,48.3193105 64.2622787,50.1077029 62.050805,50.1077029 L0.174089069,50.1077029 L0.174089069,6.16868499 C0.174089069,2.85738806 2.85846845,0.174657534 6.17268563,0.174657534 L66.0458013,0.174657534 L66.0458013,46.1092762 Z"/>
<path
fill="#000000"
fillRule="nonzero"
d="M66.0458013,46.1092762 C66.0458013,48.3193105 64.2622787,50.1077029 62.050805,50.1077029 L0.174089069,50.1077029 L0.174089069,6.16868499 C0.174089069,2.85738806 2.85846845,0.174657534 6.17268563,0.174657534 L66.0458013,0.174657534 L66.0458013,46.1092762 Z"
/>
<g fillRule="nonzero" strokeWidth=".5" transform="translate(19.96 15.27)">
<ellipse cx="7.045" cy="7.048" fill="#FF5E55" stroke="#E0443E" rx="7.045" ry="7.048" />
<ellipse cx="30.526" cy="7.048" fill="#FFC02C" stroke="#DEA123" rx="7.045" ry="7.048" />
@ -61,4 +110,4 @@ export const None = () => (
</g>
</g>
</svg>
)
);

@ -1,46 +1,46 @@
const Twitter = require('twitter')
const morph = require('morphmorph')
const Twitter = require('twitter');
const morph = require('morphmorph');
const RATE_LIMIT_CODE = 420
const RATE_LIMIT_CODE = 420;
const client = new Twitter({
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET
})
});
const uploadImage = data => client.post('media/upload', { media_data: data })
const uploadImage = data => client.post('media/upload', { media_data: data });
const uploadTweet = (media = {}) =>
client.post('statuses/update', {
status: `Carbon Copy #${media.media_id_string.slice(0, 8)}`,
media_ids: media.media_id_string
})
});
const extractImageUrl = morph.get('entities.media.0.display_url')
const extractErrorCode = morph.get('0.code')
const extractImageUrl = morph.get('entities.media.0.display_url');
const extractErrorCode = morph.get('0.code');
const respondSuccess = (res, url) => res.json({ url })
const respondSuccess = (res, url) => res.json({ url });
const respondFail = (res, err) => {
const errorCode = extractErrorCode(err)
const errorCode = extractErrorCode(err);
// check for rate limit
if (errorCode === RATE_LIMIT_CODE) {
return res.status(420).send()
return res.status(420).send();
}
console.error(`Error: ${err.message || JSON.stringify(err, null, 2)}`)
res.status(500).send()
}
console.error(`Error: ${err.message || JSON.stringify(err, null, 2)}`);
res.status(500).send();
};
module.exports = (req, res) => {
if (!req.body.data) {
return res.status(400).send()
return res.status(400).send();
}
uploadImage(req.body.data)
.then(uploadTweet)
.then(extractImageUrl)
.then(respondSuccess.bind(null, res))
.catch(respondFail.bind(null, res))
}
.catch(respondFail.bind(null, res));
};

@ -1,9 +1,9 @@
import axios from 'axios'
import debounce from 'lodash.debounce'
import ms from 'ms'
import axios from 'axios';
import debounce from 'lodash.debounce';
import ms from 'ms';
const DOMAIN = process.browser ? document.location.origin : ''
const RATE_LIMIT_CODE = 420
const DOMAIN = process.browser ? document.location.origin : '';
const RATE_LIMIT_CODE = 420;
const gistClient = axios.create({
baseURL: 'https://api.github.com',
@ -15,46 +15,50 @@ const gistClient = axios.create({
});
async function tweet(encodedImage) {
const processedData = encodedImage.split(',')[1]
const processedData = encodedImage.split(',')[1];
return axios.post(`${DOMAIN}/twitter`, { data: processedData })
return axios
.post(`${DOMAIN}/twitter`, { data: processedData })
.then(res => res.data.url)
.then(url => encodeURIComponent(`Built with #Carbon, by @dawn_labs ${url}`))
.then(uri => `https://twitter.com/intent/tweet?text=${uri}`)
.then(openTwitterUrl)
.catch(checkIfRateLimited)
.catch(checkIfRateLimited);
}
const getGist = (id) => {
const uid = id.split('/').pop()
return gistClient.get(`/gists/${uid}`)
const getGist = id => {
const uid = id.split('/').pop();
return gistClient
.get(`/gists/${uid}`)
.then(res => res.data)
.then(gist => gist.files)
.then(files => files[Object.keys(files)[0]])
.then(file => file.content)
}
.then(file => file.content);
};
// private
function openTwitterUrl(twitterUrl) {
const width = 575, height = 400
const left = (window.outerWidth - width) / 2
const right = (window.outerHeight - height) / 2
const opts = `status=1,width=${width},height=${height},top=${top},left=${left}`
const width = 575,
height = 400;
const left = (window.outerWidth - width) / 2;
const right = (window.outerHeight - height) / 2;
const opts = `status=1,width=${width},height=${height},top=${top},left=${left}`;
window.open(twitterUrl, 'twitter', opts)
window.open(twitterUrl, 'twitter', opts);
}
function checkIfRateLimited(err) {
if (err.response.status === RATE_LIMIT_CODE) {
alert('Oh no! Looks like to many people are trying to tweet right now and we\'ve been rate limited. Try again soon or save and upload manually!')
return
alert(
"Oh no! Looks like to many people are trying to tweet right now and we've been rate limited. Try again soon or save and upload manually!"
);
return;
}
throw err
throw err;
}
export default {
getGist,
tweet: debounce(tweet, ms('5s'), { leading: true, trailing: true })
}
};

@ -1,4 +1,4 @@
import toHash from 'tohash'
import toHash from 'tohash';
export const THEMES_ARRAY = [
{
@ -67,9 +67,9 @@ export const THEMES_ARRAY = [
id: 'zenburn',
name: 'Zenburn'
}
]
];
export const THEMES = toHash(THEMES_ARRAY)
export const THEMES = toHash(THEMES_ARRAY);
export const LANGUAGES = [
{
@ -277,16 +277,16 @@ export const LANGUAGES = [
name: 'YAML',
module: 'yaml'
}
]
];
export const DEFAULT_LANGUAGE = 'auto'
export const DEFAULT_LANGUAGE = 'auto';
export const COLORS = {
BLACK: '#121212',
PRIMARY: '#F8E81C',
SECONDARY: '#fff',
GRAY: '#858585'
}
};
export const DEFAULT_CODE = `const pluckDeep = key => obj => key.split('.').reduce((accum, key) => accum[key], obj)
@ -298,16 +298,14 @@ const unfold = (f, seed) => {
return res ? go(f, res[1], acc.concat([res[0]])) : acc
}
return go(f, seed, [])
}`
}`;
if (typeof window !== 'undefined' && typeof window.navigator !== 'undefined') {
LANGUAGES
.filter(language => language.module !== 'auto')
.forEach((language) => {
LANGUAGES.filter(language => language.module !== 'auto').forEach(language => {
if (language.module) {
!language.custom
? require(`codemirror/mode/${language.module}/${language.module}`)
: require(`./customModes/${language.module}`)
: require(`./customModes/${language.module}`);
}
})
});
}

@ -1,10 +1,9 @@
const CodeMirror = require('codemirror')
const CodeMirror = require('codemirror');
CodeMirror.defineMode("kotlin", function(config, parserConfig) {
CodeMirror.defineMode('kotlin', function(config, parserConfig) {
function words(str) {
var obj = {},
words = str.split(" ");
words = str.split(' ');
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
@ -12,15 +11,17 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
var multiLineStrings = parserConfig.multiLineStrings;
var keywords = words(
"package continue return object while break class data trait throw super " +
"when type this else This try val var fun for is in if do as true false null get set " +
"import where by get set abstract enum open annotation override private public internal " +
"protected catch out vararg inline finally final ref const");
var blockKeywords = words("catch class do else finally for if where try while enum");
var atoms = words("null true false this");
'package continue return object while break class data trait throw super ' +
'when type this else This try val var fun for is in if do as true false null get set ' +
'import where by get set abstract enum open annotation override private public internal ' +
'protected catch out vararg inline finally final ref const'
);
var blockKeywords = words('catch class do else finally for if where try while enum');
var atoms = words('null true false this');
var builtins = words(
"Int Double Float Long Short Byte IntArray ShortArray ByteArray String Boolean List Set " +
"Map MutableList MutableSet print println shl shr ushr and or xor inv ");
'Int Double Float Long Short Byte IntArray ShortArray ByteArray String Boolean List Set ' +
'Map MutableList MutableSet print println shl shr ushr and or xor inv '
);
var curPunc;
@ -32,8 +33,8 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
}
// Wildcard import w/o trailing semicolon (import smth.*)
if (ch == "." && stream.eat("*")) {
return "word";
if (ch == '.' && stream.eat('*')) {
return 'word';
}
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
@ -47,18 +48,18 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
stream.eatWhile(/\d/);
}
return "number";
return 'number';
}
if (ch == "/") {
if (stream.eat("*")) {
if (ch == '/') {
if (stream.eat('*')) {
state.tokenize.push(tokenComment);
return tokenComment(stream, state);
}
if (stream.eat("/")) {
if (stream.eat('/')) {
stream.skipToEnd();
return "comment";
return 'comment';
}
if (expectExpression(state.lastToken)) {
@ -67,14 +68,14 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
}
// Commented
if (ch == "-" && stream.eat(">")) {
curPunc = "->";
if (ch == '-' && stream.eat('>')) {
curPunc = '->';
return null;
}
if (/[\-+*&%=<>!?|\/~]/.test(ch)) {
stream.eatWhile(/[\-+*&%=<>|~]/);
return "operator";
return 'operator';
}
stream.eatWhile(/[\w\$_]/);
@ -82,33 +83,34 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
var cur = stream.current();
if (atoms.propertyIsEnumerable(cur)) {
return "atom";
return 'atom';
}
if (keywords.propertyIsEnumerable(cur)) {
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
return "keyword";
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = 'newstatement';
return 'keyword';
}
if (builtins.propertyIsEnumerable(cur)) {
return "builtin";
return 'builtin';
}
return "word";
return 'word';
}
tokenBase.isBase = true;
function startString(quote, stream, state) {
var tripleQuoted = false;
if (quote != "/" && stream.eat(quote)) {
if (quote != '/' && stream.eat(quote)) {
if (stream.eat(quote)) tripleQuoted = true;
else return "string";
else return 'string';
}
function t(stream, state) {
var escaped = false,
next, end = !tripleQuoted;
next,
end = !tripleQuoted;
while ((next = stream.next()) != null) {
if (next == quote && !escaped) {
@ -122,24 +124,23 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
}
}
if (quote == '"' && next == "$" && !escaped && stream.eat("{")) {
if (quote == '"' && next == '$' && !escaped && stream.eat('{')) {
state.tokenize.push(tokenBaseUntilBrace());
return "string";
return 'string';
}
if (next == "$" && !escaped && !stream.eat(" ")) {
if (next == '$' && !escaped && !stream.eat(' ')) {
state.tokenize.push(tokenBaseUntilSpace());
return "string";
return 'string';
}
escaped = !escaped && next == "\\";
escaped = !escaped && next == '\\';
}
if (multiLineStrings)
state.tokenize.push(t);
if (multiLineStrings) state.tokenize.push(t);
if (end) state.tokenize.pop();
return "string";
return 'string';
}
state.tokenize.push(t);
@ -150,13 +151,13 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
var depth = 1;
function t(stream, state) {
if (stream.peek() == "}") {
if (stream.peek() == '}') {
depth--;
if (depth == 0) {
state.tokenize.pop();
return state.tokenize[state.tokenize.length - 1](stream, state);
}
} else if (stream.peek() == "{") {
} else if (stream.peek() == '{') {
depth++;
}
@ -173,11 +174,11 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
var isWord = stream.eatWhile(/[\w]/);
if (isWord) {
state.tokenize.pop();
return "word";
return 'word';
}
}
state.tokenize.pop();
return "string";
return 'string';
}
t.isBase = true;
@ -187,21 +188,28 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
function tokenComment(stream, state) {
var maybeEnd = false,
ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
while ((ch = stream.next())) {
if (ch == '/' && maybeEnd) {
state.tokenize.pop();
break;
}
maybeEnd = (ch == "*");
maybeEnd = ch == '*';
}
return "comment";
return 'comment';
}
function expectExpression(last) {
return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) ||
last == "newstatement" || last == "keyword" || last == "proplabel";
return (
!last ||
last == 'operator' ||
last == '->' ||
/[\.\[\{\(,;:]/.test(last) ||
last == 'newstatement' ||
last == 'keyword' ||
last == 'proplabel'
);
}
function Context(indented, column, type, align, prev) {
@ -213,14 +221,13 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
}
function pushContext(state, col, type) {
return state.context = new Context(state.indented, col, type, null, state.context);
return (state.context = new Context(state.indented, col, type, null, state.context));
}
function popContext(state) {
var t = state.context.type;
if (t == ")" || t == "]" || t == "}")
state.indented = state.context.indented;
return state.context = state.context.prev;
if (t == ')' || t == ']' || t == '}') state.indented = state.context.indented;
return (state.context = state.context.prev);
}
// Interface
@ -229,7 +236,7 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
startState: function(basecolumn) {
return {
tokenize: [tokenBase],
context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
context: new Context((basecolumn || 0) - config.indentUnit, 0, 'top', false),
indented: 0,
startOfLine: true,
lastToken: null
@ -243,7 +250,7 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
state.indented = stream.indentation();
state.startOfLine = true;
// Automatic semicolon insertion
if (ctx.type == "statement" && !expectExpression(state.lastToken)) {
if (ctx.type == 'statement' && !expectExpression(state.lastToken)) {
popContext(state);
ctx = state.context;
}
@ -251,23 +258,27 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
if (stream.eatSpace()) return null;
curPunc = null;
var style = state.tokenize[state.tokenize.length - 1](stream, state);
if (style == "comment") return style;
if (style == 'comment') return style;
if (ctx.align == null) ctx.align = true;
if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
if ((curPunc == ';' || curPunc == ':') && ctx.type == 'statement') popContext(state);
else if (curPunc == '->' && ctx.type == 'statement' && ctx.prev.type == '}') {
// Handle indentation for {x -> \n ... }
else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") {
popContext(state);
state.context.align = false;
} else if (curPunc == "{") pushContext(state, stream.column(), "}");
else if (curPunc == "[") pushContext(state, stream.column(), "]");
else if (curPunc == "(") pushContext(state, stream.column(), ")");
else if (curPunc == "}") {
while (ctx.type == "statement") ctx = popContext(state);
if (ctx.type == "}") ctx = popContext(state);
while (ctx.type == "statement") ctx = popContext(state);
} else if (curPunc == '{') pushContext(state, stream.column(), '}');
else if (curPunc == '[') pushContext(state, stream.column(), ']');
else if (curPunc == '(') pushContext(state, stream.column(), ')');
else if (curPunc == '}') {
while (ctx.type == 'statement') ctx = popContext(state);
if (ctx.type == '}') ctx = popContext(state);
while (ctx.type == 'statement') ctx = popContext(state);
} else if (curPunc == ctx.type) popContext(state);
else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
pushContext(state, stream.column(), "statement");
else if (
ctx.type == '}' ||
ctx.type == 'top' ||
(ctx.type == 'statement' && curPunc == 'newstatement')
)
pushContext(state, stream.column(), 'statement');
state.startOfLine = false;
state.lastToken = curPunc || style;
return style;
@ -277,19 +288,19 @@ CodeMirror.defineMode("kotlin", function(config, parserConfig) {
if (!state.tokenize[state.tokenize.length - 1].isBase) return 0;
var firstChar = textAfter && textAfter.charAt(0),
ctx = state.context;
if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev;
if (ctx.type == 'statement' && !expectExpression(state.lastToken)) ctx = ctx.prev;
var closing = firstChar == ctx.type;
if (ctx.type == "statement") {
return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit);
if (ctx.type == 'statement') {
return ctx.indented + (firstChar == '{' ? 0 : config.indentUnit);
} else if (ctx.align) return ctx.column + (closing ? 0 : 1);
else return ctx.indented + (closing ? 0 : config.indentUnit);
},
closeBrackets: {
triples: "'\""
triples: '\'"'
},
electricChars: "{}"
electricChars: '{}'
};
});
CodeMirror.defineMIME("text/x-kotlin", "kotlin");
CodeMirror.defineMIME('text/x-kotlin', 'kotlin');

@ -1,77 +1,300 @@
const CodeMirror = require('codemirror')
const CodeMirror = require('codemirror');
CodeMirror.defineMode("nimrod", function(conf, parserConf) {
CodeMirror.defineMode('nimrod', function(conf, parserConf) {
var ERRORCLASS = 'error';
function wordRegexp(words) {
return new RegExp("^((" + words.join(")|(") + "))\\b");
}
var operators = new RegExp("\\=\\+\\-\\*\\/\\<\\>\\@\\$\\~\\&\\%\\|\\!\\?\\^\\:\\\\");
var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
var commonkeywords = ['addr', 'asm', 'atomic',
'bind', 'block', 'break', 'case', 'cast',
'const', 'continue', 'converter',
'discard', 'distinct', 'do',
'elif', 'else', 'end', 'enum', 'except', 'export',
'finally', 'for', 'from',
return new RegExp('^((' + words.join(')|(') + '))\\b');
}
var operators = new RegExp('\\=\\+\\-\\*\\/\\<\\>\\@\\$\\~\\&\\%\\|\\!\\?\\^\\:\\\\');
var identifiers = new RegExp('^[_A-Za-z][_A-Za-z0-9]*');
var commonkeywords = [
'addr',
'asm',
'atomic',
'bind',
'block',
'break',
'case',
'cast',
'const',
'continue',
'converter',
'discard',
'distinct',
'do',
'elif',
'else',
'end',
'enum',
'except',
'export',
'finally',
'for',
'from',
'generic',
'if', 'import', 'include', 'interface', 'iterator',
'lambda', 'let',
'macro', 'method', 'mixin', 'nil',
'object', 'out',
'proc', 'ptr',
'raise', 'ref', 'return',
'shared', 'static',
'template', 'try', 'tuple', 'type',
'if',
'import',
'include',
'interface',
'iterator',
'lambda',
'let',
'macro',
'method',
'mixin',
'nil',
'object',
'out',
'proc',
'ptr',
'raise',
'ref',
'return',
'shared',
'static',
'template',
'try',
'tuple',
'type',
'using',
'var',
'when', 'while', 'with', 'without',
'when',
'while',
'with',
'without',
'yield',
// keyword operators
'shl', 'shr', 'and', 'or', 'xor', 'not',
'div', 'mod', 'is', 'isnot', 'in', 'as', 'of'];
var commonBuiltins = ["int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16",
"uint32", "uint64", "float", "float32", "float64", "bool", "char",
"string", "cstring", "pointer", "range", "array", "openarray",
"seq", "set", "Byte", "Natural", "Positive", "TObject", "PObject",
"Conversion", "TResult", "TAddress", "BiggestInt", "BiggestFloat",
"cchar", "cschar", "cshort", "cint", "csize", "cuchar", "cushort",
"clong", "clonglong", "cfloat", "cdouble", "clongdouble", "cuint",
"culong", "culonglong", "cchar", "cstringArray", "TEndian", "PFloat32",
"PFloat64", "PInt64", "PInt32", "TGC_Strategy", "TFile", "TFileMode",
"TFileHandle", "isMainModule", "CompileDate", "CompileTime", "NimrodVersion",
"NimrodMajor", "NimrodMinor", "NimrodPatch", "cpuEndian", "hostOS", "hostCPU",
"inf", "neginf", "nan", "QuitSuccess", "QuitFailure", "dbgLineHook", "stdin",
"stdout", "stderr", "defined", "new", "high", "low", "sizeof", "succ", "pred",
"inc", "dec", "newSeq", "len", "incl", "excl", "card", "ord", "chr", "ze",
"ze64", "toU8", "toU16", "toU32", "abs", "min", "max", "add", "repr", "contains",
"toFloat", "toBiggestFloat", "toInt", "toBiggestInt", "addQuitProc", "copy",
"setLen", "newString", "zeroMem", "copyMem", "moveMem", "equalMem", "alloc",
"alloc0", "realloc", "dealloc", "setLen", "assert", "swap", "getRefcount",
"getCurrentException", "Msg", "getOccupiedMem", "getFreeMem", "getTotalMem",
"isNil", "seqToPtr", "find", "pop", "GC_disable", "GC_enable", "GC_fullCollect",
"GC_setStrategy", "GC_enableMarkAnd", "Sweep", "GC_disableMarkAnd", "Sweep",
"GC_getStatistics", "GC_ref", "GC_ref", "GC_ref", "GC_unref", "GC_unref",
"GC_unref", "quit", "OpenFile", "OpenFile", "CloseFile", "EndOfFile",
"readChar", "FlushFile", "readFile", "write", "readLine", "writeln",
"writeln", "getFileSize", "ReadBytes", "ReadChars", "readBuffer",
"writeBytes", "writeChars", "writeBuffer", "setFilePos", "getFilePos",
"fileHandle", "countdown", "countup", "items", "lines",
"true", "false",
'shl',
'shr',
'and',
'or',
'xor',
'not',
'div',
'mod',
'is',
'isnot',
'in',
'as',
'of'
];
var commonBuiltins = [
'int',
'int8',
'int16',
'int32',
'int64',
'uint',
'uint8',
'uint16',
'uint32',
'uint64',
'float',
'float32',
'float64',
'bool',
'char',
'string',
'cstring',
'pointer',
'range',
'array',
'openarray',
'seq',
'set',
'Byte',
'Natural',
'Positive',
'TObject',
'PObject',
'Conversion',
'TResult',
'TAddress',
'BiggestInt',
'BiggestFloat',
'cchar',
'cschar',
'cshort',
'cint',
'csize',
'cuchar',
'cushort',
'clong',
'clonglong',
'cfloat',
'cdouble',
'clongdouble',
'cuint',
'culong',
'culonglong',
'cchar',
'cstringArray',
'TEndian',
'PFloat32',
'PFloat64',
'PInt64',
'PInt32',
'TGC_Strategy',
'TFile',
'TFileMode',
'TFileHandle',
'isMainModule',
'CompileDate',
'CompileTime',
'NimrodVersion',
'NimrodMajor',
'NimrodMinor',
'NimrodPatch',
'cpuEndian',
'hostOS',
'hostCPU',
'inf',
'neginf',
'nan',
'QuitSuccess',
'QuitFailure',
'dbgLineHook',
'stdin',
'stdout',
'stderr',
'defined',
'new',
'high',
'low',
'sizeof',
'succ',
'pred',
'inc',
'dec',
'newSeq',
'len',
'incl',
'excl',
'card',
'ord',
'chr',
'ze',
'ze64',
'toU8',
'toU16',
'toU32',
'abs',
'min',
'max',
'add',
'repr',
'contains',
'toFloat',
'toBiggestFloat',
'toInt',
'toBiggestInt',
'addQuitProc',
'copy',
'setLen',
'newString',
'zeroMem',
'copyMem',
'moveMem',
'equalMem',
'alloc',
'alloc0',
'realloc',
'dealloc',
'setLen',
'assert',
'swap',
'getRefcount',
'getCurrentException',
'Msg',
'getOccupiedMem',
'getFreeMem',
'getTotalMem',
'isNil',
'seqToPtr',
'find',
'pop',
'GC_disable',
'GC_enable',
'GC_fullCollect',
'GC_setStrategy',
'GC_enableMarkAnd',
'Sweep',
'GC_disableMarkAnd',
'Sweep',
'GC_getStatistics',
'GC_ref',
'GC_ref',
'GC_ref',
'GC_unref',
'GC_unref',
'GC_unref',
'quit',
'OpenFile',
'OpenFile',
'CloseFile',
'EndOfFile',
'readChar',
'FlushFile',
'readFile',
'write',
'readLine',
'writeln',
'writeln',
'getFileSize',
'ReadBytes',
'ReadChars',
'readBuffer',
'writeBytes',
'writeChars',
'writeBuffer',
'setFilePos',
'getFilePos',
'fileHandle',
'countdown',
'countup',
'items',
'lines',
'true',
'false',
// exceptions
"E_Base", "EAsynch", "ESynch", "ESystem", "EIO", "EOS", "ERessourceExhausted",
"EArithmetic", "EDivByZero", "EOverflow", "EAccessViolation", "EAssertionFailed",
"EControlC", "EInvalidValue", "EOutOfMemory", "EInvalidIndex", "EInvalidField",
"EOutOfRange", "EStackOverflow", "ENoExceptionToReraise", "EInvalidObjectAssignment",
"EInvalidObject", "EInvalidLibrary", "EInvalidKey", "EInvalidObjectConversion",
"EFloatingPoint", "EFloatInvalidOp", "EFloatDivByZero", "EFloatOverflow",
"EFloatInexact", "EDeadThrea"];
'E_Base',
'EAsynch',
'ESynch',
'ESystem',
'EIO',
'EOS',
'ERessourceExhausted',
'EArithmetic',
'EDivByZero',
'EOverflow',
'EAccessViolation',
'EAssertionFailed',
'EControlC',
'EInvalidValue',
'EOutOfMemory',
'EInvalidIndex',
'EInvalidField',
'EOutOfRange',
'EStackOverflow',
'ENoExceptionToReraise',
'EInvalidObjectAssignment',
'EInvalidObject',
'EInvalidLibrary',
'EInvalidKey',
'EInvalidObjectConversion',
'EFloatingPoint',
'EFloatInvalidOp',
'EFloatDivByZero',
'EFloatOverflow',
'EFloatInexact',
'EDeadThrea'
];
if (parserConf.extra_keywords != undefined)
commonkeywords = commonkeywords.concat(parserConf.extra_keywords);
@ -84,7 +307,7 @@ CodeMirror.defineMode("nimrod", function(conf, parserConf) {
var indentInfo = null;
var stringPrefixes = new RegExp("^(('{3}|\"{3}|['\"]))", "i");
var stringPrefixes = new RegExp('^((\'{3}|"{3}|[\'"]))', 'i');
// tokenizers
function tokenBase(stream, state) {
@ -106,8 +329,7 @@ CodeMirror.defineMode("nimrod", function(conf, parserConf) {
}
}
if (stream.eatSpace())
return null;
if (stream.eatSpace()) return null;
var ch = stream.peek();
@ -121,9 +343,15 @@ CodeMirror.defineMode("nimrod", function(conf, parserConf) {
if (stream.match(/^[0-9\.]/, false)) {
var floatLiteral = false;
// Floats
if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) { floatLiteral = true; }
if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; }
if (stream.match(/^\.\d+/)) { floatLiteral = true; }
if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) {
floatLiteral = true;
}
if (stream.match(/^\d+\.\d*/)) {
floatLiteral = true;
}
if (stream.match(/^\.\d+/)) {
floatLiteral = true;
}
if (floatLiteral) {
// Float literals may be "imaginary"
stream.eat(/J/i);
@ -132,11 +360,17 @@ CodeMirror.defineMode("nimrod", function(conf, parserConf) {
// Integers
var intLiteral = false;
// Hex
if (stream.match(/^0x[0-9a-f]+/i)) { intLiteral = true; }
if (stream.match(/^0x[0-9a-f]+/i)) {
intLiteral = true;
}
// Binary
if (stream.match(/^0b[01]+/i)) { intLiteral = true; }
if (stream.match(/^0b[01]+/i)) {
intLiteral = true;
}
// Octal
if (stream.match(/^0o[0-7]+/i)) { intLiteral = true; }
if (stream.match(/^0o[0-7]+/i)) {
intLiteral = true;
}
// Decimal
if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) {
// Decimal literals may be "imaginary"
@ -145,7 +379,9 @@ CodeMirror.defineMode("nimrod", function(conf, parserConf) {
intLiteral = true;
}
// Zero by itself with no other piece of number.
if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
if (stream.match(/^0(?![\dx])/i)) {
intLiteral = true;
}
if (intLiteral) {
// Integer literals may be "long"
stream.eat(/L/i);
@ -159,18 +395,17 @@ CodeMirror.defineMode("nimrod", function(conf, parserConf) {
return state.tokenize(stream, state);
}
if (stream.match(operators))
return 'operator';
if (stream.match(operators)) return 'operator';
if (stream.match(keywords))
return 'keyword';
if (stream.match(keywords)) return 'keyword';
if (stream.match(builtins))
return 'builtin';
if (stream.match(builtins)) return 'builtin';
if (stream.match(identifiers)) {
if (state.lastToken != null &&
state.lastToken.match(/proc|iterator|macro|template|class|converter/)) {
if (
state.lastToken != null &&
state.lastToken.match(/proc|iterator|macro|template|class|converter/)
) {
return 'def';
}
@ -288,25 +523,21 @@ CodeMirror.defineMode("nimrod", function(conf, parserConf) {
return style;
}
if ((style === 'variable' || style === 'builtin')
&& state.lastStyle === 'meta') {
if ((style === 'variable' || style === 'builtin') && state.lastStyle === 'meta') {
style = 'meta';
}
// Handle scope changes.
if (current.match(/return|break|continue|raise/) ||
(current === 'discard' && stream.eol()))
if (current.match(/return|break|continue|raise/) || (current === 'discard' && stream.eol()))
state.dedent += 1;
if (current === 'lambda' || current === 'proc')
state.lambda = true;
if (current === 'lambda' || current === 'proc') state.lambda = true;
var delimiter_index = '[({'.indexOf(current);
if (delimiter_index !== -1) {
indent(stream, state, '])}'.slice(delimiter_index, delimiter_index + 1));
}
else if(stream.eol() && current.match(/\=|\:|import|include|type|const|var|let/)) {
} else if (stream.eol() && current.match(/\=|\:|import|include|type|const|var|let/)) {
indent(stream, state);
}
@ -349,28 +580,24 @@ CodeMirror.defineMode("nimrod", function(conf, parserConf) {
state.lastStyle = style;
var current = stream.current();
if (current && style)
state.lastToken = current;
if (current && style) state.lastToken = current;
if (stream.eol() && state.lambda)
state.lambda = false;
if (stream.eol() && state.lambda) state.lambda = false;
return style;
},
indent: function(state) {
if (state.tokenize != tokenBase)
return state.tokenize.isString ? CodeMirror.Pass : 0;
if (state.tokenize != tokenBase) return state.tokenize.isString ? CodeMirror.Pass : 0;
return state.scopes[0].offset;
},
lineComment: "#",
fold: "indent"
lineComment: '#',
fold: 'indent'
};
return external;
});
CodeMirror.defineMIME("text/x-nimrod", "nimrod");
CodeMirror.defineMIME('text/x-nimrod', 'nimrod');

@ -7,7 +7,9 @@
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js",
"deploy": "now --public"
"deploy": "now --public",
"prettier": "prettier --config .prettierrc --write 'components/**/*.js' 'handlers/**/*.js' 'lib/**/*.js' 'pages/**/*.js' 'server.js'",
"lint": "prettier --config .prettierrc -l 'components/**/*.js' 'handlers/**/*.js' 'lib/**/*.js' 'pages/**/*.js' 'server.js'"
},
"dependencies": {
"axios": "^0.16.2",
@ -37,6 +39,7 @@
"twitter": "^1.7.1"
},
"devDependencies": {
"prettier": "^1.7.2",
"uglifyjs-webpack-plugin": "1.0.0-beta.1",
"webpack": "^3.6.0"
},

@ -1,15 +1,20 @@
import Page from '../components/Page'
import Meta from '../components/Meta'
import Header from '../components/Header'
import Footer from '../components/Footer'
import { COLORS } from '../lib/constants'
import Page from '../components/Page';
import Meta from '../components/Meta';
import Header from '../components/Header';
import Footer from '../components/Footer';
import { COLORS } from '../lib/constants';
export default () => (
<Page>
<div className="about">
<div className="mb4">
<h2>What does this do?</h2>
<p>You know all of those code screenshots you see on Twitter? Although the code's usually impressive, we saw room for improvement in the aesthetic department. Carbon is the easiest way to create beautiful images of your source code. So what are you waiting for? Go impress all of your followers with your newfound design prowess. <span>🎨</span></p>
<p>
You know all of those code screenshots you see on Twitter? Although the code's usually
impressive, we saw room for improvement in the aesthetic department. Carbon is the easiest
way to create beautiful images of your source code. So what are you waiting for? Go
impress all of your followers with your newfound design prowess. <span>🎨</span>
</p>
</div>
<div className="mb4">
<h2>How do I use it?</h2>
@ -17,23 +22,38 @@ export default () => (
<p className="mb1 mt2">There are a few different ways to import code into Carbon:</p>
<ul className="mt0 mb3">
<li>Drop a file into the editor</li>
<li>Append a GitHub gist id to the url (<a className="link" href="/0db00e81d5416c339181e59481c74b59">example</a>)</li>
<li>
Append a GitHub gist id to the url (<a
className="link"
href="/0db00e81d5416c339181e59481c74b59"
>
example
</a>)
</li>
<li>Paste your code directly</li>
</ul>
<h4 className="mb0">Customization</h4>
<p className="mt2 mb3">Once you've got all of your code into Carbon, you can customize your image by changing the syntax theme, background color, window theme, or padding.</p>
<p className="mt2 mb3">
Once you've got all of your code into Carbon, you can customize your image by changing the
syntax theme, background color, window theme, or padding.
</p>
<h4 className="mb0">Export/Sharing</h4>
<p className="mt2">After you've customized your image you can Tweet a link to the image, or save it directly.</p>
<p className="mt2">
After you've customized your image you can Tweet a link to the image, or save it directly.
</p>
</div>
<div>
<h2>I want to make this better.</h2>
<p>
<a className="link" href="https://github.com/dawnlabs/carbon">Please do.</a>
<a className="link" href="https://github.com/dawnlabs/carbon">
Please do.
</a>
</p>
</div>
</div>
<style jsx>{`
p, li {
p,
li {
color: ${COLORS.GRAY};
}
@ -51,4 +71,4 @@ export default () => (
}
`}</style>
</Page>
)
);

@ -1,20 +1,20 @@
// Theirs
import React from 'react'
import HTML5Backend from 'react-dnd-html5-backend'
import { DragDropContext } from 'react-dnd'
import domtoimage from 'dom-to-image'
import ReadFileDropContainer from 'dropperx'
import React from 'react';
import HTML5Backend from 'react-dnd-html5-backend';
import { DragDropContext } from 'react-dnd';
import domtoimage from 'dom-to-image';
import ReadFileDropContainer from 'dropperx';
// Ours
import Page from '../components/Page'
import Button from '../components/Button'
import Dropdown from '../components/Dropdown'
import ColorPicker from '../components/ColorPicker'
import Settings from '../components/Settings'
import Toolbar from '../components/Toolbar'
import Overlay from '../components/Overlay'
import Carbon from '../components/Carbon'
import api from '../lib/api'
import Page from '../components/Page';
import Button from '../components/Button';
import Dropdown from '../components/Dropdown';
import ColorPicker from '../components/ColorPicker';
import Settings from '../components/Settings';
import Toolbar from '../components/Toolbar';
import Overlay from '../components/Overlay';
import Carbon from '../components/Carbon';
import api from '../lib/api';
import {
THEMES_ARRAY,
THEMES,
@ -22,7 +22,7 @@ import {
DEFAULT_LANGUAGE,
COLORS,
DEFAULT_CODE
} from '../lib/constants'
} from '../lib/constants';
class Editor extends React.Component {
/* pathname, asPath, err, req, res */
@ -30,17 +30,17 @@ class Editor extends React.Component {
try {
// TODO fix this hack
if (asPath.length > 30) {
const content = await api.getGist(asPath)
return { content }
const content = await api.getGist(asPath);
return { content };
}
} catch (e) {
console.log(e)
console.log(e);
}
return {}
return {};
}
constructor(props) {
super(props)
super(props);
this.state = {
background: '#ABB8C3',
theme: THEMES.seti.id,
@ -51,15 +51,15 @@ class Editor extends React.Component {
paddingHorizontal: '32px',
uploading: false,
code: props.content || DEFAULT_CODE
}
};
this.save = this.save.bind(this)
this.upload = this.upload.bind(this)
this.updateCode = this.updateCode.bind(this)
this.save = this.save.bind(this);
this.upload = this.upload.bind(this);
this.updateCode = this.updateCode.bind(this);
}
getCarbonImage() {
const node = document.getElementById('section')
const node = document.getElementById('section');
const config = {
style: {
@ -68,36 +68,35 @@ class Editor extends React.Component {
},
width: node.offsetWidth * 2,
height: node.offsetHeight * 2
}
};
return domtoimage.toPng(node, config)
return domtoimage.toPng(node, config);
}
updateCode(code) {
this.setState({ code })
this.setState({ code });
}
save() {
this.getCarbonImage()
.then((dataUrl) => {
const link = document.createElement('a')
link.download = 'carbon.png'
link.href = dataUrl
document.body.appendChild(link)
link.click()
link.remove()
})
this.getCarbonImage().then(dataUrl => {
const link = document.createElement('a');
link.download = 'carbon.png';
link.href = dataUrl;
document.body.appendChild(link);
link.click();
link.remove();
});
}
upload() {
this.setState({ uploading: true })
this.setState({ uploading: true });
this.getCarbonImage()
.then(api.tweet)
.then(() => this.setState({ uploading: false }))
.catch((err) => {
console.error(err)
this.setState({ uploading: false })
})
.catch(err => {
console.error(err);
this.setState({ uploading: false });
});
}
render() {
@ -105,13 +104,23 @@ class Editor extends React.Component {
<Page enableHeroText>
<div id="editor">
<Toolbar>
<Dropdown selected={THEMES[this.state.theme]} list={THEMES_ARRAY} onChange={theme => this.setState({ theme: theme.id })}/>
<Dropdown list={LANGUAGES} onChange={language => this.setState({ language: language.module })}/>
<Dropdown
selected={THEMES[this.state.theme]}
list={THEMES_ARRAY}
onChange={theme => this.setState({ theme: theme.id })}
/>
<Dropdown
list={LANGUAGES}
onChange={language => this.setState({ language: language.module })}
/>
<ColorPicker
onChange={color => this.setState({ background: color })}
bg={this.state.background}
/>
<Settings onChange={(key, value) => this.setState({ [key]: value })} enabled={this.state} />
<Settings
onChange={(key, value) => this.setState({ [key]: value })}
enabled={this.state}
/>
<div className="buttons">
<Button
className="tweetButton"
@ -125,18 +134,20 @@ class Editor extends React.Component {
</Toolbar>
<ReadFileDropContainer onDrop={([file]) => this.setState({ code: file.content })}>
{
({ isOver, canDrop }) => (
<Overlay isOver={isOver || canDrop} title={`Drop your file here to import ${isOver ? '✋' : '✊'}`}>
{({ isOver, canDrop }) => (
<Overlay
isOver={isOver || canDrop}
title={`Drop your file here to import ${isOver ? '✋' : '✊'}`}
>
<Carbon config={this.state} updateCode={this.updateCode}>
{this.state.code}
</Carbon>
</Overlay>
)
}
)}
</ReadFileDropContainer>
</div>
<style jsx>{`
<style jsx>
{`
#editor {
background: ${COLORS.BLACK};
border: 3px solid ${COLORS.SECONDARY};
@ -151,8 +162,8 @@ class Editor extends React.Component {
`}
</style>
</Page>
)
);
}
}
export default DragDropContext(HTML5Backend)(Editor)
export default DragDropContext(HTML5Backend)(Editor);

@ -1,2 +1,2 @@
import Editor from './editor'
export default Editor
import Editor from './editor';
export default Editor;

@ -1,40 +1,38 @@
const express = require('express')
const morgan = require('morgan')
const bodyParser = require('body-parser')
const next = require('next')
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const next = require('next');
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production' && !process.env.NOW
const app = next({ dev })
const handle = app.getRequestHandler()
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production' && !process.env.NOW;
const app = next({ dev });
const handle = app.getRequestHandler();
function wrap(handler) {
return (req, res) => handler(req, res).catch((err) => {
console.log('ERR:', err)
})
return (req, res) =>
handler(req, res).catch(err => {
console.log('ERR:', err);
});
}
app.prepare()
.then(() => {
const server = express()
app.prepare().then(() => {
const server = express();
server.use(morgan('tiny'))
server.use(morgan('tiny'));
server.get('/about', (req, res) =>
app.render(req, res, '/about'))
server.get('/about', (req, res) => app.render(req, res, '/about'));
// if root, render webpage from next
server.get('/*', (req, res) =>
app.render(req, res, '/', req.query))
server.get('/*', (req, res) => app.render(req, res, '/', req.query));
// otherwise, try and get gist
server.get('*', handle)
server.get('*', handle);
// api endpoints
server.post('/twitter', bodyParser.json({ limit: '5mb' }), require('./handlers/twitter'))
server.post('/twitter', bodyParser.json({ limit: '5mb' }), require('./handlers/twitter'));
server.listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
server.listen(port, err => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}`);
});
});

File diff suppressed because it is too large Load Diff

@ -3033,6 +3033,10 @@ preserve@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
prettier@^1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.7.2.tgz#81371e64018aafc69cf1031956c70e029339f54e"
private@^0.1.6, private@^0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1"

Loading…
Cancel
Save