diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..103bd56
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,25 @@
+module.exports = {
+ parser: 'babel-eslint',
+ env: {
+ browser: true,
+ es6: true,
+ node: true
+ },
+ extends: ['eslint:recommended', 'plugin:react/recommended'],
+ parserOptions: {
+ ecmaFeatures: {
+ experimentalObjectRestSpread: true,
+ jsx: true
+ },
+ sourceType: 'module'
+ },
+ plugins: ['react', 'import'],
+ rules: {
+ 'react/react-in-jsx-scope': 'off',
+ 'react/prop-types': 'off',
+ 'react/display-name': 'off',
+ 'react/jsx-uses-react': 'error',
+ 'react/jsx-uses-vars': 'error',
+ 'import/no-unresolved': 2
+ }
+}
diff --git a/components/Carbon.js b/components/Carbon.js
index 365fb90..6145f2a 100644
--- a/components/Carbon.js
+++ b/components/Carbon.js
@@ -1,279 +1,41 @@
-import React, { PureComponent } from 'react'
-import * as hljs from 'highlight.js'
-import Spinner from 'react-spinner'
-import ResizeObserver from 'resize-observer-polyfill'
-import debounce from 'lodash.debounce'
-import ms from 'ms'
-
-import WindowControls from '../components/WindowControls'
-import Watermark from '../components/svg/Watermark'
-import CodeMirror from '../lib/react-codemirror'
-import { COLORS, LANGUAGE_MODE_HASH, LANGUAGE_NAME_HASH, DEFAULT_SETTINGS } from '../lib/constants'
-
-class Carbon extends PureComponent {
+// Theirs
+import React from 'react'
+import { Provider } from 'unstated'
+import HTML5Backend from 'react-dnd-html5-backend'
+import { DragDropContext } from 'react-dnd'
+
+// Ours
+import EditorContainer from '../containers/Editor'
+import Editor from './Editor'
+import Toolbar from './Toolbar'
+import { COLORS } from '../lib/constants'
+
+class Carbon extends React.Component {
constructor(props) {
super(props)
-
- this.state = {
- loading: true,
- language: props.config.language
- }
-
- this.handleLanguageChange = this.handleLanguageChange.bind(this)
- this.handleTitleBarChange = this.handleTitleBarChange.bind(this)
- this.codeUpdated = this.codeUpdated.bind(this)
- }
-
- componentDidMount() {
- this.setState({
- loading: false
- })
-
- this.handleLanguageChange(this.props.children)
-
- const ro = new ResizeObserver(entries => {
- const cr = entries[0].contentRect
- this.props.onAspectRatioChange(cr.width / cr.height)
- })
- ro.observe(this.exportContainerNode)
- }
-
- componentWillReceiveProps(newProps) {
- // TODO use getDerivedStateFromProps() on React@16.3
- this.handleLanguageChange(newProps.children, { customProps: newProps })
- }
-
- codeUpdated(newCode) {
- this.handleLanguageChange(newCode)
- this.props.updateCode(newCode)
- }
-
- handleTitleBarChange(newTitle) {
- this.props.updateTitleBar(newTitle)
+ this.inject = [new EditorContainer(props)]
}
- handleLanguageChange = debounce(
- (newCode, config) => {
- const props = (config && config.customProps) || this.props
-
- if (props.config.language === 'auto') {
- // try to set the language
- const detectedLanguage = hljs.highlightAuto(newCode).language
- const languageMode =
- LANGUAGE_MODE_HASH[detectedLanguage] || LANGUAGE_NAME_HASH[detectedLanguage]
-
- if (languageMode) {
- this.setState({ language: languageMode.mime || languageMode.mode })
- }
- } else {
- this.setState({ language: props.config.language })
- }
- },
- ms('300ms'),
- { trailing: true }
- )
-
render() {
- const config = { ...DEFAULT_SETTINGS, ...this.props.config }
- const options = {
- lineNumbers: config.lineNumbers,
- mode: this.state.language || 'plaintext',
- theme: config.theme,
- scrollBarStyle: null,
- viewportMargin: Infinity,
- lineWrapping: true,
- extraKeys: {
- 'Shift-Tab': 'indentLess'
- }
- }
- const backgroundImage =
- (this.props.config.backgroundImage && this.props.config.backgroundImageSelection) ||
- this.props.config.backgroundImage
-
- // set content to spinner if loading, else editor
- let content = (
-
-
(this.exportContainerNode = ele)}>
- {content}
-
+
+
+
+
-
+
)
}
}
-export default Carbon
+export default DragDropContext(HTML5Backend)(Carbon)
diff --git a/components/CodeWindow.js b/components/CodeWindow.js
new file mode 100644
index 0000000..4d95277
--- /dev/null
+++ b/components/CodeWindow.js
@@ -0,0 +1,280 @@
+import React, { PureComponent } from 'react'
+import * as hljs from 'highlight.js'
+import Spinner from 'react-spinner'
+import ResizeObserver from 'resize-observer-polyfill'
+import debounce from 'lodash.debounce'
+import ms from 'ms'
+
+import WindowControls from '../components/WindowControls'
+import Watermark from '../components/svg/Watermark'
+import CodeMirror from '../lib/react-codemirror'
+import { COLORS, LANGUAGE_MODE_HASH, LANGUAGE_NAME_HASH, DEFAULT_SETTINGS } from '../lib/constants'
+
+class CodeWindow extends PureComponent {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ loading: true,
+ language: props.config.language
+ }
+
+ this.handleLanguageChange = this.handleLanguageChange.bind(this)
+ this.handleTitleBarChange = this.handleTitleBarChange.bind(this)
+ this.codeUpdated = this.codeUpdated.bind(this)
+ }
+
+ componentDidMount() {
+ this.setState({
+ loading: false
+ })
+
+ this.handleLanguageChange(this.props.children)
+
+ const ro = new ResizeObserver(entries => {
+ const cr = entries[0].contentRect
+ this.props.onAspectRatioChange(cr.width / cr.height)
+ })
+ ro.observe(this.exportContainerNode)
+ }
+
+ componentWillReceiveProps(newProps) {
+ // TODO use getDerivedStateFromProps() on React@16.3
+ this.handleLanguageChange(newProps.children, { customProps: newProps })
+ }
+
+ codeUpdated(newCode) {
+ this.handleLanguageChange(newCode)
+ this.props.updateCode(newCode)
+ }
+
+ handleTitleBarChange(newTitle) {
+ this.props.updateTitleBar(newTitle)
+ }
+
+ handleLanguageChange = debounce(
+ (newCode, config) => {
+ const props = (config && config.customProps) || this.props
+
+ if (props.config.language === 'auto') {
+ // try to set the language
+ const detectedLanguage = hljs.highlightAuto(newCode).language
+ const languageMode =
+ LANGUAGE_MODE_HASH[detectedLanguage] || LANGUAGE_NAME_HASH[detectedLanguage]
+
+ if (languageMode) {
+ this.setState({ language: languageMode.mime || languageMode.mode })
+ }
+ } else {
+ this.setState({ language: props.config.language })
+ }
+ },
+ ms('300ms'),
+ { trailing: true }
+ )
+
+ render() {
+ const config = { ...DEFAULT_SETTINGS, ...this.props.config }
+ const options = {
+ lineNumbers: config.lineNumbers,
+ mode: this.state.language || 'plaintext',
+ theme: config.theme,
+ scrollBarStyle: null,
+ viewportMargin: Infinity,
+ lineWrapping: true,
+ extraKeys: {
+ 'Shift-Tab': 'indentLess'
+ }
+ }
+ const backgroundImage =
+ (this.props.config.backgroundImage && this.props.config.backgroundImageSelection) ||
+ this.props.config.backgroundImage
+
+ // set content to spinner if loading, else editor
+ let content = (
+
+
+
+
+ )
+ if (this.state.loading === false) {
+ content = (
+
+ {config.windowControls ? (
+
+ ) : null}
+
this.codeUpdated(code)}
+ value={this.props.children}
+ options={options}
+ />
+ {config.watermark && }
+
+
+
+ )
+ }
+
+ return (
+
+ {/* TODO use createRef */}
+
(this.exportContainerNode = ele)}>
+ {content}
+
+
+
+
+ )
+ }
+}
+
+export default CodeWindow
diff --git a/components/Dropdown.js b/components/Dropdown.js
index 4c71cbe..123cf9c 100644
--- a/components/Dropdown.js
+++ b/components/Dropdown.js
@@ -74,11 +74,9 @@ class Dropdown extends PureComponent {
}
}
-const renderDropdown = ({ button, color, list, minWidth, selected }) => ({
+const renderDropdown = ({ button, color, list, minWidth }) => ({
isOpen,
highlightedIndex,
- setHighlightedIndex,
- selectHighlightedItem,
selectedItem,
getRootProps,
getButtonProps,
diff --git a/components/Editor.js b/components/Editor.js
index 33b7a6e..df225cf 100644
--- a/components/Editor.js
+++ b/components/Editor.js
@@ -1,276 +1,48 @@
-// Theirs
import React from 'react'
-import HTML5Backend from 'react-dnd-html5-backend'
-import { DragDropContext } from 'react-dnd'
-import domtoimage from 'dom-to-image'
+import { Subscribe } from 'unstated'
import ReadFileDropContainer, { DATA_URL, TEXT } from 'dropperx'
-// Ours
-import Button from './Button'
-import Dropdown from './Dropdown'
-import BackgroundSelect from './BackgroundSelect'
-import Settings from './Settings'
-import Toolbar from './Toolbar'
+import EditorContainer from '../containers/Editor'
import Overlay from './Overlay'
-import Carbon from './Carbon'
-import api from '../lib/api'
-import {
- THEMES,
- THEMES_HASH,
- LANGUAGES,
- LANGUAGE_MIME_HASH,
- LANGUAGE_MODE_HASH,
- LANGUAGE_NAME_HASH,
- DEFAULT_THEME,
- DEFAULT_EXPORT_SIZE,
- COLORS,
- EXPORT_SIZES_HASH,
- DEFAULT_CODE,
- DEFAULT_SETTINGS
-} from '../lib/constants'
-import { serializeState } from '../lib/routing'
-import { getState } from '../lib/util'
+import CodeWindow from './CodeWindow'
-const saveButtonOptions = {
- button: true,
- color: '#c198fb',
- selected: { id: 'SAVE_IMAGE', name: 'Save Image' },
- list: ['png', 'svg'].map(id => ({ id, name: id.toUpperCase() }))
-}
+import { DEFAULT_CODE } from '../lib/constants'
+import { isImage } from '../lib/util'
+
+const editorContainer = [EditorContainer]
class Editor extends React.Component {
constructor(props) {
super(props)
- this.state = {
- ...DEFAULT_SETTINGS,
- uploading: false,
- code: props.content
- }
-
- this.save = this.save.bind(this)
- this.upload = this.upload.bind(this)
- this.updateSetting = this.updateSetting.bind(this)
- this.updateCode = this.updateSetting.bind(this, 'code')
- this.updateAspectRatio = this.updateSetting.bind(this, 'aspectRatio')
- this.updateTitleBar = this.updateSetting.bind(this, 'titleBar')
- this.updateTheme = this.updateTheme.bind(this)
- this.updateLanguage = this.updateLanguage.bind(this)
- this.updateBackground = this.updateBackground.bind(this)
- this.resetDefaultSettings = this.resetDefaultSettings.bind(this)
- this.getCarbonImage = this.getCarbonImage.bind(this)
- this.onDrop = this.onDrop.bind(this)
- }
-
- componentDidMount() {
- // Load from localStorage and then URL params
- this.setState({
- ...getState(localStorage),
- ...this.props.initialState
- })
- }
-
- componentDidUpdate() {
- this.props.onUpdate(this.state)
- }
-
- getCarbonImage({ format } = { format: 'png' }) {
- // if safari, get image from api
- if (
- navigator.userAgent.indexOf('Safari') !== -1 &&
- navigator.userAgent.indexOf('Chrome') === -1 &&
- format === 'png'
- ) {
- const encodedState = serializeState(this.state)
- return api.image(encodedState)
- }
-
- const node = document.getElementById('export-container')
-
- const exportSize = (EXPORT_SIZES_HASH[this.state.exportSize] || DEFAULT_EXPORT_SIZE).value
- const width = node.offsetWidth * exportSize
- const height = this.state.squaredImage
- ? node.offsetWidth * exportSize
- : node.offsetHeight * exportSize
-
- const config = {
- style: {
- transform: `scale(${exportSize})`,
- 'transform-origin': 'center',
- background: this.state.squaredImage ? this.state.backgroundColor : 'none'
- },
- filter: n => {
- // %[00 -> 19] cause failures
- if (n.innerText && n.innerText.match(/%[0-1][0-9]/)) {
- return false
- }
- if (n.className) {
- return String(n.className).indexOf('eliminateOnRender') < 0
- }
- return true
- },
- width,
- height
- }
-
- if (format === 'svg') {
- return domtoimage
- .toSvg(node, config)
- .then(dataUrl => dataUrl.split(' ').join(' '))
- .then(uri => uri.slice(uri.indexOf(',') + 1))
- .then(data => new Blob([data], { type: 'image/svg+xml' }))
- .then(data => window.URL.createObjectURL(data))
- }
-
- return domtoimage.toBlob(node, config).then(blob => window.URL.createObjectURL(blob))
- }
-
- updateSetting(key, value) {
- this.setState({ [key]: value })
+ this.renderPane = this.renderPane.bind(this)
}
- save({ id: format = 'png' }) {
- const link = document.createElement('a')
-
- return this.getCarbonImage({ format }).then(url => {
- link.download = `carbon.${format}`
- link.href = url
- document.body.appendChild(link)
- link.click()
- link.remove()
- })
- }
-
- resetDefaultSettings() {
- this.setState(DEFAULT_SETTINGS)
- localStorage.clear()
- }
-
- upload() {
- this.setState({ uploading: true })
- this.getCarbonImage({ format: 'png' })
- .then(this.props.tweet)
- .catch(console.error)
- .then(() => this.setState({ uploading: false }))
- }
-
- onDrop([file]) {
- if (isImage(file)) {
- this.setState({
- backgroundImage: file.content,
- backgroundImageSelection: null,
- backgroundMode: 'image'
- })
- } else {
- this.setState({ code: file.content, language: 'auto' })
- }
- }
-
- updateTheme(theme) {
- this.updateSetting('theme', theme.id)
- }
-
- updateLanguage(language) {
- this.updateSetting('language', language.mime || language.mode)
- }
-
- updateBackground({ photographer, ...changes } = {}) {
- if (photographer) {
- this.setState(({ code = DEFAULT_CODE }) => ({
- ...changes,
- code: code + `\n\n// Photo by ${photographer.name} on Unsplash`
- }))
- } else {
- this.setState(changes)
- }
- }
-
- render() {
+ renderPane(editor) {
return (
-
-
-
-
-
-
-
-
- {this.props.tweet && (
-
- )}
-
-
-
-
-
- {({ isOver, canDrop }) => (
-
-
- {this.state.code != null ? this.state.code : DEFAULT_CODE}
-
-
- )}
-
-
-
-
+
+ {({ isOver, canDrop }) => (
+
+
+ {editor.state.code != null ? editor.state.code : DEFAULT_CODE}
+
+
+ )}
+
)
}
-}
-function isImage(file) {
- return file.type.split('/')[0] === 'image'
+ render() {
+ return
{this.renderPane}
+ }
}
function readAs(file) {
@@ -280,8 +52,4 @@ function readAs(file) {
return TEXT
}
-Editor.defaultProps = {
- onUpdate: () => {}
-}
-
-export default DragDropContext(HTML5Backend)(Editor)
+export default Editor
diff --git a/components/Meta.js b/components/Meta.js
index 3d23303..c741f38 100644
--- a/components/Meta.js
+++ b/components/Meta.js
@@ -1,3 +1,4 @@
+import React from 'react'
import Head from 'next/head'
import { THEMES } from '../lib/constants'
import Reset from './style/Reset'
diff --git a/components/Toolbar.js b/components/Toolbar.js
index 464c50f..91ee4a5 100644
--- a/components/Toolbar.js
+++ b/components/Toolbar.js
@@ -1,31 +1,105 @@
import React from 'react'
+import { Subscribe } from 'unstated'
-const Toolbar = props => (
-
- {props.children}
-
-
-)
+ list={LANGUAGES}
+ onChange={editor.updateLanguage}
+ />
+
+
+
+ {/* TODO don't set container function if no prop */}
+ {editor.upload && (
+
+ )}
+
+
+
+
+ )
+}
export default Toolbar
diff --git a/containers/Editor.js b/containers/Editor.js
new file mode 100644
index 0000000..44f6d4e
--- /dev/null
+++ b/containers/Editor.js
@@ -0,0 +1,168 @@
+// Theirs
+import { Container } from 'unstated'
+import domtoimage from 'dom-to-image'
+
+// Ours
+import api from '../lib/api'
+import {
+ DEFAULT_EXPORT_SIZE,
+ EXPORT_SIZES_HASH,
+ DEFAULT_CODE,
+ DEFAULT_SETTINGS
+} from '../lib/constants'
+import { serializeState } from '../lib/routing'
+import { getState, isImage } from '../lib/util'
+
+class EditorContainer extends Container {
+ constructor(props = {}) {
+ super(props)
+ this.state = {
+ ...DEFAULT_SETTINGS,
+ uploading: false,
+ code: props.content
+ }
+
+ this.save = this.save.bind(this)
+ this.upload = this.upload.bind(this)
+ this.updateSetting = this.updateSetting.bind(this)
+ this.updateCode = this.updateSetting.bind(this, 'code')
+ this.updateAspectRatio = this.updateSetting.bind(this, 'aspectRatio')
+ this.updateTitleBar = this.updateSetting.bind(this, 'titleBar')
+ this.updateTheme = this.updateTheme.bind(this)
+ this.updateLanguage = this.updateLanguage.bind(this)
+ this.updateBackground = this.updateBackground.bind(this)
+ this.resetDefaultSettings = this.resetDefaultSettings.bind(this)
+ this.getCarbonImage = this.getCarbonImage.bind(this)
+ this.handleDroppedFile = this.handleDroppedFile.bind(this)
+ }
+
+ componentDidMount() {
+ // Load from localStorage and then URL params
+ this.setState({
+ ...getState(localStorage),
+ ...this.props.initialState
+ })
+ }
+
+ componentDidUpdate() {
+ this.props.onUpdate(this.state)
+ }
+
+ getCarbonImage({ format } = { format: 'png' }) {
+ // if safari, get image from api
+ if (
+ navigator.userAgent.indexOf('Safari') !== -1 &&
+ navigator.userAgent.indexOf('Chrome') === -1 &&
+ format === 'png'
+ ) {
+ const encodedState = serializeState(this.state)
+ return api.image(encodedState)
+ }
+
+ const node = document.getElementById('export-container')
+
+ const exportSize = (EXPORT_SIZES_HASH[this.state.exportSize] || DEFAULT_EXPORT_SIZE).value
+ const width = node.offsetWidth * exportSize
+ const height = this.state.squaredImage
+ ? node.offsetWidth * exportSize
+ : node.offsetHeight * exportSize
+
+ const config = {
+ style: {
+ transform: `scale(${exportSize})`,
+ 'transform-origin': 'center',
+ background: this.state.squaredImage ? this.state.backgroundColor : 'none'
+ },
+ filter: n => {
+ // %[00 -> 19] cause failures
+ if (n.innerText && n.innerText.match(/%[0-1][0-9]/)) {
+ return false
+ }
+ if (n.className) {
+ return String(n.className).indexOf('eliminateOnRender') < 0
+ }
+ return true
+ },
+ width,
+ height
+ }
+
+ if (format === 'svg') {
+ return domtoimage
+ .toSvg(node, config)
+ .then(dataUrl => dataUrl.split(' ').join(' '))
+ .then(uri => uri.slice(uri.indexOf(',') + 1))
+ .then(data => new Blob([data], { type: 'image/svg+xml' }))
+ .then(data => window.URL.createObjectURL(data))
+ }
+
+ return domtoimage.toBlob(node, config).then(blob => window.URL.createObjectURL(blob))
+ }
+
+ updateSetting(key, value) {
+ this.setState({ [key]: value })
+ }
+
+ save({ id: format = 'png' }) {
+ const link = document.createElement('a')
+
+ return this.getCarbonImage({ format }).then(url => {
+ link.download = `carbon.${format}`
+ link.href = url
+ document.body.appendChild(link)
+ link.click()
+ link.remove()
+ })
+ }
+
+ resetDefaultSettings() {
+ this.setState(DEFAULT_SETTINGS)
+ localStorage.clear()
+ }
+
+ upload() {
+ this.setState({ uploading: true })
+ this.getCarbonImage({ format: 'png' })
+ .then(this.props.tweet)
+ // eslint-disable-next-line
+ .catch(console.error)
+ .then(() => this.setState({ uploading: false }))
+ }
+
+ handleDroppedFile([file]) {
+ if (isImage(file)) {
+ this.setState({
+ backgroundImage: file.content,
+ backgroundImageSelection: null,
+ backgroundMode: 'image'
+ })
+ } else {
+ this.setState({ code: file.content, language: 'auto' })
+ }
+ }
+
+ updateTheme(theme) {
+ this.updateSetting('theme', theme.id)
+ }
+
+ updateLanguage(language) {
+ this.updateSetting('language', language.mime || language.mode)
+ }
+
+ updateBackground({ photographer, ...changes } = {}) {
+ if (photographer) {
+ this.setState(({ code = DEFAULT_CODE }) => ({
+ ...changes,
+ code: code + `\n\n// Photo by ${photographer.name} on Unsplash`
+ }))
+ } else {
+ this.setState(changes)
+ }
+ }
+}
+
+EditorContainer.defaultProps = {
+ onUpdate: () => {}
+}
+
+export default EditorContainer
diff --git a/cypress/integration/background-color-spec.js b/cypress/integration/background-color-spec.js
index 01cfe7a..9d51b79 100644
--- a/cypress/integration/background-color-spec.js
+++ b/cypress/integration/background-color-spec.js
@@ -56,7 +56,7 @@ describe('background color', () => {
const pink = 'ff00ff'
openPicker()
- .find(`input[value="FF0000"]`)
+ .find('input[value="FF0000"]')
.clear()
.type(`${pink}{enter}`)
closePicker()
diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js
index fd170fb..bbfbd1b 100644
--- a/cypress/plugins/index.js
+++ b/cypress/plugins/index.js
@@ -11,7 +11,7 @@
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
-module.exports = (on, config) => {
+module.exports = (/* on, config */) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}
diff --git a/handlers/image.js b/handlers/image.js
index 2ca2cf6..c9199c2 100644
--- a/handlers/image.js
+++ b/handlers/image.js
@@ -33,6 +33,7 @@ module.exports = browser => async (req, res) => {
res.status(200).json({ dataUrl })
} catch (e) {
+ // eslint-disable-next-line
console.error(e)
res.status(500).send()
} finally {
diff --git a/handlers/twitter.js b/handlers/twitter.js
index d1b0599..acc7526 100644
--- a/handlers/twitter.js
+++ b/handlers/twitter.js
@@ -29,6 +29,7 @@ const respondFail = (res, err) => {
return res.status(420).send()
}
+ // eslint-disable-next-line
console.error(`Error: ${err.message || JSON.stringify(err, null, 2)}`)
return res.status(500).send()
}
diff --git a/lib/custom/modes/apache.js b/lib/custom/modes/apache.js
index 1d12e03..86da57e 100644
--- a/lib/custom/modes/apache.js
+++ b/lib/custom/modes/apache.js
@@ -1,3 +1,4 @@
+/* eslint-disable */
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Apache mode by gloony
diff --git a/lib/custom/modes/elixir.js b/lib/custom/modes/elixir.js
index abeff3c..0d16ff8 100644
--- a/lib/custom/modes/elixir.js
+++ b/lib/custom/modes/elixir.js
@@ -1,4 +1,5 @@
+/* eslint-disable */
import CodeMirror from 'codemirror'
// Require Codemirror elixir mode from npm modules and register it here
-import registerElixirMode from 'codemirror-mode-elixir'
+export * from 'codemirror-mode-elixir'
diff --git a/lib/custom/modes/graphql.js b/lib/custom/modes/graphql.js
index fdb1f8a..9545e0c 100644
--- a/lib/custom/modes/graphql.js
+++ b/lib/custom/modes/graphql.js
@@ -1,2 +1,3 @@
+/* eslint-disable */
import CodeMirror from 'codemirror'
import 'codemirror-graphql/mode'
diff --git a/lib/custom/modes/nimrod.js b/lib/custom/modes/nimrod.js
index 8a4b681..95ec81c 100755
--- a/lib/custom/modes/nimrod.js
+++ b/lib/custom/modes/nimrod.js
@@ -1,3 +1,4 @@
+/* eslint-disable */
const CodeMirror = require('codemirror')
CodeMirror.defineMode('nimrod', function(conf, parserConf) {
diff --git a/lib/customDomToImage.js b/lib/customDomToImage.js
index ebfda53..a06de93 100644
--- a/lib/customDomToImage.js
+++ b/lib/customDomToImage.js
@@ -1,3 +1,4 @@
+/* eslint-disable */
;(function(global) {
'use strict'
diff --git a/lib/util.js b/lib/util.js
index 2738693..91b36ff 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -36,3 +36,7 @@ export const fileToDataURL = blob =>
reader.onload = e => res(e.target.result)
reader.readAsDataURL(blob)
})
+
+export function isImage(file) {
+ return file.type.split('/')[0] === 'image'
+}
diff --git a/package.json b/package.json
index 3bf4fc5..4c0c917 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
"test": "npm run cy:run --",
"deploy": "now --public --docker -e NODE_ENV=production",
"prettier": "prettier --config .prettierrc --write *.js {components,handlers,lib,pages}/*.js",
- "lint": "prettier --config .prettierrc *.js {components,handlers,lib,pages}/*.js",
+ "lint": "eslint .",
"precommit": "npm run contrib:build && git add README.md && lint-staged",
"contrib:add": "all-contributors add",
"contrib:build": "all-contributors generate",
@@ -23,13 +23,11 @@
"codemirror": "^5.36.0",
"codemirror-graphql": "^0.6.12",
"codemirror-mode-elixir": "^1.1.1",
- "cross-env": "^5.1.3",
"dom-to-image": "^2.5.2",
"downshift": "^1.28.0",
"dropperx": "^0.1.0",
"express": "^4.16.2",
- "form-data": "^2.2.0",
- "graphql": "^0.13.2",
+ "graphql": "^0.11.7",
"highlight.js": "^9.12.0",
"history": "^4.7.2",
"isomorphic-fetch": "^2.2.1",
@@ -50,18 +48,22 @@
"react-dnd-html5-backend": "^2.4.1",
"react-dom": "16.2.0",
"react-image-crop": "^3.0.9",
- "react-spinkit": "^3.0.0",
"react-spinner": "^0.2.7",
"react-syntax-highlight": "^15.3.1",
"resize-observer-polyfill": "^1.5.0",
"tohash": "^1.0.2",
"twitter": "^1.7.1",
- "unsplash-js": "^4.8.0"
+ "unsplash-js": "^4.8.0",
+ "unstated": "^2.0.2"
},
"devDependencies": {
"@zeit/next-css": "^0.1.5",
"all-contributors-cli": "^4.7.0",
+ "babel-eslint": "8",
"cypress": "^2.1.0",
+ "eslint": "^4.19.1",
+ "eslint-plugin-import": "^2.11.0",
+ "eslint-plugin-react": "^7.7.0",
"hex2rgb": "^2.2.0",
"husky": "^0.14.3",
"lint-staged": "^7.0.4",
diff --git a/pages/_document.js b/pages/_document.js
index c11f0d5..f7d475e 100644
--- a/pages/_document.js
+++ b/pages/_document.js
@@ -1,3 +1,4 @@
+import React from 'react'
import Document, { Head, Main, NextScript } from 'next/document'
export default class extends Document {
diff --git a/pages/about.js b/pages/about.js
index 9e36e61..2e4b528 100644
--- a/pages/about.js
+++ b/pages/about.js
@@ -1,3 +1,4 @@
+import React from 'react'
import Page from '../components/Page'
import { COLORS } from '../lib/constants'
diff --git a/pages/index.js b/pages/index.js
index 0440ee6..d13526d 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -2,7 +2,7 @@
import React from 'react'
// Ours
-import Editor from '../components/Editor'
+import Carbon from '../components/Carbon'
import Page from '../components/Page'
import api from '../lib/api'
import { getQueryStringState, updateQueryString } from '../lib/routing'
@@ -23,6 +23,7 @@ class Index extends React.Component {
return { content, initialState }
}
} catch (e) {
+ // eslint-disable-next-line
console.log(e)
}
return { initialState }
@@ -31,7 +32,7 @@ class Index extends React.Component {
render() {
return (