Lint and fix issues, don't add linting yet though (#293)

* Lint and fix issue, don't add linting yet though

* Clean up

* Remove /about href
main
Michael Fix 7 years ago committed by GitHub
parent 083a0e8441
commit 5a4cdd7d7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -10,7 +10,7 @@ import { parseRGBA, capitalizeFirstLetter } from '../lib/util'
class BackgroundSelect extends React.PureComponent { class BackgroundSelect extends React.PureComponent {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { isVisible: false, selectedTab: 'color', mounted: false } this.state = { isVisible: false, mounted: false }
this.toggle = this.toggle.bind(this) this.toggle = this.toggle.bind(this)
this.selectTab = this.selectTab.bind(this) this.selectTab = this.selectTab.bind(this)
this.handlePickColor = this.handlePickColor.bind(this) this.handlePickColor = this.handlePickColor.bind(this)
@ -69,9 +69,9 @@ class BackgroundSelect extends React.PureComponent {
<div className="bg-select-pickers" hidden={!this.state.isVisible}> <div className="bg-select-pickers" hidden={!this.state.isVisible}>
<WindowPointer fromLeft="15px" /> <WindowPointer fromLeft="15px" />
<div className="picker-tabs"> <div className="picker-tabs">
{['color', 'image'].map((tab, i) => ( {['color', 'image'].map(tab => (
<div <div
key={i} key={tab}
className={`picker-tab ${this.props.mode === tab ? 'active' : ''}`} className={`picker-tab ${this.props.mode === tab ? 'active' : ''}`}
onClick={this.selectTab.bind(null, tab)} onClick={this.selectTab.bind(null, tab)}
> >
@ -94,118 +94,120 @@ class BackgroundSelect extends React.PureComponent {
</div> </div>
</div> </div>
</div> </div>
<style jsx>{` <style jsx>
.bg-select-container { {`
height: 100%; .bg-select-container {
} height: 100%;
}
.bg-select-display {
display: flex; .bg-select-display {
overflow: hidden; display: flex;
height: 100%; overflow: hidden;
width: 72px; height: 100%;
border: 1px solid ${COLORS.SECONDARY}; width: 72px;
border-radius: 3px; border: 1px solid ${COLORS.SECONDARY};
} border-radius: 3px;
}
.bg-select-label {
display: flex; .bg-select-label {
align-items: center; display: flex;
justify-content: center; align-items: center;
user-select: none; justify-content: center;
cursor: default; user-select: none;
height: 100%; cursor: default;
padding: 0 8px; height: 100%;
border-right: 1px solid ${COLORS.SECONDARY}; padding: 0 8px;
} border-right: 1px solid ${COLORS.SECONDARY};
}
.bg-color-container {
position: relative; .bg-color-container {
width: 100%; position: relative;
background: #fff; width: 100%;
cursor: pointer; background: #fff;
} cursor: pointer;
}
.bg-color {
position: absolute; .bg-color {
top: 0px; position: absolute;
right: 0px; top: 0px;
bottom: 0px; right: 0px;
left: 0px; bottom: 0px;
${this.props.mode === 'image' left: 0px;
? `background: url(${this.props.image}); ${this.props.mode === 'image'
? `background: url(${this.props.image});
background-size: cover; background-size: cover;
background-repeat: no-repeat;` background-repeat: no-repeat;`
: `background: ${background};`}; : `background: ${background};`};
} }
.bg-color-alpha { .bg-color-alpha {
position: absolute; position: absolute;
top: 0px; top: 0px;
right: 0px; right: 0px;
bottom: 0px; bottom: 0px;
left: 0px; left: 0px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==); background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==);
} }
.picker-tabs { .picker-tabs {
display: flex; display: flex;
border-bottom: 1px solid ${COLORS.SECONDARY}; border-bottom: 1px solid ${COLORS.SECONDARY};
} }
.picker-tab { .picker-tab {
user-select: none; user-select: none;
cursor: pointer; cursor: pointer;
background: rgba(255, 255, 255, 0.165); background: rgba(255, 255, 255, 0.165);
width: 50%; width: 50%;
text-align: center; text-align: center;
padding: 8px 0; padding: 8px 0;
border-right: 1px solid ${COLORS.SECONDARY}; border-right: 1px solid ${COLORS.SECONDARY};
} }
.picker-tab:last-child { .picker-tab:last-child {
border-right: none; border-right: none;
} }
.picker-tab.active { .picker-tab.active {
background: none; background: none;
} }
.bg-select-pickers { .bg-select-pickers {
position: absolute; position: absolute;
width: 222px; width: 222px;
margin-left: 36px; margin-left: 36px;
margin-top: 4px; margin-top: 4px;
border: 1px solid ${COLORS.SECONDARY}; border: 1px solid ${COLORS.SECONDARY};
border-radius: 3px; border-radius: 3px;
background: #1a1a1a; background: #1a1a1a;
} }
/* react-color overrides */ /* react-color overrides */
.bg-select-pickers :global(.sketch-picker) { .bg-select-pickers :global(.sketch-picker) {
background: #1a1a1a !important; background: #1a1a1a !important;
padding: 8px 8px 0 !important; padding: 8px 8px 0 !important;
margin: 0 auto 1px !important; margin: 0 auto 1px !important;
} }
.bg-select-pickers :global(.sketch-picker > div:nth-child(3) > div > div > span) { .bg-select-pickers :global(.sketch-picker > div:nth-child(3) > div > div > span) {
color: ${COLORS.SECONDARY} !important; color: ${COLORS.SECONDARY} !important;
} }
.bg-select-pickers :global(.sketch-picker > div:nth-child(3) > div > div > input) { .bg-select-pickers :global(.sketch-picker > div:nth-child(3) > div > div > input) {
width: 100% !important; width: 100% !important;
box-shadow: none; box-shadow: none;
outline: none; outline: none;
border-radius: 2px; border-radius: 2px;
background: rgba(255, 255, 255, 0.165); background: rgba(255, 255, 255, 0.165);
color: #fff !important; color: #fff !important;
} }
/* prettier-ignore */ /* prettier-ignore */
.bg-select-pickers :global(.sketch-picker > div:nth-child(2) > div:nth-child(1) > div:nth-child(2), .sketch-picker > div:nth-child(2) > div:nth-child(2)) { .bg-select-pickers :global(.sketch-picker > div:nth-child(2) > div:nth-child(1) > div:nth-child(2), .sketch-picker > div:nth-child(2) > div:nth-child(2)) {
background: #fff; background: #fff;
} }
`}</style> `}
</style>
</div> </div>
) )
} }

@ -12,24 +12,26 @@ export default props => (
}} }}
> >
<span>{props.title}</span> <span>{props.title}</span>
<style jsx>{` <style jsx>
button { {`
cursor: pointer; button {
outline: none; cursor: pointer;
height: 100%; outline: none;
padding: 0 16px; height: 100%;
border-radius: 3px; padding: 0 16px;
user-select: none; border-radius: 3px;
} user-select: none;
}
button:hover { button:hover {
background: ${COLORS.HOVER} !important; background: ${COLORS.HOVER} !important;
} }
button > span { button > span {
font-size: 14px; font-size: 14px;
line-height: 1; line-height: 1;
} }
`}</style> `}
</style>
</button> </button>
) )

@ -1,23 +1,14 @@
import { EOL } from 'os'
import * as hljs from 'highlight.js' import * as hljs from 'highlight.js'
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import Spinner from 'react-spinner' import Spinner from 'react-spinner'
import ResizeObserver from 'resize-observer-polyfill' import ResizeObserver from 'resize-observer-polyfill'
import toHash from 'tohash'
import debounce from 'lodash.debounce' import debounce from 'lodash.debounce'
import ms from 'ms' import ms from 'ms'
import WindowControls from '../components/WindowControls' import WindowControls from '../components/WindowControls'
import Watermark from '../components/svg/Watermark' import Watermark from '../components/svg/Watermark'
import CodeMirror from '../lib/react-codemirror' import CodeMirror from '../lib/react-codemirror'
import { import { COLORS, LANGUAGE_MODE_HASH, LANGUAGE_NAME_HASH, DEFAULT_SETTINGS } from '../lib/constants'
COLORS,
DEFAULT_LANGUAGE,
LANGUAGES,
LANGUAGE_MODE_HASH,
LANGUAGE_NAME_HASH,
DEFAULT_SETTINGS
} from '../lib/constants'
class Carbon extends PureComponent { class Carbon extends PureComponent {
constructor(props) { constructor(props) {
@ -130,120 +121,122 @@ class Carbon extends PureComponent {
<div className="alpha eliminateOnRender" /> <div className="alpha eliminateOnRender" />
<div className="bg" /> <div className="bg" />
</div> </div>
<style jsx>{` <style jsx>
#container { {`
position: relative; #container {
min-width: ${config.widthAdjustment ? '90px' : '680px'}; position: relative;
max-width: 1024px; /* The Fallback */ min-width: ${config.widthAdjustment ? '90px' : '680px'};
max-width: 92vw; max-width: 1024px; /* The Fallback */
padding: ${config.paddingVertical} ${config.paddingHorizontal}; max-width: 92vw;
} padding: ${config.paddingVertical} ${config.paddingHorizontal};
}
#container :global(.watermark) {
fill-opacity: 0.3; #container :global(.watermark) {
position: absolute; fill-opacity: 0.3;
z-index: 2; position: absolute;
bottom: calc(${config.paddingVertical} + 16px); z-index: 2;
right: calc(${config.paddingHorizontal} + 16px); bottom: calc(${config.paddingVertical} + 16px);
} right: calc(${config.paddingHorizontal} + 16px);
}
#container #container-bg {
position: absolute; #container #container-bg {
top: 0px; position: absolute;
right: 0px; top: 0px;
bottom: 0px; right: 0px;
left: 0px; bottom: 0px;
} left: 0px;
}
#container .white {
background: #fff; #container .white {
position: absolute; background: #fff;
top: 0px; position: absolute;
right: 0px; top: 0px;
bottom: 0px; right: 0px;
left: 0px; bottom: 0px;
} left: 0px;
}
#container .bg {
${this.props.config.backgroundMode === 'image' #container .bg {
? `background: url(${backgroundImage}); ${this.props.config.backgroundMode === 'image'
? `background: url(${backgroundImage});
background-size: cover; background-size: cover;
background-repeat: no-repeat;` background-repeat: no-repeat;`
: `background: ${this.props.config.backgroundColor || config.backgroundColor}; : `background: ${this.props.config.backgroundColor || config.backgroundColor};
background-size: auto; background-size: auto;
background-repeat: repeat;`} position: absolute; background-repeat: repeat;`} position: absolute;
top: 0px; top: 0px;
right: 0px; right: 0px;
bottom: 0px; bottom: 0px;
left: 0px; left: 0px;
} }
#container .alpha { #container .alpha {
position: absolute; position: absolute;
top: 0px; top: 0px;
right: 0px; right: 0px;
bottom: 0px; bottom: 0px;
left: 0px; left: 0px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==); background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==);
} }
#container :global(.cm-s-dracula .CodeMirror-cursor) { #container :global(.cm-s-dracula .CodeMirror-cursor) {
border-left: solid 2px #159588; border-left: solid 2px #159588;
} }
#container :global(.cm-s-solarized) { #container :global(.cm-s-solarized) {
box-shadow: none; box-shadow: none;
} }
#container :global(.cm-s-solarized.cm-s-light) { #container :global(.cm-s-solarized.cm-s-light) {
text-shadow: #eee8d5 0 1px; text-shadow: #eee8d5 0 1px;
} }
#container :global(.CodeMirror-gutters) { #container :global(.CodeMirror-gutters) {
background-color: unset; background-color: unset;
border-right: none; border-right: none;
} }
#container :global(.CodeMirror__container) { #container :global(.CodeMirror__container) {
min-width: inherit; min-width: inherit;
position: relative; position: relative;
z-index: 1; z-index: 1;
border-radius: 5px; border-radius: 5px;
${config.dropShadow ${config.dropShadow
? `box-shadow: 0 ${config.dropShadowOffsetY} ${ ? `box-shadow: 0 ${config.dropShadowOffsetY} ${
config.dropShadowBlurRadius config.dropShadowBlurRadius
} rgba(0, 0, 0, 0.55)` } rgba(0, 0, 0, 0.55)`
: ''}; : ''};
} }
#container :global(.CodeMirror__container .CodeMirror) { #container :global(.CodeMirror__container .CodeMirror) {
height: auto; height: auto;
min-width: inherit; min-width: inherit;
padding: 18px 18px; padding: 18px 18px;
${config.lineNumbers ? 'padding-left: 12px;' : ''} border-radius: 5px; ${config.lineNumbers ? 'padding-left: 12px;' : ''} border-radius: 5px;
font-family: ${config.fontFamily}, monospace !important; font-family: ${config.fontFamily}, monospace !important;
font-size: ${config.fontSize}; font-size: ${config.fontSize};
font-variant-ligatures: contextual; font-variant-ligatures: contextual;
font-feature-settings: 'calt' 1; font-feature-settings: 'calt' 1;
user-select: none; user-select: none;
} }
#container :global(.CodeMirror-scroll) { #container :global(.CodeMirror-scroll) {
overflow: hidden !important; overflow: hidden !important;
} }
#container :global(.window-theme__sharp > .CodeMirror) { #container :global(.window-theme__sharp > .CodeMirror) {
border-radius: 0px; border-radius: 0px;
} }
#container :global(.window-theme__bw > .CodeMirror) { #container :global(.window-theme__bw > .CodeMirror) {
border: 2px solid ${COLORS.SECONDARY}; border: 2px solid ${COLORS.SECONDARY};
} }
#container :global(.window-controls + .CodeMirror__container > .CodeMirror) { #container :global(.window-controls + .CodeMirror__container > .CodeMirror) {
padding-top: 48px; padding-top: 48px;
} }
`}</style> `}
</style>
</div> </div>
) )
} }
@ -254,24 +247,26 @@ class Carbon extends PureComponent {
{content} {content}
<div id="twitter-png-fix" /> <div id="twitter-png-fix" />
</div> </div>
<style jsx>{` <style jsx>
#section, {`
#export-container { #section,
height: 100%; #export-container {
display: flex; height: 100%;
flex-direction: column; display: flex;
justify-content: center; flex-direction: column;
align-items: center; justify-content: center;
overflow: hidden; align-items: center;
} overflow: hidden;
}
/* forces twitter to save images as png — https://github.com/dawnlabs/carbon/issues/86 */
#twitter-png-fix { /* forces twitter to save images as png — https://github.com/dawnlabs/carbon/issues/86 */
height: 1px; #twitter-png-fix {
width: 100%; height: 1px;
background: rgba(0, 0, 0, 0.01); width: 100%;
} background: rgba(0, 0, 0, 0.01);
`}</style> }
`}
</style>
</div> </div>
) )
} }

@ -1,6 +1,5 @@
import React from 'react' import React from 'react'
import Toggle from './Toggle' import Toggle from './Toggle'
import Arrowdown from './svg/Arrowdown'
class Collapse extends React.Component { class Collapse extends React.Component {
constructor(props) { constructor(props) {

@ -10,13 +10,10 @@ class Dropdown extends PureComponent {
inputValue: this.props.selected.name, inputValue: this.props.selected.name,
itemsToShow: this.props.list itemsToShow: this.props.list
} }
userInputtedValue = ''
onUserAction = changes => { onUserAction = changes => {
this.setState(({ inputValue, itemsToShow }) => { this.setState(({ inputValue, itemsToShow }) => {
const clearUserInput = changes.hasOwnProperty('isOpen') if (Object.prototype.hasOwnProperty.call(changes, 'inputValue')) {
if (changes.hasOwnProperty('inputValue')) {
if (changes.type === Downshift.stateChangeTypes.keyDownEscape) { if (changes.type === Downshift.stateChangeTypes.keyDownEscape) {
inputValue = this.userInputtedValue inputValue = this.userInputtedValue
} else { } else {
@ -30,7 +27,7 @@ class Dropdown extends PureComponent {
: this.props.list : this.props.list
if ( if (
changes.hasOwnProperty('highlightedIndex') && Object.prototype.hasOwnProperty.call(changes, 'highlightedIndex') &&
(changes.type === Downshift.stateChangeTypes.keyDownArrowUp || (changes.type === Downshift.stateChangeTypes.keyDownArrowUp ||
changes.type === Downshift.stateChangeTypes.keyDownArrowDown) changes.type === Downshift.stateChangeTypes.keyDownArrowDown)
) { ) {
@ -38,7 +35,7 @@ class Dropdown extends PureComponent {
this.props.onChange(itemsToShow[changes.highlightedIndex]) this.props.onChange(itemsToShow[changes.highlightedIndex])
} }
if (changes.hasOwnProperty('isOpen')) { if (Object.prototype.hasOwnProperty.call(changes, 'isOpen')) {
this.userInputtedValue = '' this.userInputtedValue = ''
// clear on open // clear on open
@ -56,6 +53,8 @@ class Dropdown extends PureComponent {
}) })
} }
userInputtedValue = ''
render() { render() {
const { button, color, list, selected, onChange } = this.props const { button, color, list, selected, onChange } = this.props
@ -122,13 +121,15 @@ const DropdownContainer = ({ children, innerRef, minWidth, ...rest }) => {
return ( return (
<div {...rest} ref={innerRef} className="dropdown-container"> <div {...rest} ref={innerRef} className="dropdown-container">
{children} {children}
<style jsx>{` <style jsx>
.dropdown-container { {`
min-width: ${minWidth}px; .dropdown-container {
cursor: pointer; min-width: ${minWidth}px;
user-select: none; cursor: pointer;
} user-select: none;
`}</style> }
`}
</style>
</div> </div>
) )
} }
@ -150,40 +151,42 @@ const SelectedItem = ({ getButtonProps, getInputProps, children, isOpen, color,
className="dropdown-display-text" className="dropdown-display-text"
/> />
)} )}
<div role="button" className={`dropdown-arrow`}> <div role="button" className="dropdown-arrow">
<ArrowDown fill={itemColor} /> <ArrowDown fill={itemColor} />
</div> </div>
<style jsx>{` <style jsx>
.dropdown-display { {`
display: flex; .dropdown-display {
align-items: center; display: flex;
height: 100%; align-items: center;
border: 1px solid ${itemColor}; height: 100%;
border-radius: 3px; border: 1px solid ${itemColor};
padding: 8px 16px; border-radius: 3px;
outline: none; padding: 8px 16px;
} outline: none;
.dropdown-display:hover { }
background: ${COLORS.HOVER}; .dropdown-display:hover {
} background: ${COLORS.HOVER};
}
.dropdown-display.is-open { .dropdown-display.is-open {
border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0;
} }
.dropdown-display-text { .dropdown-display-text {
flex-grow: 1; flex-grow: 1;
color: ${itemColor}; color: ${itemColor};
background: transparent; background: transparent;
border: none; border: none;
outline: none; outline: none;
font-size: inherit; font-size: inherit;
font-family: inherit; font-family: inherit;
} }
.is-open > .dropdown-arrow { .is-open > .dropdown-arrow {
transform: rotate(180deg); transform: rotate(180deg);
} }
`}</style> `}
</style>
</span> </span>
) )
} }
@ -192,15 +195,17 @@ const ListItems = ({ children, color }) => {
return ( return (
<ul role="listbox" className="dropdown-list"> <ul role="listbox" className="dropdown-list">
{children} {children}
<style jsx>{` <style jsx>
.dropdown-list { {`
margin-top: -1px; .dropdown-list {
border: 1px solid ${color || COLORS.SECONDARY}; margin-top: -1px;
border-radius: 0 0 3px 3px; border: 1px solid ${color || COLORS.SECONDARY};
max-height: 350px; border-radius: 0 0 3px 3px;
overflow-y: scroll; max-height: 350px;
} overflow-y: scroll;
`}</style> }
`}
</style>
</ul> </ul>
) )
} }
@ -212,27 +217,29 @@ const ListItem = ({ children, color, isHighlighted, isSelected, ...rest }) => {
<li {...rest} role="option" className="dropdown-list-item"> <li {...rest} role="option" className="dropdown-list-item">
<span className="dropdown-list-item-text">{children}</span> <span className="dropdown-list-item-text">{children}</span>
{isSelected ? <CheckMark /> : null} {isSelected ? <CheckMark /> : null}
<style jsx>{` <style jsx>
.dropdown-list-item { {`
display: flex; .dropdown-list-item {
align-items: center; display: flex;
background: ${isHighlighted ? COLORS.HOVER : COLORS.BLACK}; align-items: center;
padding: 8px 16px; background: ${isHighlighted ? COLORS.HOVER : COLORS.BLACK};
border-bottom: 1px solid ${itemColor}; padding: 8px 16px;
} border-bottom: 1px solid ${itemColor};
}
.dropdown-list-item:last-child { .dropdown-list-item:last-child {
border-bottom: none; border-bottom: none;
} }
.dropdown-list-item:hover { .dropdown-list-item:hover {
background: ${COLORS.HOVER}; background: ${COLORS.HOVER};
} }
.dropdown-list-item-text { .dropdown-list-item-text {
flex-grow: 1; flex-grow: 1;
color: ${itemColor}; color: ${itemColor};
} }
`}</style> `}
</style>
</li> </li>
) )
} }

@ -1,7 +1,6 @@
import React from 'react' import React from 'react'
import { COLORS } from '../lib/constants'
import Checkmark from './svg/Checkmark' import Checkmark from './svg/Checkmark'
import { EXPORT_SIZES } from '../lib/constants' import { EXPORT_SIZES, COLORS } from '../lib/constants'
export default class extends React.Component { export default class extends React.Component {
constructor(props) { constructor(props) {
@ -22,12 +21,16 @@ export default class extends React.Component {
} }
renderExportSizes() { renderExportSizes() {
return EXPORT_SIZES.map((exportSize, i) => { return EXPORT_SIZES.map(exportSize => (
return ( <div
<div className="list-item" key={i} onClick={this.select.bind(null, exportSize.id)}> className="list-item"
<span style={{ ExportSize: exportSize.id }}>{exportSize.name}</span> key={exportSize.id}
{this.props.selected === exportSize.id ? <Checkmark /> : null} onClick={this.select.bind(null, exportSize.id)}
<style jsx>{` >
<span style={{ ExportSize: exportSize.id }}>{exportSize.name}</span>
{this.props.selected === exportSize.id ? <Checkmark /> : null}
<style jsx>
{`
.list-item { .list-item {
display: flex; display: flex;
align-items: center; align-items: center;
@ -44,10 +47,10 @@ export default class extends React.Component {
.list-item:last-of-type { .list-item:last-of-type {
border-bottom: none; border-bottom: none;
} }
`}</style> `}
</div> </style>
) </div>
}) ))
} }
render() { render() {
@ -63,25 +66,27 @@ export default class extends React.Component {
<span style={{ exportSize: selectedExportSize.id }}>{selectedExportSize.name}</span> <span style={{ exportSize: selectedExportSize.id }}>{selectedExportSize.name}</span>
</div> </div>
<div className="list">{this.renderExportSizes()}</div> <div className="list">{this.renderExportSizes()}</div>
<style jsx>{` <style jsx>
.display { {`
display: flex; .display {
align-items: center; display: flex;
justify-content: space-between; align-items: center;
cursor: pointer; justify-content: space-between;
user-select: none; cursor: pointer;
padding: 8px; user-select: none;
} padding: 8px;
.list { }
display: none; .list {
margin-top: -1px; display: none;
max-height: 80px; margin-top: -1px;
overflow-y: scroll; max-height: 80px;
} overflow-y: scroll;
.is-visible + .list { }
display: block; .is-visible + .list {
} display: block;
`}</style> }
`}
</style>
</div> </div>
) )
} }

@ -21,28 +21,30 @@ export default class extends React.Component {
} }
renderListItems() { renderListItems() {
return FONTS.map((font, i) => ( return FONTS.map(font => (
<div className="list-item" key={i} onClick={this.select.bind(null, font.id)}> <div className="list-item" key={font.id} onClick={this.select.bind(null, font.id)}>
<span style={{ fontFamily: font.id }}>{font.name}</span> <span style={{ fontFamily: font.id }}>{font.name}</span>
{this.props.selected === font.id ? <Checkmark /> : null} {this.props.selected === font.id ? <Checkmark /> : null}
<style jsx>{` <style jsx>
.list-item { {`
display: flex; .list-item {
align-items: center; display: flex;
justify-content: space-between; align-items: center;
cursor: pointer; justify-content: space-between;
user-select: none; cursor: pointer;
padding: 8px 16px; user-select: none;
border-bottom: 1px solid ${COLORS.SECONDARY}; padding: 8px 16px;
background: rgba(255, 255, 255, 0.165); border-bottom: 1px solid ${COLORS.SECONDARY};
} background: rgba(255, 255, 255, 0.165);
.list-item:first-of-type { }
border-top: 1px solid ${COLORS.SECONDARY}; .list-item:first-of-type {
} border-top: 1px solid ${COLORS.SECONDARY};
.list-item:last-of-type { }
border-bottom: none; .list-item:last-of-type {
} border-bottom: none;
`}</style> }
`}
</style>
</div> </div>
)) ))
} }
@ -59,25 +61,27 @@ export default class extends React.Component {
<span style={{ fontFamily: selectedFont.id }}>{selectedFont.name}</span> <span style={{ fontFamily: selectedFont.id }}>{selectedFont.name}</span>
</div> </div>
<div className="list">{this.renderListItems()}</div> <div className="list">{this.renderListItems()}</div>
<style jsx>{` <style jsx>
.display { {`
display: flex; .display {
align-items: center; display: flex;
justify-content: space-between; align-items: center;
cursor: pointer; justify-content: space-between;
user-select: none; cursor: pointer;
padding: 8px; user-select: none;
} padding: 8px;
.list { }
display: none; .list {
margin-top: -1px; display: none;
max-height: 80px; margin-top: -1px;
overflow-y: scroll; max-height: 80px;
} overflow-y: scroll;
.is-visible + .list { }
display: block; .is-visible + .list {
} display: block;
`}</style> }
`}
</style>
</div> </div>
) )
} }

@ -4,7 +4,7 @@ import { COLORS } from '../lib/constants'
const Footer = () => ( const Footer = () => (
<footer role="contentinfo" className="mt3"> <footer role="contentinfo" className="mt3">
<nav role="navigation" className="mt3"> <nav className="mt3">
<Link href="/about"> <Link href="/about">
<a className="link">about</a> <a className="link">about</a>
</Link> </Link>
@ -22,33 +22,35 @@ const Footer = () => (
</a>{' '} </a>{' '}
¬ ¬
</div> </div>
<style jsx>{` <style jsx>
footer { {`
font-size: 14px; footer {
} font-size: 14px;
}
footer > div { footer > div {
text-align: center; text-align: center;
color: ${COLORS.GRAY}; color: ${COLORS.GRAY};
} }
a { a {
margin-right: 16px; margin-right: 16px;
} }
a:last-child { a:last-child {
margin-right: 0; margin-right: 0;
} }
.dawn-link { .dawn-link {
color: ${COLORS.PRIMARY}; color: ${COLORS.PRIMARY};
text-decoration: none; text-decoration: none;
} }
.dawn-link:hover { .dawn-link:hover {
color: #fff; color: #fff;
} }
`}</style> `}
</style>
</footer> </footer>
) )

@ -14,25 +14,27 @@ const Header = ({ enableHeroText }) => (
</h2> </h2>
) : null} ) : null}
</div> </div>
<style jsx>{` <style jsx>
.header { {`
width: 656px; .header {
} width: 656px;
}
.header-content { .header-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
.header-content a { .header-content a {
height: 64px; height: 64px;
} }
h2 { h2 {
text-align: center; text-align: center;
} }
`}</style> `}
</style>
</header> </header>
) )

@ -1,9 +1,7 @@
import React from 'react' import React from 'react'
import ReactCrop, { makeAspectCrop } from 'react-image-crop' import ReactCrop, { makeAspectCrop } from 'react-image-crop'
import Slider from './Slider'
import RandomImage from './RandomImage' import RandomImage from './RandomImage'
import { COLORS } from '../lib/constants'
import { fileToDataURL } from '../lib/util' import { fileToDataURL } from '../lib/util'
const getCroppedImg = (imageDataURL, pixelCrop) => { const getCroppedImg = (imageDataURL, pixelCrop) => {
@ -12,7 +10,7 @@ const getCroppedImg = (imageDataURL, pixelCrop) => {
canvas.height = pixelCrop.height canvas.height = pixelCrop.height
const ctx = canvas.getContext('2d') const ctx = canvas.getContext('2d')
return new Promise((resolve, reject) => { return new Promise(resolve => {
const image = new Image() const image = new Image()
image.src = imageDataURL image.src = imageDataURL
image.onload = () => { image.onload = () => {
@ -47,7 +45,7 @@ export default class extends React.Component {
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (this.state.crop && this.props.aspectRatio != nextProps.aspectRatio) { if (this.state.crop && this.props.aspectRatio !== nextProps.aspectRatio) {
// update crop for editor container aspect-ratio change // update crop for editor container aspect-ratio change
this.setState({ this.setState({
crop: makeAspectCrop( crop: makeAspectCrop(
@ -61,20 +59,17 @@ export default class extends React.Component {
} }
} }
selectImage(e) { async onDragEnd() {
const file = e.target ? e.target.files[0] : e if (this.state.pixelCrop) {
const croppedImg = await getCroppedImg(this.props.imageDataURL, this.state.pixelCrop)
return fileToDataURL(file).then(dataURL => this.props.onChange({ backgroundImageSelection: croppedImg })
this.props.onChange({ backgroundImage: dataURL, backgroundImageSelection: null }) }
)
} }
removeImage() { onCropChange(crop, pixelCrop) {
this.setState(INITIAL_STATE, () => { this.setState({
this.props.onChange({ crop: { ...crop, aspect: this.props.aspectRatio },
backgroundImage: null, pixelCrop
backgroundImageSelection: null
})
}) })
} }
@ -93,18 +88,21 @@ export default class extends React.Component {
}) })
} }
onCropChange(crop, pixelCrop) { selectImage(e) {
this.setState({ const file = e.target ? e.target.files[0] : e
crop: { ...crop, aspect: this.props.aspectRatio },
pixelCrop return fileToDataURL(file).then(dataURL =>
}) this.props.onChange({ backgroundImage: dataURL, backgroundImageSelection: null })
)
} }
async onDragEnd() { removeImage() {
if (this.state.pixelCrop) { this.setState(INITIAL_STATE, () => {
const croppedImg = await getCroppedImg(this.props.imageDataURL, this.state.pixelCrop) this.props.onChange({
this.props.onChange({ backgroundImageSelection: croppedImg }) backgroundImage: null,
} backgroundImageSelection: null
})
})
} }
render() { render() {
@ -125,31 +123,33 @@ export default class extends React.Component {
</span> </span>
<RandomImage onChange={this.selectImage} /> <RandomImage onChange={this.selectImage} />
</div> </div>
<style jsx>{` <style jsx>
.choose-image, {`
.random-image { .choose-image,
padding: 8px; .random-image {
} padding: 8px;
}
input {
cursor: pointer; input {
outline: none; cursor: pointer;
} outline: none;
}
span {
display: block; span {
margin-bottom: 16px; display: block;
} margin-bottom: 16px;
}
a {
text-decoration: underline; a {
} text-decoration: underline;
}
hr {
border-bottom: none; hr {
margin-bottom: 0; border-bottom: none;
} margin-bottom: 0;
`}</style> }
`}
</style>
</div> </div>
) )
@ -174,31 +174,33 @@ export default class extends React.Component {
keepSelection keepSelection
/> />
</div> </div>
<style jsx>{` <style jsx>
.settings-container img { {`
width: 100%; .settings-container img {
} width: 100%;
}
.label {
user-select: none; .label {
margin-bottom: 4px; user-select: none;
} margin-bottom: 4px;
}
:global(.ReactCrop__image) {
user-select: none; :global(.ReactCrop__image) {
user-drag: none; user-select: none;
} user-drag: none;
}
.image-container {
padding: 8px; .image-container {
} padding: 8px;
}
.image-container .label {
display: flex; .image-container .label {
justify-content: space-between; display: flex;
align-items: center; justify-content: space-between;
} align-items: center;
`}</style> }
`}
</style>
</div> </div>
) )
} }
@ -206,11 +208,13 @@ export default class extends React.Component {
return ( return (
<div> <div>
<div className="image-picker-container">{content}</div> <div className="image-picker-container">{content}</div>
<style jsx>{` <style jsx>
.image-picker-container { {`
font-size: 12px; .image-picker-container {
} font-size: 12px;
`}</style> }
`}
</style>
</div> </div>
) )
} }

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import { Controls, ControlsBW } from './svg/Controls'
export default ({ language }) => ( export default ({ language }) => (
<div className="language"> <div className="language">

@ -1,5 +1,5 @@
import Head from 'next/head' import Head from 'next/head'
import { THEMES, COLORS } from '../lib/constants' import { THEMES } from '../lib/constants'
import Reset from './style/Reset' import Reset from './style/Reset'
import Font from './style/Font' import Font from './style/Font'
import Typography from './style/Typography' import Typography from './style/Typography'
@ -39,11 +39,11 @@ export default () => (
/> />
<link <link
rel="stylesheet" rel="stylesheet"
href={`//cdnjs.cloudflare.com/ajax/libs/codemirror/5.30.0/theme/solarized.min.css`} href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.30.0/theme/solarized.min.css"
/> />
{THEMES.filter(t => t.hasStylesheet !== false).map((theme, i) => ( {THEMES.filter(t => t.hasStylesheet !== false).map(theme => (
<link <link
key={i} key={theme.id}
rel="stylesheet" rel="stylesheet"
href={ href={
theme.link || theme.link ||
@ -55,10 +55,12 @@ export default () => (
<Reset /> <Reset />
<Font /> <Font />
<Typography /> <Typography />
<style jsx>{` <style jsx>
.meta { {`
display: none; .meta {
} display: none;
`}</style> }
`}
</style>
</div> </div>
) )

@ -2,25 +2,27 @@ const Overlay = props => (
<div className="dnd-container"> <div className="dnd-container">
{props.isOver ? <div className="dnd-overlay">{props.title}</div> : null} {props.isOver ? <div className="dnd-overlay">{props.title}</div> : null}
{props.children} {props.children}
<style jsx>{` <style jsx>
.dnd-container { {`
position: relative; .dnd-container {
} position: relative;
}
.dnd-overlay { .dnd-overlay {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
text-align: center; text-align: center;
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: 999; z-index: 999;
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
background: rgba(0, 0, 0, 0.85); background: rgba(0, 0, 0, 0.85);
} }
`}</style> `}
</style>
</div> </div>
) )

@ -11,13 +11,15 @@ export default ({ children, enableHeroText }) => (
<Footer /> <Footer />
<style jsx>{` <style jsx>
.main { {`
display: flex; .main {
justify-content: center; display: flex;
flex-direction: column; justify-content: center;
align-items: center; flex-direction: column;
} align-items: center;
`}</style> }
`}
</style>
</main> </main>
) )

@ -10,9 +10,8 @@ const WALLPAPER_COLLECTION_ID = 136026
const RANDOM_WALLPAPER_URL = `https://source.unsplash.com/collection/${WALLPAPER_COLLECTION_ID}/240x320` const RANDOM_WALLPAPER_URL = `https://source.unsplash.com/collection/${WALLPAPER_COLLECTION_ID}/240x320`
const largerImage = url => url.replace(/w=\d+/, 'w=1920').replace(/&h=\d+/, '') const largerImage = url => url.replace(/w=\d+/, 'w=1920').replace(/&h=\d+/, '')
const smallerImage = url => url.replace(/w=\d+/, 'w=240')
export default class extends React.Component { export default class RandomImage extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { cacheIndex: 0, loading: false } this.state = { cacheIndex: 0, loading: false }
@ -22,9 +21,6 @@ export default class extends React.Component {
this.nextImage = this.nextImage.bind(this) this.nextImage = this.nextImage.bind(this)
} }
cache = []
imageUrls = {}
// fetch images in browser (we require window.FileReader) // fetch images in browser (we require window.FileReader)
componentDidMount() { componentDidMount() {
// clear cache when remounted // clear cache when remounted
@ -39,7 +35,7 @@ export default class extends React.Component {
const res = await axios.get(`${RANDOM_WALLPAPER_URL}?sig=${sig}`, { responseType: 'blob' }) const res = await axios.get(`${RANDOM_WALLPAPER_URL}?sig=${sig}`, { responseType: 'blob' })
// image already in cache? // image already in cache?
if (this.imageUrls[res.request.responseURL]) return if (this.imageUrls[res.request.responseURL]) return undefined
this.imageUrls[res.request.responseURL] = true this.imageUrls[res.request.responseURL] = true
return { return {
@ -48,6 +44,9 @@ export default class extends React.Component {
} }
} }
cache = []
imageUrls = {}
selectImage() { selectImage() {
this.setState({ loading: true }) this.setState({ loading: true })
axios axios
@ -85,27 +84,29 @@ export default class extends React.Component {
<span onClick={this.nextImage}>Try Another</span> <span onClick={this.nextImage}>Try Another</span>
</div> </div>
<div className="image">{this.state.loading && <Spinner />}</div> <div className="image">{this.state.loading && <Spinner />}</div>
<style jsx>{` <style jsx>
.image { {`
width: 100%; .image {
height: 120px; width: 100%;
background: url(${bgImage}); height: 120px;
background-size: cover; background: url(${bgImage});
background-repeat: no-repeat; background-size: cover;
} background-repeat: no-repeat;
}
.controls {
display: flex; .controls {
justify-content: space-between; display: flex;
margin-bottom: 4px; justify-content: space-between;
} margin-bottom: 4px;
}
span {
opacity: ${this.state.loading ? 0.5 : 1}; span {
cursor: ${this.state.loading ? 'not-allowed' : 'pointer'}; opacity: ${this.state.loading ? 0.5 : 1};
user-select: none; cursor: ${this.state.loading ? 'not-allowed' : 'pointer'};
} user-select: none;
`}</style> }
`}
</style>
</div> </div>
) )
} }

@ -116,62 +116,64 @@ class Settings extends React.Component {
/> />
</Collapse> </Collapse>
</div> </div>
<style jsx>{` <style jsx>
.settings-container { {`
display: flex; .settings-container {
position: relative; display: flex;
height: 100%; position: relative;
width: 37px; height: 100%;
align-items: center; width: 37px;
justify-content: center; align-items: center;
border-radius: 3px; justify-content: center;
color: #fff; border-radius: 3px;
font-size: 12px; color: #fff;
} font-size: 12px;
}
.settings-display { .settings-display {
height: 100%; height: 100%;
width: 100%; width: 100%;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
border: 1px solid ${COLORS.SECONDARY}; border: 1px solid ${COLORS.SECONDARY};
border-radius: 3px; border-radius: 3px;
user-select: none; user-select: none;
position: relative; position: relative;
z-index: 1; z-index: 1;
cursor: pointer; cursor: pointer;
} }
.settings-display:hover { .settings-display:hover {
background: ${COLORS.HOVER}; background: ${COLORS.HOVER};
} }
.is-visible + .settings-settings { .is-visible + .settings-settings {
display: block; display: block;
} }
.settings-settings { .settings-settings {
display: none; display: none;
position: absolute; position: absolute;
top: 44px; top: 44px;
left: 0; left: 0;
border: 1px solid ${COLORS.SECONDARY}; border: 1px solid ${COLORS.SECONDARY};
width: 184px; width: 184px;
border-radius: 3px; border-radius: 3px;
background: ${COLORS.BLACK}; background: ${COLORS.BLACK};
} }
.settings-settings > :global(div) { .settings-settings > :global(div) {
border-bottom: solid 1px ${COLORS.SECONDARY}; border-bottom: solid 1px ${COLORS.SECONDARY};
} }
.settings-settings > :global(div):first-child, .settings-settings > :global(div):first-child,
.settings-settings > :global(div):last-child, .settings-settings > :global(div):last-child,
.settings-settings > :global(.collapse) { .settings-settings > :global(.collapse) {
border-bottom: none; border-bottom: none;
} }
`}</style> `}
</style>
</div> </div>
) )
} }

@ -27,49 +27,51 @@ export default class extends React.Component {
<div <div
className="slider-bg" className="slider-bg"
style={{ style={{
transform: `translate3d(${(parseInt(this.props.value) - minValue) * transform: `translate3d(${(parseInt(this.props.value, 10) - minValue) *
1.0 / 1.0 /
(maxValue - minValue) * (maxValue - minValue) *
100}%, 0px, 0px)` 100}%, 0px, 0px)`
}} }}
/> />
<style jsx>{` <style jsx>
.slider { {`
position: relative; .slider {
height: 32px; position: relative;
overflow: hidden; height: 32px;
user-select: none; overflow: hidden;
} user-select: none;
}
.slider:last-of-type { .slider:last-of-type {
border-bottom: 0; border-bottom: 0;
} }
.label { .label {
position: absolute; position: absolute;
left: 8px; left: 8px;
height: 32px; height: 32px;
line-height: 32px; line-height: 32px;
} }
.slider input { .slider input {
opacity: 0; opacity: 0;
cursor: ew-resize; cursor: ew-resize;
position: relative; position: relative;
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
.slider-bg { .slider-bg {
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
pointer-events: none; pointer-events: none;
height: 32px; height: 32px;
width: 100%; width: 100%;
background: rgba(255, 255, 255, 0.165); background: rgba(255, 255, 255, 0.165);
} }
`}</style> `}
</style>
</div> </div>
) )
} }

@ -18,30 +18,32 @@ export default class extends React.Component {
} }
renderThemes() { renderThemes() {
return WINDOW_THEMES.map((theme, i) => { return WINDOW_THEMES.map(theme => {
const Img = WINDOW_THEMES_MAP[theme] const Img = WINDOW_THEMES_MAP[theme]
return ( return (
<div <div
className={`theme ${this.props.selected === theme ? 'selected' : ''}`} className={`theme ${this.props.selected === theme ? 'selected' : ''}`}
key={i} key={theme}
onClick={this.select.bind(null, theme)} onClick={this.select.bind(null, theme)}
> >
<Img /> <Img />
<style jsx>{` <style jsx>
.theme { {`
cursor: pointer; .theme {
margin-right: 8px; cursor: pointer;
} margin-right: 8px;
}
.theme:last-of-type { .theme:last-of-type {
margin-right: 0px; margin-right: 0px;
} }
.selected :global(svg) { .selected :global(svg) {
border-radius: 3px; border-radius: 3px;
border: solid 2px ${COLORS.SECONDARY}; border: solid 2px ${COLORS.SECONDARY};
} }
`}</style> `}
</style>
</div> </div>
) )
}) })
@ -52,22 +54,24 @@ export default class extends React.Component {
<div className="window-theme"> <div className="window-theme">
<span className="label">Window theme</span> <span className="label">Window theme</span>
<div className="themes">{this.renderThemes()}</div> <div className="themes">{this.renderThemes()}</div>
<style jsx>{` <style jsx>
.window-theme { {`
padding: 8px; .window-theme {
} padding: 8px;
}
.window-theme span { .window-theme span {
display: inline-block; display: inline-block;
margin-bottom: 8px; margin-bottom: 8px;
} }
.themes { .themes {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
width: 100%; width: 100%;
} }
`}</style> `}
</style>
</div> </div>
) )
} }

@ -13,19 +13,21 @@ export default class extends React.Component {
render() { render() {
return ( return (
<div className={'toggle ' + this.props.className} onClick={this.toggle}> <div className={`toggle ${this.props.className}`} onClick={this.toggle}>
<span className="label">{this.props.label}</span> <span className="label">{this.props.label}</span>
{this.props.enabled ? <Checkmark /> : null} {this.props.enabled ? <Checkmark /> : null}
<style jsx>{` <style jsx>
.toggle { {`
display: flex; .toggle {
align-items: center; display: flex;
justify-content: ${this.props.center ? 'center' : 'space-between'}; align-items: center;
cursor: pointer; justify-content: ${this.props.center ? 'center' : 'space-between'};
user-select: none; cursor: pointer;
padding: 8px; user-select: none;
} padding: 8px;
`}</style> }
`}
</style>
</div> </div>
) )
} }

@ -1,27 +1,30 @@
import React from 'react' import React from 'react'
const Toolbar = props => ( const Toolbar = props => (
<div id="toolbar"> <div id="toolbar">
{props.children} {props.children}
<style jsx>{` <style jsx>
#toolbar { {`
width: 100%; #toolbar {
height: 40px; // TODO fix width: 100%;
margin-bottom: 16px; height: 40px; // TODO fix
display: flex; margin-bottom: 16px;
position: relative; display: flex;
z-index: 3; position: relative;
font-size: 14px; z-index: 3;
color: #fff; font-size: 14px;
} color: #fff;
}
#toolbar > :global(div) { #toolbar > :global(div) {
margin-right: 8px; margin-right: 8px;
} }
#toolbar > :global(div):last-child { #toolbar > :global(div):last-child {
margin-right: 0px; margin-right: 0px;
} }
`}</style> `}
</style>
</div> </div>
) )

@ -3,17 +3,19 @@ import React from 'react'
export default ({ fromLeft }) => ( export default ({ fromLeft }) => (
<div style={{ left: fromLeft }}> <div style={{ left: fromLeft }}>
<div className="window-pointer" /> <div className="window-pointer" />
<style jsx>{` <style jsx>
.window-pointer { {`
width: 0px; .window-pointer {
height: 0px; width: 0px;
border-style: solid; height: 0px;
border-width: 0 4px 5px 4px; border-style: solid;
border-color: transparent transparent #fff transparent; border-width: 0 4px 5px 4px;
position: absolute; border-color: transparent transparent #fff transparent;
top: -5px; position: absolute;
left: 15px; top: -5px;
} left: 15px;
`}</style> }
`}
</style>
</div> </div>
) )

@ -1,91 +1,93 @@
export default () => ( export default () => (
<style jsx global>{` <style jsx global>
@font-face { {`
font-family: 'Iosevka'; @font-face {
src: url('//cdn.jsdelivr.net/npm/@typopro/web-iosevka@3.7.5/TypoPRO-iosevka-term-bold.woff') font-family: 'Iosevka';
format('woff'); src: url('//cdn.jsdelivr.net/npm/@typopro/web-iosevka@3.7.5/TypoPRO-iosevka-term-bold.woff')
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'Hack';
src: url('//cdn.jsdelivr.net/font-hack/2.020/fonts/woff2/hack-regular-webfont.woff2?v=2.020')
format('woff2'),
url('//cdn.jsdelivr.net/font-hack/2.020/fonts/woff/hack-regular-webfont.woff?v=2.020')
format('woff'); format('woff');
font-weight: 400; font-weight: 400;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Fira Code'; font-family: 'Hack';
src: url('//cdn.rawgit.com/tonsky/FiraCode/1.204/distr/woff2/FiraCode-Regular.woff2') src: url('//cdn.jsdelivr.net/font-hack/2.020/fonts/woff2/hack-regular-webfont.woff2?v=2.020')
format('woff2'), format('woff2'),
url('//cdn.rawgit.com/tonsky/FiraCode/1.204/distr/woff/FiraCode-Regular.woff') url('//cdn.jsdelivr.net/font-hack/2.020/fonts/woff/hack-regular-webfont.woff?v=2.020')
format('woff'); format('woff');
font-weight: 400; font-weight: 400;
font-style: normal; font-style: normal;
} }
@font-face {
font-family: 'Fira Code';
src: url('//cdn.rawgit.com/tonsky/FiraCode/1.204/distr/woff2/FiraCode-Regular.woff2')
format('woff2'),
url('//cdn.rawgit.com/tonsky/FiraCode/1.204/distr/woff/FiraCode-Regular.woff')
format('woff');
font-weight: 400;
font-style: normal;
}
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Anonymous Pro'; font-family: 'Anonymous Pro';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Anonymous Pro Regular'), local('AnonymousPro-Regular'), src: local('Anonymous Pro Regular'), local('AnonymousPro-Regular'),
url(//fonts.gstatic.com/s/anonymouspro/v11/Zhfjj_gat3waL4JSju74E3n3cbdKJftHIk87C9ihfO8.woff2) url(//fonts.gstatic.com/s/anonymouspro/v11/Zhfjj_gat3waL4JSju74E3n3cbdKJftHIk87C9ihfO8.woff2)
format('woff2'); format('woff2');
unicode-range: U+0000-00ff, U+0131, U+0152-0153, U+02bb-02bc, U+02c6, U+02da, U+02dc, unicode-range: U + 0000-00ff, U + 0131, U + 0152-0153, U + 02bb-02bc, U + 02c6, U + 02da,
U+2000-206f, U+2074, U+20ac, U+2122, U+2212, U+2215; U + 02dc, U + 2000-206f, U + 2074, U + 20ac, U + 2122, U + 2212, U + 2215;
} }
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Droid Sans Mono'; font-family: 'Droid Sans Mono';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Droid Sans Mono Regular'), local('DroidSansMono-Regular'), src: local('Droid Sans Mono Regular'), local('DroidSansMono-Regular'),
url(//fonts.gstatic.com/s/droidsansmono/v9/ns-m2xQYezAtqh7ai59hJVlgUn8GogvcKKzoM9Dh-4E.woff2) url(//fonts.gstatic.com/s/droidsansmono/v9/ns-m2xQYezAtqh7ai59hJVlgUn8GogvcKKzoM9Dh-4E.woff2)
format('woff2'); format('woff2');
unicode-range: U+0000-00ff, U+0131, U+0152-0153, U+02bb-02bc, U+02c6, U+02da, U+02dc, unicode-range: U + 0000-00ff, U + 0131, U + 0152-0153, U + 02bb-02bc, U + 02c6, U + 02da,
U+2000-206f, U+2074, U+20ac, U+2122, U+2212, U+2215; U + 02dc, U + 2000-206f, U + 2074, U + 20ac, U + 2122, U + 2212, U + 2215;
} }
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Inconsolata'; font-family: 'Inconsolata';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Inconsolata Regular'), local('Inconsolata-Regular'), src: local('Inconsolata Regular'), local('Inconsolata-Regular'),
url(//fonts.gstatic.com/s/inconsolata/v16/BjAYBlHtW3CJxDcjzrnZCIgp9Q8gbYrhqGlRav_IXfk.woff2) url(//fonts.gstatic.com/s/inconsolata/v16/BjAYBlHtW3CJxDcjzrnZCIgp9Q8gbYrhqGlRav_IXfk.woff2)
format('woff2'); format('woff2');
unicode-range: U+0000-00ff, U+0131, U+0152-0153, U+02bb-02bc, U+02c6, U+02da, U+02dc, unicode-range: U + 0000-00ff, U + 0131, U + 0152-0153, U + 02bb-02bc, U + 02c6, U + 02da,
U+2000-206f, U+2074, U+20ac, U+2122, U+2212, U+2215; U + 02dc, U + 2000-206f, U + 2074, U + 20ac, U + 2122, U + 2212, U + 2215;
} }
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Source Code Pro'; font-family: 'Source Code Pro';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Source Code Pro'), local('SourceCodePro-Regular'), src: local('Source Code Pro'), local('SourceCodePro-Regular'),
url(//fonts.gstatic.com/s/sourcecodepro/v7/mrl8jkM18OlOQN8JLgasD5bPFduIYtoLzwST68uhz_Y.woff2) url(//fonts.gstatic.com/s/sourcecodepro/v7/mrl8jkM18OlOQN8JLgasD5bPFduIYtoLzwST68uhz_Y.woff2)
format('woff2'); format('woff2');
unicode-range: U+0000-00ff, U+0131, U+0152-0153, U+02bb-02bc, U+02c6, U+02da, U+02dc, unicode-range: U + 0000-00ff, U + 0131, U + 0152-0153, U + 02bb-02bc, U + 02c6, U + 02da,
U+2000-206f, U+2074, U+20ac, U+2122, U+2212, U+2215; U + 02dc, U + 2000-206f, U + 2074, U + 20ac, U + 2122, U + 2212, U + 2215;
} }
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Ubuntu Mono'; font-family: 'Ubuntu Mono';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Ubuntu Mono'), local('UbuntuMono-Regular'), src: local('Ubuntu Mono'), local('UbuntuMono-Regular'),
url(//fonts.gstatic.com/s/ubuntumono/v7/ViZhet7Ak-LRXZMXzuAfkYgp9Q8gbYrhqGlRav_IXfk.woff2) url(//fonts.gstatic.com/s/ubuntumono/v7/ViZhet7Ak-LRXZMXzuAfkYgp9Q8gbYrhqGlRav_IXfk.woff2)
format('woff2'); format('woff2');
unicode-range: U+0000-00ff, U+0131, U+0152-0153, U+02bb-02bc, U+02c6, U+02da, U+02dc, unicode-range: U + 0000-00ff, U + 0131, U + 0152-0153, U + 02bb-02bc, U + 02c6, U + 02da,
U+2000-206f, U+2074, U+20ac, U+2122, U+2212, U+2215; U + 02dc, U + 2000-206f, U + 2074, U + 20ac, U + 2122, U + 2212, U + 2215;
} }
`}</style> `}
</style>
) )

@ -1,195 +1,197 @@
import { COLORS } from '../../lib/constants' import { COLORS } from '../../lib/constants'
export default () => ( export default () => (
<style jsx global>{` <style jsx global>
/* http://meyerweb.com/eric/tools/css/reset/ {`
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126 v2.0 | 20110126
License: none (public domain) License: none (public domain)
*/ */
html, html,
body, body,
div, div,
span, span,
applet, applet,
object, object,
iframe, iframe,
h1, h1,
h2, h2,
h3, h3,
h4, h4,
h5, h5,
h6, h6,
p, p,
blockquote, blockquote,
pre, pre,
a, a,
abbr, abbr,
acronym, acronym,
address, address,
big, big,
cite, cite,
code, code,
del, del,
dfn, dfn,
em, em,
img, img,
ins, ins,
kbd, kbd,
q, q,
s, s,
samp, samp,
small, small,
strike, strike,
strong, strong,
sub, sub,
sup, sup,
tt, tt,
var, var,
b, b,
u, u,
i, i,
center, center,
dl, dl,
dt, dt,
dd, dd,
ol, ol,
ul, ul,
li, li,
fieldset, fieldset,
form, form,
label, label,
legend, legend,
table, table,
caption, caption,
tbody, tbody,
tfoot, tfoot,
thead, thead,
tr, tr,
th, th,
td, td,
article, article,
aside, aside,
canvas, canvas,
details, details,
embed, embed,
figure, figure,
figcaption, figcaption,
footer, footer,
header, header,
hgroup, hgroup,
menu, menu,
nav, nav,
output, output,
ruby, ruby,
section, section,
summary, summary,
time, time,
mark, mark,
audio, audio,
video { video {
margin: 0; margin: 0;
padding: 0; padding: 0;
border: 0; border: 0;
font-size: 100%; font-size: 100%;
font-weight: inherit; font-weight: inherit;
font-family: inherit; font-family: inherit;
font-style: inherit; font-style: inherit;
vertical-align: baseline; vertical-align: baseline;
} }
/* HTML5 display-role reset for older browsers */ /* HTML5 display-role reset for older browsers */
article, article,
aside, aside,
details, details,
figcaption, figcaption,
figure, figure,
footer, footer,
header, header,
hgroup, hgroup,
menu, menu,
nav, nav,
section { section {
display: block; display: block;
} }
ol, ol,
ul { ul {
list-style: none; list-style: none;
} }
blockquote, blockquote,
q { q {
quotes: none; quotes: none;
} }
blockquote:before, blockquote:before,
blockquote:after, blockquote:after,
q:before, q:before,
q:after { q:after {
content: ''; content: '';
content: none; content: none;
} }
table { table {
border-collapse: collapse; border-collapse: collapse;
border-spacing: 0; border-spacing: 0;
} }
html, html,
body { body {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
background: ${COLORS.BLACK}; background: ${COLORS.BLACK};
color: white; 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; sans-serif;
font-weight: 400; font-weight: 400;
font-style: normal; font-style: normal;
text-transform: initial; text-transform: initial;
letter-spacing: initial; letter-spacing: initial;
overflow-y: auto; overflow-y: auto;
min-width: 848px; min-width: 848px;
min-height: 704px; min-height: 704px;
} }
* { * {
box-sizing: border-box; box-sizing: border-box;
} }
h1, h1,
h2, h2,
h3, h3,
h4, h4,
h5, h5,
h6 { h6 {
font-weight: 500; font-weight: 500;
} }
a { a {
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
} }
*::selection { *::selection {
background: rgba(255, 255, 255, 0.99); background: rgba(255, 255, 255, 0.99);
color: #121212; color: #121212;
} }
.link { .link {
color: #fff; color: #fff;
text-decoration: none; text-decoration: none;
padding-bottom: 3px; padding-bottom: 3px;
background: linear-gradient( background: linear-gradient(
to right, to right,
rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0.7) 0%,
rgba(255, 255, 255, 0.7) 100% rgba(255, 255, 255, 0.7) 100%
); );
background-size: 1px 1px; background-size: 1px 1px;
background-position: 0 100%; background-position: 0 100%;
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.link:hover { .link:hover {
color: ${COLORS.PRIMARY}; color: ${COLORS.PRIMARY};
background: none; background: none;
} }
`}</style> `}
</style>
) )

@ -1,178 +1,180 @@
export default () => ( export default () => (
<style jsx global>{` <style jsx global>
/* https://github.com/jxnblk/type-system {`
/* https://github.com/jxnblk/type-system
Brent Jackson Brent Jackson
License: MIT License: MIT
*/ */
:root { :root {
--h0: 4.5rem; --h0: 4.5rem;
--h1: 3rem; --h1: 3rem;
--h2: 2.25rem; --h2: 2.25rem;
--h3: 1.5rem; --h3: 1.5rem;
--h4: 1.125rem; --h4: 1.125rem;
--h5: 0.75rem; --h5: 0.75rem;
--lh: calc(4/3); --lh: calc(4 / 3);
--mx: 32em; --mx: 32em;
--m1: calc(2/3 * 1em); --m1: calc(2 / 3 * 1em);
--m2: calc(4/3 * 1em); --m2: calc(4 / 3 * 1em);
--m3: calc(8/3 * 1em); --m3: calc(8 / 3 * 1em);
--m4: calc(16/3 * 1em); --m4: calc(16 / 3 * 1em);
--x1: 0.5rem; --x1: 0.5rem;
--x2: 1rem; --x2: 1rem;
--x3: 2rem; --x3: 2rem;
--x4: 4rem; --x4: 4rem;
--x5: 8rem; --x5: 8rem;
--x6: 16rem; --x6: 16rem;
} }
body {
font-size: var(--h4);
line-height: var(--lh);
margin: 2rem 0;
}
h1, body {
h2, font-size: var(--h4);
h3 { line-height: var(--lh);
margin-top: var(--m1); margin: 2rem 0;
margin-bottom: 0; }
}
h4, h1,
h5, h2,
h6, h3 {
p, margin-top: var(--m1);
dl, margin-bottom: 0;
ol, }
ul,
blockquote {
margin-top: var(--m2);
margin-bottom: var(--m2);
}
h1 { h4,
font-size: var(--h2); h5,
} h6,
h2, p,
h3 { dl,
font-size: var(--h3); ol,
} ul,
h4 { blockquote {
font-size: var(--h4); margin-top: var(--m2);
} margin-bottom: var(--m2);
h5, }
h6 {
font-size: var(--h5);
}
.h0 { h1 {
font-size: var(--h0); font-size: var(--h2);
} }
.h1 { h2,
font-size: var(--h1); h3 {
} font-size: var(--h3);
.h2 { }
font-size: var(--h2); h4 {
} font-size: var(--h4);
.h3 { }
font-size: var(--h3); h5,
} h6 {
.h4 { font-size: var(--h5);
font-size: var(--h4); }
}
.h5 {
font-size: var(--h5);
}
.h6 {
font-size: var(--h5);
}
@media screen and (min-width: 40em) { .h0 {
.xh0 {
font-size: var(--h0); font-size: var(--h0);
} }
.xh1 { .h1 {
font-size: var(--h1); font-size: var(--h1);
} }
.xh2 { .h2 {
font-size: var(--h2); font-size: var(--h2);
} }
.xh3 { .h3 {
font-size: var(--h3); font-size: var(--h3);
} }
.xh4 { .h4 {
font-size: var(--h4); font-size: var(--h4);
} }
.xh5 { .h5 {
font-size: var(--h5); font-size: var(--h5);
} }
.xh6 { .h6 {
font-size: var(--h5); font-size: var(--h5);
} }
}
.lh1 { @media screen and (min-width: 40em) {
line-height: 1; .xh0 {
} font-size: var(--h0);
/* h0, h1, h3 */ }
.lh2 { .xh1 {
line-height: calc(7/6 * 1em); font-size: var(--h1);
} }
/* For body copy */ .xh2 {
.lh3 { font-size: var(--h2);
line-height: calc(16/9 * 1em); }
} .xh3 {
font-size: var(--h3);
}
.xh4 {
font-size: var(--h4);
}
.xh5 {
font-size: var(--h5);
}
.xh6 {
font-size: var(--h5);
}
}
.mt0 { .lh1 {
margin-top: 0; line-height: 1;
} }
.mb0 { /* h0, h1, h3 */
margin-bottom: 0; .lh2 {
} line-height: calc(7 / 6 * 1em);
.mt1 { }
margin-top: var(--x1); /* For body copy */
} .lh3 {
.mb1 { line-height: calc(16 / 9 * 1em);
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 { .mt0 {
max-width: var(--mx); margin-top: 0;
} }
.bold { .mb0 {
font-weight: bold; margin-bottom: 0;
} }
`}</style> .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;
}
`}
</style>
) )

@ -1,22 +1,23 @@
/* global domtoimage */
const PORT = parseInt(process.env.PORT, 10) || 3000 const PORT = parseInt(process.env.PORT, 10) || 3000
const ARBITRARY_WAIT_TIME = 500 const ARBITRARY_WAIT_TIME = 500
module.exports = browser => async (req, res) => { module.exports = browser => async (req, res) => {
let page = await browser.newPage() const page = await browser.newPage()
let state = req.body.state const { state } = req.body
if (!state) res.status(400).send() if (!state) res.status(400).send()
try { try {
await page.goto(`http://localhost:${PORT}?state=${state}`) await page.goto(`http://localhost:${PORT}?state=${state}`)
await page.addScriptTag({ path: `./lib/customDomToImage.js` }) await page.addScriptTag({ path: './lib/customDomToImage.js' })
// wait for page to detect language // wait for page to detect language
await delay(ARBITRARY_WAIT_TIME) await delay(ARBITRARY_WAIT_TIME)
const targetElement = await page.$('#export-container') const targetElement = await page.$('#export-container')
let dataUrl = await page.evaluate(target => { const dataUrl = await page.evaluate(target => {
const config = { const config = {
style: { style: {
transform: 'scale(2)', transform: 'scale(2)',

@ -30,7 +30,7 @@ const respondFail = (res, err) => {
} }
console.error(`Error: ${err.message || JSON.stringify(err, null, 2)}`) console.error(`Error: ${err.message || JSON.stringify(err, null, 2)}`)
res.status(500).send() return res.status(500).send()
} }
module.exports = (req, res) => { module.exports = (req, res) => {
@ -38,7 +38,7 @@ module.exports = (req, res) => {
return res.status(400).send() return res.status(400).send()
} }
uploadImage(req.body.data) return uploadImage(req.body.data)
.then(uploadTweet) .then(uploadTweet)
.then(extractImageUrl) .then(extractImageUrl)
.then(respondSuccess.bind(null, res)) .then(respondSuccess.bind(null, res))

@ -30,7 +30,7 @@ async function image(state) {
return axios.post(`${DOMAIN}/image`, { state }).then(res => res.data.dataUrl) return axios.post(`${DOMAIN}/image`, { state }).then(res => res.data.dataUrl)
} }
const getGist = uid => { function getGist(uid) {
return gistClient return gistClient
.get(`/gists/${uid}`) .get(`/gists/${uid}`)
.then(res => res.data) .then(res => res.data)
@ -41,10 +41,10 @@ const getGist = uid => {
// private // private
function openTwitterUrl(twitterUrl) { function openTwitterUrl(twitterUrl) {
const width = 575, const width = 575
height = 400 const height = 400
const left = (window.outerWidth - width) / 2 const left = (window.outerWidth - width) / 2
const right = (window.outerHeight - height) / 2 const top = (window.outerHeight - height) / 2
const opts = `status=1,width=${width},height=${height},top=${top},left=${left}` const opts = `status=1,width=${width},height=${height},top=${top},left=${left}`
window.open(twitterUrl, 'twitter', opts) window.open(twitterUrl, 'twitter', opts)

@ -1,4 +1,4 @@
const colors = new Set([ export const colors = new Set([
'indian red', 'indian red',
'crimson', 'crimson',
'lightpink', 'lightpink',
@ -595,6 +595,5 @@ const colors = new Set([
'whitesmoke' 'whitesmoke'
]) ])
export const validateColor = (str = '') => { export const validateColor = (str = '') =>
return /#\d{3,6}|rgba{0,1}\(.*?\)/gi.test(str) || colors.has(str.toLowerCase()) /#\d{3,6}|rgba{0,1}\(.*?\)/gi.test(str) || colors.has(str.toLowerCase())
}

@ -73,22 +73,21 @@ const keysToQuery = keys =>
export const getQueryStringState = query => { export const getQueryStringState = query => {
if (query.state) { if (query.state) {
return deserializeState(query.state) return deserializeState(query.state)
} else { }
const state = mapper.map(mappings, query)
deserializeCode(state)
Object.keys(state).forEach(key => { const state = mapper.map(mappings, query)
if (state[key] === '') state[key] = undefined deserializeCode(state)
})
return state Object.keys(state).forEach(key => {
} if (state[key] === '') state[key] = undefined
})
return state
} }
export const updateQueryString = state => { export const updateQueryString = state => {
// If react_perf is set as a queryParm, don't update
if (history.location.search.indexOf('react_perf') < 0) { if (history.location.search.indexOf('react_perf') < 0) {
let mappedState = mapper.map(reverseMappings, state) const mappedState = mapper.map(reverseMappings, state)
serializeCode(mappedState) serializeCode(mappedState)
history.replace({ history.replace({

@ -1,4 +1,5 @@
import morph from 'morphmorph' import morph from 'morphmorph'
const KEY = 'CARBON_STATE' const KEY = 'CARBON_STATE'
const assign = morph.assign(KEY) const assign = morph.assign(KEY)
@ -6,7 +7,9 @@ const assign = morph.assign(KEY)
const parse = v => { const parse = v => {
try { try {
return JSON.parse(v) return JSON.parse(v)
} catch (e) {} } catch (e) {
// pass
}
} }
const escapeHtml = s => { const escapeHtml = s => {
@ -27,10 +30,9 @@ export const capitalizeFirstLetter = s => s.charAt(0).toUpperCase() + s.slice(1)
export const range = n => [...Array(n).keys()] export const range = n => [...Array(n).keys()]
export const fileToDataURL = blob => { export const fileToDataURL = blob =>
return new Promise(res => { new Promise(res => {
const reader = new FileReader() const reader = new FileReader()
reader.onload = e => res(e.target.result) reader.onload = e => res(e.target.result)
reader.readAsDataURL(blob) reader.readAsDataURL(blob)
}) })
}

@ -1,4 +1,5 @@
import Document, { Head, Main, NextScript } from 'next/document' import Document, { Head, Main, NextScript } from 'next/document'
export default class extends Document { export default class extends Document {
render() { render() {
return ( return (

@ -1,7 +1,4 @@
import Page from '../components/Page' 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 { COLORS } from '../lib/constants'
export default () => ( export default () => (
@ -13,7 +10,10 @@ export default () => (
You know all of those code screenshots you see on Twitter? Although the code&apos;s You know all of those code screenshots you see on Twitter? Although the code&apos;s
usually impressive, we saw room for improvement in the aesthetic department. Carbon is the 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? 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> Go impress all of your followers with your newfound design prowess.{' '}
<span role="img" aria-label="Palette">
🎨
</span>
</p> </p>
</div> </div>
<div className="mb4"> <div className="mb4">
@ -23,12 +23,11 @@ export default () => (
<ul className="mt0 mb3"> <ul className="mt0 mb3">
<li>Drop a file into the editor</li> <li>Drop a file into the editor</li>
<li> <li>
Append a GitHub gist id to the url (<a Append a GitHub gist id to the url (
className="link" <a className="link" href="/0db00e81d5416c339181e59481c74b59">
href="/0db00e81d5416c339181e59481c74b59"
>
example example
</a>) </a>
)
</li> </li>
<li>Paste your code directly</li> <li>Paste your code directly</li>
</ul> </ul>
@ -56,24 +55,26 @@ export default () => (
</p> </p>
</div> </div>
</div> </div>
<style jsx>{` <style jsx>
p, {`
li { p,
color: ${COLORS.GRAY}; li {
} color: ${COLORS.GRAY};
}
span { span {
color: #fff; color: #fff;
} }
ul { ul {
list-style-position: inside; list-style-position: inside;
list-style-type: circle; list-style-type: circle;
} }
.about { .about {
max-width: 632px; max-width: 632px;
} }
`}</style> `}
</style>
</Page> </Page>
) )

@ -14,7 +14,6 @@ import Settings from '../components/Settings'
import Toolbar from '../components/Toolbar' import Toolbar from '../components/Toolbar'
import Overlay from '../components/Overlay' import Overlay from '../components/Overlay'
import Carbon from '../components/Carbon' import Carbon from '../components/Carbon'
import ArrowDown from '../components/svg/Arrowdown'
import api from '../lib/api' import api from '../lib/api'
import { import {
THEMES, THEMES,
@ -23,14 +22,11 @@ import {
LANGUAGE_MIME_HASH, LANGUAGE_MIME_HASH,
LANGUAGE_MODE_HASH, LANGUAGE_MODE_HASH,
LANGUAGE_NAME_HASH, LANGUAGE_NAME_HASH,
DEFAULT_LANGUAGE,
DEFAULT_THEME, DEFAULT_THEME,
DEFAULT_EXPORT_SIZE, DEFAULT_EXPORT_SIZE,
COLORS, COLORS,
EXPORT_SIZES,
EXPORT_SIZES_HASH, EXPORT_SIZES_HASH,
DEFAULT_CODE, DEFAULT_CODE,
DEFAULT_BG_COLOR,
DEFAULT_SETTINGS DEFAULT_SETTINGS
} from '../lib/constants' } from '../lib/constants'
import { getQueryStringState, updateQueryString, serializeState } from '../lib/routing' import { getQueryStringState, updateQueryString, serializeState } from '../lib/routing'
@ -106,10 +102,10 @@ class Editor extends React.Component {
} }
getCarbonImage({ format, type } = { format: 'png' }) { getCarbonImage({ format, type } = { format: 'png' }) {
//if safari, get image from api // if safari, get image from api
if ( if (
navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Safari') !== -1 &&
navigator.userAgent.indexOf('Chrome') == -1 && navigator.userAgent.indexOf('Chrome') === -1 &&
format === 'png' format === 'png'
) { ) {
const encodedState = serializeState(this.state) const encodedState = serializeState(this.state)
@ -266,19 +262,21 @@ class Editor extends React.Component {
)} )}
</ReadFileDropContainer> </ReadFileDropContainer>
</div> </div>
<style jsx>{` <style jsx>
#editor { {`
background: ${COLORS.BLACK}; #editor {
border: 3px solid ${COLORS.SECONDARY}; background: ${COLORS.BLACK};
border-radius: 8px; border: 3px solid ${COLORS.SECONDARY};
padding: 16px; border-radius: 8px;
} padding: 16px;
}
.buttons { .buttons {
display: flex; display: flex;
margin-left: auto; margin-left: auto;
} }
`}</style> `}
</style>
</Page> </Page>
) )
} }

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

Loading…
Cancel
Save