mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-04-09 13:36:57 +00:00
Use fira code in editor (#695)
Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
This commit is contained in:
parent
b3288a6666
commit
8ce344512c
19 changed files with 311 additions and 113 deletions
|
@ -56,6 +56,7 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
|||
- Code blocks with 'vega-lite' as language are rendered as [vega-lite diagrams](https://vega.github.io/vega-lite/examples/).
|
||||
- Markdown files can be imported into an existing note directly from the editor.
|
||||
- The table button in the toolbar opens an overlay where the user can choose the number of columns and rows
|
||||
- A toggle in the editor preferences for turning ligatures on and off.
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -70,6 +71,7 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
|||
- Use KaTeX instead of MathJax. ([Why?](https://community.codimd.org/t/frequently-asked-questions/190))
|
||||
- The dark-mode is also applied to the read-only-view and can be toggled from there.
|
||||
- Access tokens for the CLI and 3rd-party-clients can be managed in the user profile.
|
||||
- Change editor font to "Fira Code"
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -49,9 +49,9 @@
|
|||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "4.2.1",
|
||||
"fast-deep-equal": "3.1.3",
|
||||
"firacode": "5.2.0",
|
||||
"flowchart.js": "1.15.0",
|
||||
"fontsource-source-sans-pro": "3.1.5",
|
||||
"fontsource-source-code-pro": "3.1.5",
|
||||
"fork-awesome": "1.1.7",
|
||||
"highlight.js": "10.4.1",
|
||||
"i18next": "19.8.4",
|
||||
|
|
|
@ -389,11 +389,29 @@
|
|||
},
|
||||
"preferences": {
|
||||
"title": "Preferences",
|
||||
"theme": "Editor theme",
|
||||
"keyMap": "Keymap",
|
||||
"indentWithTabs": "Tab character",
|
||||
"indentUnit": "Tab size (when using spaces)",
|
||||
"spellcheck": "Spell checking"
|
||||
"theme": {
|
||||
"label": "Editor theme",
|
||||
"one-dark": "Dark",
|
||||
"neat": "Light"
|
||||
},
|
||||
"keyMap": {
|
||||
"label": "Keymap",
|
||||
"sublime": "Sublime",
|
||||
"emacs": "Emacs",
|
||||
"vim": "Vim"
|
||||
},
|
||||
"indentWithTabs": {
|
||||
"label": "Tab character",
|
||||
"on": "Tabs",
|
||||
"off": "Spaces"
|
||||
},
|
||||
"indentUnit": "Number of spaces per tab",
|
||||
"spellcheck": {
|
||||
"label": "Spell checking"
|
||||
},
|
||||
"ligatures": {
|
||||
"label": "Show ligatures"
|
||||
}
|
||||
}
|
||||
},
|
||||
"embeddings": {
|
||||
|
@ -413,6 +431,8 @@
|
|||
}
|
||||
},
|
||||
"common": {
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"import": "Import",
|
||||
"export": "Export",
|
||||
"refresh": "Refresh",
|
||||
|
|
|
@ -11,11 +11,23 @@
|
|||
@import '../../../../node_modules/codemirror/theme/neat';
|
||||
@import './one-dark';
|
||||
@import 'hints';
|
||||
@import '../../../../node_modules/firacode/distr/fira_code.css';
|
||||
|
||||
.CodeMirror {
|
||||
font-family: "Source Code Pro", "Twemoji Mozilla", Consolas, monaco, monospace;
|
||||
font-family: "Fira Code", "Twemoji Mozilla", Consolas, monaco, monospace;
|
||||
letter-spacing: 0.025em;
|
||||
line-height: 1.25;
|
||||
font-size: 18px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.no-ligatures .CodeMirror {
|
||||
//These two properties must be set separately because otherwise node-scss breaks.
|
||||
.CodeMirror-line, .CodeMirror-line-like {
|
||||
font-feature-settings: inherit;
|
||||
}
|
||||
.CodeMirror-line, .CodeMirror-line-like {
|
||||
font-variant-ligatures: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ export const EditorPane: React.FC<EditorPaneProps & ScrollProps> = ({ onContentC
|
|||
const [editor, setEditor] = useState<Editor>()
|
||||
const [statusBarInfo, setStatusBarInfo] = useState<StatusBarInfo>(defaultState)
|
||||
const editorPreferences = useSelector((state: ApplicationState) => state.editorConfig.preferences, equal)
|
||||
const ligaturesEnabled = useSelector((state: ApplicationState) => state.editorConfig.ligatures, equal)
|
||||
|
||||
const lastScrollPosition = useRef<number>()
|
||||
const [editorScroll, setEditorScroll] = useState<ScrollInfo>()
|
||||
|
@ -163,7 +164,7 @@ export const EditorPane: React.FC<EditorPaneProps & ScrollProps> = ({ onContentC
|
|||
editor={editor}
|
||||
/>
|
||||
<ControlledCodeMirror
|
||||
className="overflow-hidden w-100 flex-fill"
|
||||
className={`overflow-hidden w-100 flex-fill ${ligaturesEnabled ? '' : 'no-ligatures'}`}
|
||||
value={content}
|
||||
options={codeMirrorOptions}
|
||||
onChange={onChange}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { EditorConfiguration } from 'codemirror'
|
||||
import equal from "fast-deep-equal"
|
||||
import React, { ChangeEvent, useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { ApplicationState } from '../../../../../redux'
|
||||
import { mergeEditorPreferences } from '../../../../../redux/editor/methods'
|
||||
import { EditorPreferenceInput, EditorPreferenceInputType } from './editor-preference-input'
|
||||
import { EditorPreferenceProperty } from './editor-preference-property'
|
||||
|
||||
export interface EditorPreferenceBooleanProps {
|
||||
property: EditorPreferenceProperty
|
||||
}
|
||||
|
||||
export const EditorPreferenceBooleanProperty: React.FC<EditorPreferenceBooleanProps> = ({ property }) => {
|
||||
const preference = useSelector((state: ApplicationState) => state.editorConfig.preferences[property]?.toString() || '', equal)
|
||||
|
||||
const { t } = useTranslation()
|
||||
const selectItem = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
|
||||
const selectedItem: boolean = event.target.value === 'true'
|
||||
|
||||
mergeEditorPreferences({
|
||||
[property]: selectedItem
|
||||
} as EditorConfiguration)
|
||||
}, [property])
|
||||
|
||||
const i18nPrefix = `editor.modal.preferences.${property}`
|
||||
|
||||
return (
|
||||
<EditorPreferenceInput onChange={selectItem} property={property} type={EditorPreferenceInputType.SELECT} value={preference}>
|
||||
<option value={'true'}>
|
||||
{t(`${i18nPrefix}.on`)}
|
||||
</option>
|
||||
<option value={'false'}>
|
||||
{t(`${i18nPrefix}.off`)}
|
||||
</option>
|
||||
</EditorPreferenceInput>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import React from 'react'
|
||||
import { Form } from 'react-bootstrap'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
|
||||
export enum EditorPreferenceInputType {
|
||||
SELECT,
|
||||
BOOLEAN,
|
||||
NUMBER
|
||||
}
|
||||
|
||||
export interface EditorPreferenceInputProps {
|
||||
property: string
|
||||
type: EditorPreferenceInputType
|
||||
onChange: React.ChangeEventHandler<HTMLSelectElement>
|
||||
value?: string | number | string[]
|
||||
}
|
||||
|
||||
export const EditorPreferenceInput: React.FC<EditorPreferenceInputProps> = ({ property, type, onChange, value, children }) => {
|
||||
useTranslation()
|
||||
return (
|
||||
<Form.Group controlId={`editor-pref-${property}`}>
|
||||
<Form.Label>
|
||||
<Trans i18nKey={`editor.modal.preferences.${property}${type===EditorPreferenceInputType.NUMBER ? '' : '.label'}`}/>
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
as={type === EditorPreferenceInputType.NUMBER ? 'input' : 'select'}
|
||||
size='sm'
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
type={type === EditorPreferenceInputType.NUMBER ? 'number' : ''}>
|
||||
{children}
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import React, { ChangeEvent, useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { ApplicationState } from '../../../../../redux'
|
||||
import { setEditorLigatures } from '../../../../../redux/editor/methods'
|
||||
import { EditorPreferenceInput, EditorPreferenceInputType } from './editor-preference-input'
|
||||
|
||||
export const EditorPreferenceLigaturesSelect: React.FC = () => {
|
||||
const ligaturesEnabled = useSelector((state: ApplicationState) => Boolean(state.editorConfig.ligatures).toString())
|
||||
const saveLigatures = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
|
||||
const ligaturesActivated: boolean = event.target.value === 'true'
|
||||
setEditorLigatures(ligaturesActivated)
|
||||
}, [])
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<EditorPreferenceInput onChange={saveLigatures} value={ligaturesEnabled} property={"ligatures"}
|
||||
type={EditorPreferenceInputType.BOOLEAN}>
|
||||
<option value='true'>{t(`common.yes`)}</option>
|
||||
<option value='false'>{t(`common.no`)}</option>
|
||||
</EditorPreferenceInput>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { EditorConfiguration } from 'codemirror'
|
||||
import equal from "fast-deep-equal"
|
||||
import React, { ChangeEvent, useCallback } from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { ApplicationState } from '../../../../../redux'
|
||||
import { mergeEditorPreferences } from '../../../../../redux/editor/methods'
|
||||
import { EditorPreferenceInput, EditorPreferenceInputType } from './editor-preference-input'
|
||||
import { EditorPreferenceProperty } from './editor-preference-property'
|
||||
|
||||
export interface EditorPreferenceNumberProps {
|
||||
property: EditorPreferenceProperty
|
||||
}
|
||||
|
||||
export const EditorPreferenceNumberProperty: React.FC<EditorPreferenceNumberProps> = ({ property }) => {
|
||||
const preference = useSelector((state: ApplicationState) => state.editorConfig.preferences[property]?.toString() || '', equal)
|
||||
|
||||
const selectItem = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
|
||||
const selectedItem: number = Number.parseInt(event.target.value)
|
||||
|
||||
mergeEditorPreferences({
|
||||
[property]: selectedItem
|
||||
} as EditorConfiguration)
|
||||
}, [property])
|
||||
|
||||
return (
|
||||
<EditorPreferenceInput onChange={selectItem} property={property} type={EditorPreferenceInputType.NUMBER} value={preference}/>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export enum EditorPreferenceProperty {
|
||||
KEYMAP = 'keyMap',
|
||||
THEME = 'theme',
|
||||
INDENT_WITH_TABS = 'indentWithTabs',
|
||||
INDENT_UNIT = 'indentUnit',
|
||||
SPELL_CHECK = 'spellcheck'
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { EditorConfiguration } from 'codemirror'
|
||||
import equal from "fast-deep-equal"
|
||||
import React, { ChangeEvent, useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { ApplicationState } from '../../../../../redux'
|
||||
import { mergeEditorPreferences } from '../../../../../redux/editor/methods'
|
||||
import { EditorPreferenceInput, EditorPreferenceInputType } from './editor-preference-input'
|
||||
import { EditorPreferenceProperty } from './editor-preference-property'
|
||||
|
||||
export interface EditorPreferenceSelectPropertyProps {
|
||||
property: EditorPreferenceProperty
|
||||
selections: string[]
|
||||
}
|
||||
|
||||
export const EditorPreferenceSelectProperty: React.FC<EditorPreferenceSelectPropertyProps> = ({ property, selections }) => {
|
||||
const preference = useSelector((state: ApplicationState) => state.editorConfig.preferences[property]?.toString() || '', equal)
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
const selectItem = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
|
||||
const selectedItem: string = event.target.value
|
||||
|
||||
mergeEditorPreferences({
|
||||
[property]: selectedItem
|
||||
} as EditorConfiguration)
|
||||
}, [property])
|
||||
|
||||
const i18nPrefix = `editor.modal.preferences.${property}`
|
||||
|
||||
return (
|
||||
<EditorPreferenceInput onChange={selectItem} property={property} type={EditorPreferenceInputType.SELECT} value={preference}>
|
||||
{selections.map(selection =>
|
||||
<option key={selection} value={selection}>
|
||||
{t(`${i18nPrefix}.${selection}`) }
|
||||
</option>)}
|
||||
</EditorPreferenceInput>
|
||||
)
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 The HedgeDoc developers (see AUTHORS file)
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { EditorConfiguration } from 'codemirror'
|
||||
import React, { ChangeEvent, useCallback, useState } from 'react'
|
||||
import { Form } from 'react-bootstrap'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
|
||||
export enum EditorPreferenceProperty {
|
||||
KEYMAP = 'keyMap',
|
||||
THEME = 'theme',
|
||||
INDENT_WITH_TABS = 'indentWithTabs',
|
||||
INDENT_UNIT = 'indentUnit',
|
||||
SPELL_CHECK= 'spellcheck'
|
||||
}
|
||||
|
||||
export interface EditorPreferenceSelectProps {
|
||||
onChange: (config: EditorConfiguration) => void
|
||||
preferences: EditorConfiguration
|
||||
property: EditorPreferenceProperty
|
||||
}
|
||||
|
||||
export const EditorPreferenceSelect: React.FC<EditorPreferenceSelectProps> = ({ property, onChange, preferences, children }) => {
|
||||
useTranslation()
|
||||
const [selected, setSelected] = useState(preferences[property])
|
||||
|
||||
const selectItem = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
|
||||
let selectedItem: string | boolean | number = event.target.value
|
||||
if (property === EditorPreferenceProperty.INDENT_UNIT) {
|
||||
selectedItem = parseInt(selectedItem)
|
||||
}
|
||||
setSelected(selectedItem)
|
||||
if (property === EditorPreferenceProperty.INDENT_WITH_TABS) {
|
||||
selectedItem = selectedItem === 'true'
|
||||
}
|
||||
onChange({
|
||||
...preferences,
|
||||
[property]: selectedItem
|
||||
})
|
||||
}, [preferences, property, setSelected, onChange])
|
||||
|
||||
return (
|
||||
<Form.Group controlId={`editor-pref-${property}`}>
|
||||
<Form.Label>
|
||||
<Trans i18nKey={`editor.modal.preferences.${property}`}/>
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
as={property === EditorPreferenceProperty.INDENT_UNIT ? 'input' : 'select'}
|
||||
size='sm'
|
||||
value={selected as string | number}
|
||||
onChange={selectItem}
|
||||
type={property === EditorPreferenceProperty.INDENT_UNIT ? 'number' : ''}>
|
||||
{ children }
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
)
|
||||
}
|
|
@ -4,26 +4,26 @@ SPDX-FileCopyrightText: 2020 The HedgeDoc developers (see AUTHORS file)
|
|||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { EditorConfiguration } from 'codemirror'
|
||||
import equal from 'fast-deep-equal'
|
||||
import React, { Fragment, useCallback, useState } from 'react'
|
||||
import equal from "fast-deep-equal"
|
||||
import React, { Fragment, useState } from 'react'
|
||||
import { Button, Form, ListGroup } from 'react-bootstrap'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { ApplicationState } from '../../../../../redux'
|
||||
import { setEditorPreferences } from '../../../../../redux/editor/methods'
|
||||
import { ForkAwesomeIcon } from '../../../../common/fork-awesome/fork-awesome-icon'
|
||||
import { CommonModal } from '../../../../common/modals/common-modal'
|
||||
import { EditorPreferenceProperty, EditorPreferenceSelect } from './editor-preference-select'
|
||||
import { ShowIf } from '../../../../common/show-if/show-if'
|
||||
import { EditorPreferenceBooleanProperty } from './editor-preference-boolean-property'
|
||||
import { EditorPreferenceInput, EditorPreferenceInputType } from './editor-preference-input'
|
||||
import { EditorPreferenceLigaturesSelect } from './editor-preference-ligatures-select'
|
||||
import { EditorPreferenceNumberProperty } from './editor-preference-number-property'
|
||||
import { EditorPreferenceProperty } from "./editor-preference-property"
|
||||
import { EditorPreferenceSelectProperty } from "./editor-preference-select-property"
|
||||
|
||||
export const EditorPreferences: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const preferences = useSelector((state: ApplicationState) => state.editorConfig.preferences, equal)
|
||||
|
||||
const sendPreferences = useCallback((newPreferences: EditorConfiguration) => {
|
||||
setEditorPreferences(newPreferences)
|
||||
}, [])
|
||||
const indentWithTabs = useSelector((state: ApplicationState) => state.editorConfig.preferences.indentWithTabs ?? false, equal)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
@ -39,32 +39,27 @@ export const EditorPreferences: React.FC = () => {
|
|||
<Form>
|
||||
<ListGroup>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceSelect onChange={sendPreferences} preferences={preferences} property={EditorPreferenceProperty.THEME}>
|
||||
<option value='one-dark'>Dark</option>
|
||||
<option value='neat'>Light</option>
|
||||
</EditorPreferenceSelect>
|
||||
<EditorPreferenceSelectProperty property={EditorPreferenceProperty.THEME} selections={['one-dark', 'neat']}/>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceSelect onChange={sendPreferences} preferences={preferences} property={EditorPreferenceProperty.KEYMAP}>
|
||||
<option value='sublime'>Sublime</option>
|
||||
<option value='emacs'>Emacs</option>
|
||||
<option value='vim'>Vim</option>
|
||||
</EditorPreferenceSelect>
|
||||
<EditorPreferenceSelectProperty property={EditorPreferenceProperty.KEYMAP} selections={['sublime', 'emacs', 'vim']}/>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceSelect onChange={sendPreferences} preferences={preferences} property={EditorPreferenceProperty.INDENT_WITH_TABS}>
|
||||
<option value='false'>Spaces</option>
|
||||
<option value='true'>Tab</option>
|
||||
</EditorPreferenceSelect>
|
||||
<EditorPreferenceBooleanProperty property={EditorPreferenceProperty.INDENT_WITH_TABS}/>
|
||||
</ListGroup.Item>
|
||||
<ShowIf condition={!indentWithTabs}>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceNumberProperty property={EditorPreferenceProperty.INDENT_UNIT}/>
|
||||
</ListGroup.Item>
|
||||
</ShowIf>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceLigaturesSelect/>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceSelect onChange={sendPreferences} preferences={preferences} property={EditorPreferenceProperty.INDENT_UNIT}/>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceSelect onChange={() => alert('This feature is not yet implemented.')} preferences={preferences} property={EditorPreferenceProperty.SPELL_CHECK}>
|
||||
<option value='off'>off</option>
|
||||
<EditorPreferenceInput onChange={() => alert('This feature is not yet implemented.')} property={EditorPreferenceProperty.SPELL_CHECK} type={EditorPreferenceInputType.SELECT}>
|
||||
<option value='off'>Off</option>
|
||||
<option value='en'>English</option>
|
||||
</EditorPreferenceSelect>
|
||||
</EditorPreferenceInput>
|
||||
</ListGroup.Item>
|
||||
</ListGroup>
|
||||
</Form>
|
||||
|
|
|
@ -37,7 +37,7 @@ export const FlowChart: React.FC<FlowChartProps> = ({ code }) => {
|
|||
'line-color': darkModeActivated ? '#ffffff' : '#000000',
|
||||
'element-color': darkModeActivated ? '#ffffff' : '#000000',
|
||||
'font-color': darkModeActivated ? '#ffffff' : '#000000',
|
||||
'font-family': 'Source Code Pro, "Twemoji Mozilla", monospace'
|
||||
'font-family': 'Source Sans Pro, "Twemoji Mozilla", monospace'
|
||||
})
|
||||
setError(false)
|
||||
} catch (error) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
EditorConfig,
|
||||
EditorConfigActionType,
|
||||
SetEditorConfigAction,
|
||||
SetEditorLigaturesAction,
|
||||
SetEditorPreferencesAction,
|
||||
SetEditorSyncScrollAction
|
||||
} from './types'
|
||||
|
@ -52,12 +53,18 @@ export const setEditorSyncScroll = (syncScroll: boolean): void => {
|
|||
store.dispatch(action)
|
||||
}
|
||||
|
||||
export const setEditorPreferences = (preferences: EditorConfiguration): void => {
|
||||
export const setEditorLigatures = (ligatures: boolean): void => {
|
||||
const action: SetEditorLigaturesAction = {
|
||||
type: EditorConfigActionType.SET_LIGATURES,
|
||||
ligatures: ligatures
|
||||
}
|
||||
store.dispatch(action);
|
||||
}
|
||||
|
||||
export const mergeEditorPreferences = (preferences: EditorConfiguration): void => {
|
||||
const action: SetEditorPreferencesAction = {
|
||||
type: EditorConfigActionType.SET_EDITOR_PREFERENCES,
|
||||
preferences: {
|
||||
...preferences
|
||||
}
|
||||
type: EditorConfigActionType.MERGE_EDITOR_PREFERENCES,
|
||||
preferences: preferences
|
||||
}
|
||||
store.dispatch(action)
|
||||
}
|
||||
|
|
|
@ -12,12 +12,14 @@ import {
|
|||
EditorConfigActions,
|
||||
EditorConfigActionType,
|
||||
SetEditorConfigAction,
|
||||
SetEditorLigaturesAction,
|
||||
SetEditorPreferencesAction,
|
||||
SetEditorSyncScrollAction
|
||||
} from './types'
|
||||
|
||||
const initialState: EditorConfig = {
|
||||
editorMode: EditorMode.BOTH,
|
||||
ligatures: true,
|
||||
syncScroll: true,
|
||||
preferences: {
|
||||
theme: 'one-dark',
|
||||
|
@ -28,7 +30,7 @@ const initialState: EditorConfig = {
|
|||
}
|
||||
|
||||
const getInitialState = (): EditorConfig => {
|
||||
return loadFromLocalStorage() ?? initialState
|
||||
return { ...initialState, ...loadFromLocalStorage() }
|
||||
}
|
||||
|
||||
export const EditorConfigReducer: Reducer<EditorConfig, EditorConfigActions> = (state: EditorConfig = getInitialState(), action: EditorConfigActions) => {
|
||||
|
@ -48,10 +50,19 @@ export const EditorConfigReducer: Reducer<EditorConfig, EditorConfigActions> = (
|
|||
}
|
||||
saveToLocalStorage(newState)
|
||||
return newState
|
||||
case EditorConfigActionType.SET_EDITOR_PREFERENCES:
|
||||
case EditorConfigActionType.SET_LIGATURES:
|
||||
newState = {
|
||||
...state,
|
||||
preferences: (action as SetEditorPreferencesAction).preferences
|
||||
ligatures: (action as SetEditorLigaturesAction).ligatures
|
||||
}
|
||||
saveToLocalStorage(newState)
|
||||
return newState
|
||||
case EditorConfigActionType.MERGE_EDITOR_PREFERENCES:
|
||||
newState = {
|
||||
...state,
|
||||
preferences: {
|
||||
...state.preferences, ...(action as SetEditorPreferencesAction).preferences
|
||||
}
|
||||
}
|
||||
saveToLocalStorage(newState)
|
||||
return newState
|
||||
|
|
|
@ -11,12 +11,14 @@ import { EditorMode } from '../../components/editor/app-bar/editor-view-mode'
|
|||
export enum EditorConfigActionType {
|
||||
SET_EDITOR_VIEW_MODE = 'editor/mode/set',
|
||||
SET_SYNC_SCROLL = 'editor/syncScroll/set',
|
||||
SET_EDITOR_PREFERENCES = 'editor/preferences/set'
|
||||
MERGE_EDITOR_PREFERENCES = 'editor/preferences/merge',
|
||||
SET_LIGATURES = 'editor/preferences/setLigatures'
|
||||
}
|
||||
|
||||
export interface EditorConfig {
|
||||
editorMode: EditorMode;
|
||||
syncScroll: boolean;
|
||||
ligatures: boolean
|
||||
preferences: EditorConfiguration
|
||||
}
|
||||
|
||||
|
@ -28,6 +30,10 @@ export interface SetEditorSyncScrollAction extends EditorConfigActions {
|
|||
syncScroll: boolean
|
||||
}
|
||||
|
||||
export interface SetEditorLigaturesAction extends EditorConfigActions {
|
||||
ligatures: boolean
|
||||
}
|
||||
|
||||
export interface SetEditorConfigAction extends EditorConfigActions {
|
||||
mode: EditorMode
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
@import "../../node_modules/bootstrap/scss/bootstrap";
|
||||
@import '../../node_modules/react-bootstrap-typeahead/css/Typeahead';
|
||||
@import "~fontsource-source-sans-pro/index.css";
|
||||
@import "~fontsource-source-code-pro/index.css";
|
||||
@import "fonts/twemoji/twemoji";
|
||||
@import '../../node_modules/fork-awesome/css/fork-awesome.min';
|
||||
|
||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -6869,6 +6869,11 @@ find-up@^3.0.0:
|
|||
dependencies:
|
||||
locate-path "^3.0.0"
|
||||
|
||||
firacode@5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/firacode/-/firacode-5.2.0.tgz#2eab5b4f59e3197d5e84f15a25485a88f0cd3180"
|
||||
integrity sha512-Q1SO7vibzYcT+KaohGK0ypGS58zLtO2o2UuiLvngTEhBbHQoZmZ4DAiugj0MNNpeM4jG9gM9NyusVDM3MxYP7A==
|
||||
|
||||
flat-cache@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
|
||||
|
@ -6908,11 +6913,6 @@ follow-redirects@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
|
||||
integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==
|
||||
|
||||
fontsource-source-code-pro@3.1.5:
|
||||
version "3.1.5"
|
||||
resolved "https://registry.yarnpkg.com/fontsource-source-code-pro/-/fontsource-source-code-pro-3.1.5.tgz#0f000f06dfa7220f62c64f572e5d9ee1fd087a8e"
|
||||
integrity sha512-eoYyrTaNcgrWc62w0pImfualDr2JE4SKpeGlEqV+Y34tHYbuD5jTIkzx3GrDH4eDw9KDS5wQdlnSVOj+SVy0Zw==
|
||||
|
||||
fontsource-source-sans-pro@3.1.5:
|
||||
version "3.1.5"
|
||||
resolved "https://registry.yarnpkg.com/fontsource-source-sans-pro/-/fontsource-source-sans-pro-3.1.5.tgz#575edceadf0e68603c1c74b087f4423738cce2f9"
|
||||
|
|
Loading…
Add table
Reference in a new issue