diff --git a/components/Editor.js b/components/Editor.js
index 518869b..a7a4c34 100644
--- a/components/Editor.js
+++ b/components/Editor.js
@@ -45,13 +45,13 @@ class Editor extends React.Component {
this.state = {
...DEFAULT_SETTINGS,
preset: DEFAULT_PRESET_ID,
+ highlights: {},
loading: true
}
this.export = this.export.bind(this)
this.upload = this.upload.bind(this)
this.updateSetting = this.updateSetting.bind(this)
- this.updateTheme = this.updateTheme.bind(this)
this.updateLanguage = this.updateLanguage.bind(this)
this.updateBackground = this.updateBackground.bind(this)
this.resetDefaultSettings = this.resetDefaultSettings.bind(this)
@@ -86,7 +86,7 @@ class Editor extends React.Component {
newState.language = unescapeHtml(newState.language)
}
- this.updateState(newState)
+ this.setState(newState)
this.isSafari =
window.navigator &&
@@ -112,7 +112,8 @@ class Editor extends React.Component {
// if safari, get image from api
const isPNG = format !== 'svg'
if (this.context.image && this.isSafari && isPNG) {
- const encodedState = serializeState(this.state)
+ const { highlights, ...state } = this.state
+ const encodedState = serializeState({ ...state, ...highlights })
return this.context.image(encodedState)
}
@@ -239,10 +240,6 @@ class Editor extends React.Component {
}
}
- updateTheme(theme) {
- this.updateSetting('theme', theme)
- }
-
updateLanguage(language) {
this.updateSetting('language', language.mime || language.mode)
}
@@ -271,6 +268,7 @@ class Editor extends React.Component {
render() {
const {
theme,
+ highlights,
language,
backgroundColor,
backgroundImage,
@@ -284,7 +282,13 @@ class Editor extends React.Component {
return (
-
+
import('./ThemeCreate'), {
loading: () => null
@@ -40,13 +42,15 @@ const ThemeItem = ({ children, item, isSelected, onClick }) => (
const themeIcon =
+const getCustomName = themes =>
+ `Custom Theme ${themes.filter(({ name }) => name.startsWith('Custom Theme')).length + 1}`
+
class Themes extends React.PureComponent {
selectedTheme = DEFAULT_THEME
state = {
themes: THEMES,
preset: this.props.theme,
- highlights: {},
name: 'Custom Theme',
selected: null
}
@@ -54,36 +58,67 @@ class Themes extends React.PureComponent {
dropdown = React.createRef()
componentDidMount() {
+ const { queryState } = getRouteState(this.props.router)
+
+ const queryHighlights = queryState
+ ? Object.keys(queryState)
+ .filter(key => HIGHLIGHT_KEYS.includes(key))
+ .reduce((obj, key) => ({ ...obj, [key]: queryState[key] }), {})
+ : {}
+
const storedThemes = getThemes(localStorage) || []
this.setState(({ themes }) => {
const newThemes = [...storedThemes, ...themes]
- const name = `Custom Theme ${newThemes.filter(({ name }) => name.startsWith('Custom Theme'))
- .length + 1}`
+ const name = getCustomName(newThemes)
this.selectedTheme = newThemes.find(({ id }) => id === this.props.theme) || DEFAULT_THEME
+ const highlights = {
+ ...this.selectedTheme.highlights,
+ ...queryHighlights
+ }
+
+ this.props.onChange('highlights', highlights)
+
return {
themes: newThemes,
- highlights: this.selectedTheme.highlights,
+ highlights,
name
}
})
}
- applyPreset = preset =>
- this.setState(({ themes }) => ({
- preset,
- highlights: themes.find(({ id }) => id === preset).highlights
- }))
+ componentDidUpdate(prevProps) {
+ const { isVisible, theme, onChange } = this.props
+ const { themes } = this.state
+
+ if (prevProps.isVisible && !isVisible) {
+ this.setState({ name: getCustomName(themes) })
+ onChange('highlights', themes.find(({ id }) => id === theme).highlights)
+ }
+ }
+
+ applyPreset = preset => {
+ this.setState(({ themes }) => {
+ this.props.onChange('highlights', themes.find(({ id }) => id === preset).highlights)
+ return {
+ preset
+ }
+ })
+ }
handleChange = ({ id }) => {
+ const { theme, toggleVisibility, onChange } = this.props
+ const { themes } = this.state
+
if (id === 'create') {
- this.props.toggleVisibility()
+ toggleVisibility()
this.dropdown.current.closeMenu()
} else {
- this.props.updateTheme(id)
+ onChange('theme', id)
+ onChange('highlights', themes.find(({ id }) => id === theme).highlights)
}
}
@@ -95,11 +130,9 @@ class Themes extends React.PureComponent {
}))
updateHighlight = ({ rgb }) =>
- this.setState({
- highlights: {
- ...this.state.highlights,
- [this.state.selected]: stringifyRGBA(rgb)
- }
+ this.props.onChange('highlights', {
+ ...this.props.highlights,
+ [this.state.selected]: stringifyRGBA(rgb)
})
removeTheme = id => event => {
@@ -112,14 +145,16 @@ class Themes extends React.PureComponent {
saveThemes(localStorage, newThemes.filter(({ custom }) => custom))
if (this.props.theme === id) {
- this.props.updateTheme(DEFAULT_THEME.id)
+ this.props.onChange('theme', DEFAULT_THEME.id)
+ this.props.onChange('highlights', DEFAULT_THEME.highlights)
} else {
this.setState({ themes: newThemes })
}
}
createTheme = () => {
- const { themes, name, highlights } = this.state
+ const { highlights } = this.props
+ const { themes, name } = this.state
const id = `theme:${generateId()}`
@@ -134,14 +169,14 @@ class Themes extends React.PureComponent {
saveThemes(localStorage, customThemes)
- this.props.updateTheme(id)
+ this.props.onChange('theme', id)
}
itemWrapper = props =>
render() {
- const { theme, isVisible, toggleVisibility } = this.props
- const { name, themes, highlights, selected, preset } = this.state
+ const { theme, isVisible, toggleVisibility, highlights } = this.props
+ const { name, themes, selected, preset } = this.state
const dropdownValue = isVisible ? { name } : { id: theme, name: this.selectedTheme.name }
@@ -255,4 +290,4 @@ class Themes extends React.PureComponent {
}
}
-export default managePopout(Themes)
+export default managePopout(withRouter(Themes))
diff --git a/lib/routing.js b/lib/routing.js
index f4948f5..5b7022d 100644
--- a/lib/routing.js
+++ b/lib/routing.js
@@ -35,7 +35,19 @@ const mappings = [
{ field: 'wm:watermark', type: 'bool' },
{ field: 'copy', type: 'bool' },
{ field: 'readonly', type: 'bool' },
- { field: 'id' }
+ { field: 'id' },
+ { field: 'text' },
+ { field: 'meta' },
+ { field: 'tbg:background' },
+ { field: 'var:variable' },
+ { field: 'attr:attribute' },
+ { field: 'def:definition' },
+ { field: 'kw:keyword' },
+ { field: 'op:operator' },
+ { field: 'prop:property' },
+ { field: 'num:number' },
+ { field: 'str:string' },
+ { field: 'cmt:comment' }
]
const reverseMappings = mappings.map(mapping =>