mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-29 06:15:29 -04:00
Add prettier for codestyle and re-format everything (#1294)
This commit is contained in:
parent
8b78154075
commit
0aae1f70d2
319 changed files with 4809 additions and 3936 deletions
|
@ -19,28 +19,33 @@ export interface EditorPreferenceBooleanProps {
|
|||
}
|
||||
|
||||
export const EditorPreferenceBooleanProperty: React.FC<EditorPreferenceBooleanProps> = ({ property }) => {
|
||||
const preference = useSelector((state: ApplicationState) => state.editorConfig.preferences[property]?.toString() || '', equal)
|
||||
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'
|
||||
const selectItem = useCallback(
|
||||
(event: ChangeEvent<HTMLSelectElement>) => {
|
||||
const selectedItem: boolean = event.target.value === 'true'
|
||||
|
||||
mergeEditorPreferences({
|
||||
[property]: selectedItem
|
||||
} as EditorConfiguration)
|
||||
}, [property])
|
||||
mergeEditorPreferences({
|
||||
[property]: selectedItem
|
||||
} as EditorConfiguration)
|
||||
},
|
||||
[property]
|
||||
)
|
||||
|
||||
const i18nPrefix = `editor.modal.preferences.${ 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
|
||||
onChange={selectItem}
|
||||
property={property}
|
||||
type={EditorPreferenceInputType.SELECT}
|
||||
value={preference}>
|
||||
<option value={'true'}>{t(`${i18nPrefix}.on`)}</option>
|
||||
<option value={'false'}>{t(`${i18nPrefix}.off`)}</option>
|
||||
</EditorPreferenceInput>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -20,21 +20,28 @@ export interface EditorPreferenceInputProps {
|
|||
value?: string | number | string[]
|
||||
}
|
||||
|
||||
export const EditorPreferenceInput: React.FC<EditorPreferenceInputProps> = ({ property, type, onChange, value, children }) => {
|
||||
export const EditorPreferenceInput: React.FC<EditorPreferenceInputProps> = ({
|
||||
property,
|
||||
type,
|
||||
onChange,
|
||||
value,
|
||||
children
|
||||
}) => {
|
||||
useTranslation()
|
||||
return (
|
||||
<Form.Group controlId={ `editor-pref-${ property }` }>
|
||||
<Form.Group controlId={`editor-pref-${property}`}>
|
||||
<Form.Label>
|
||||
<Trans
|
||||
i18nKey={ `editor.modal.preferences.${ property }${ type === EditorPreferenceInputType.NUMBER ? '' : '.label' }` }/>
|
||||
i18nKey={`editor.modal.preferences.${property}${type === EditorPreferenceInputType.NUMBER ? '' : '.label'}`}
|
||||
/>
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
as={ type === EditorPreferenceInputType.NUMBER ? 'input' : 'select' }
|
||||
as={type === EditorPreferenceInputType.NUMBER ? 'input' : 'select'}
|
||||
size='sm'
|
||||
value={ value }
|
||||
onChange={ onChange }
|
||||
type={ type === EditorPreferenceInputType.NUMBER ? 'number' : '' }>
|
||||
{ children }
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
type={type === EditorPreferenceInputType.NUMBER ? 'number' : ''}>
|
||||
{children}
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
)
|
||||
|
|
|
@ -11,8 +11,7 @@ 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 ligaturesEnabled = useSelector((state: ApplicationState) => Boolean(state.editorConfig.ligatures).toString())
|
||||
const saveLigatures = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
|
||||
const ligaturesActivated: boolean = event.target.value === 'true'
|
||||
setEditorLigatures(ligaturesActivated)
|
||||
|
@ -20,10 +19,13 @@ export const EditorPreferenceLigaturesSelect: React.FC = () => {
|
|||
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
|
||||
onChange={saveLigatures}
|
||||
value={ligaturesEnabled}
|
||||
property={'ligatures'}
|
||||
type={EditorPreferenceInputType.BOOLEAN}>
|
||||
<option value='true'>{t(`common.yes`)}</option>
|
||||
<option value='false'>{t(`common.no`)}</option>
|
||||
</EditorPreferenceInput>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -18,18 +18,28 @@ export interface EditorPreferenceNumberProps {
|
|||
}
|
||||
|
||||
export const EditorPreferenceNumberProperty: React.FC<EditorPreferenceNumberProps> = ({ property }) => {
|
||||
const preference = useSelector((state: ApplicationState) => state.editorConfig.preferences[property]?.toString() || '', equal)
|
||||
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)
|
||||
const selectItem = useCallback(
|
||||
(event: ChangeEvent<HTMLSelectElement>) => {
|
||||
const selectedItem: number = Number.parseInt(event.target.value)
|
||||
|
||||
mergeEditorPreferences({
|
||||
[property]: selectedItem
|
||||
} as EditorConfiguration)
|
||||
}, [property])
|
||||
mergeEditorPreferences({
|
||||
[property]: selectedItem
|
||||
} as EditorConfiguration)
|
||||
},
|
||||
[property]
|
||||
)
|
||||
|
||||
return (
|
||||
<EditorPreferenceInput onChange={ selectItem } property={ property } type={ EditorPreferenceInputType.NUMBER }
|
||||
value={ preference }/>
|
||||
<EditorPreferenceInput
|
||||
onChange={selectItem}
|
||||
property={property}
|
||||
type={EditorPreferenceInputType.NUMBER}
|
||||
value={preference}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -19,28 +19,41 @@ export interface EditorPreferenceSelectPropertyProps {
|
|||
selections: string[]
|
||||
}
|
||||
|
||||
export const EditorPreferenceSelectProperty: React.FC<EditorPreferenceSelectPropertyProps> = ({ property, selections }) => {
|
||||
const preference = useSelector((state: ApplicationState) => state.editorConfig.preferences[property]?.toString() || '', equal)
|
||||
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
|
||||
const selectItem = useCallback(
|
||||
(event: ChangeEvent<HTMLSelectElement>) => {
|
||||
const selectedItem: string = event.target.value
|
||||
|
||||
mergeEditorPreferences({
|
||||
[property]: selectedItem
|
||||
} as EditorConfiguration)
|
||||
}, [property])
|
||||
mergeEditorPreferences({
|
||||
[property]: selectedItem
|
||||
} as EditorConfiguration)
|
||||
},
|
||||
[property]
|
||||
)
|
||||
|
||||
const i18nPrefix = `editor.modal.preferences.${ 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
|
||||
onChange={selectItem}
|
||||
property={property}
|
||||
type={EditorPreferenceInputType.SELECT}
|
||||
value={preference}>
|
||||
{selections.map((selection) => (
|
||||
<option key={selection} value={selection}>
|
||||
{t(`${i18nPrefix}.${selection}`)}
|
||||
</option>
|
||||
))}
|
||||
</EditorPreferenceInput>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -11,8 +11,7 @@ import { setEditorSmartPaste } from '../../../../../redux/editor/methods'
|
|||
import { EditorPreferenceInput, EditorPreferenceInputType } from './editor-preference-input'
|
||||
|
||||
export const EditorPreferenceSmartPasteSelect: React.FC = () => {
|
||||
const smartPasteEnabled = useSelector((state: ApplicationState) => Boolean(state.editorConfig.smartPaste)
|
||||
.toString())
|
||||
const smartPasteEnabled = useSelector((state: ApplicationState) => Boolean(state.editorConfig.smartPaste).toString())
|
||||
const saveSmartPaste = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
|
||||
const smartPasteActivated: boolean = event.target.value === 'true'
|
||||
setEditorSmartPaste(smartPasteActivated)
|
||||
|
@ -21,13 +20,12 @@ export const EditorPreferenceSmartPasteSelect: React.FC = () => {
|
|||
|
||||
return (
|
||||
<EditorPreferenceInput
|
||||
onChange={ saveSmartPaste }
|
||||
value={ smartPasteEnabled }
|
||||
property={ 'smartPaste' }
|
||||
type={ EditorPreferenceInputType.BOOLEAN }
|
||||
>
|
||||
<option value='true'>{ t(`common.yes`) }</option>
|
||||
<option value='false'>{ t(`common.no`) }</option>
|
||||
onChange={saveSmartPaste}
|
||||
value={smartPasteEnabled}
|
||||
property={'smartPaste'}
|
||||
type={EditorPreferenceInputType.BOOLEAN}>
|
||||
<option value='true'>{t(`common.yes`)}</option>
|
||||
<option value='false'>{t(`common.no`)}</option>
|
||||
</EditorPreferenceInput>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -24,47 +24,55 @@ import { EditorPreferenceSmartPasteSelect } from './editor-preference-smart-past
|
|||
export const EditorPreferences: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const indentWithTabs = useSelector((state: ApplicationState) => state.editorConfig.preferences.indentWithTabs ?? false, equal)
|
||||
const indentWithTabs = useSelector(
|
||||
(state: ApplicationState) => state.editorConfig.preferences.indentWithTabs ?? false,
|
||||
equal
|
||||
)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Button variant='light' onClick={ () => setShowModal(true) } title={ t('editor.editorToolbar.preferences') }>
|
||||
<ForkAwesomeIcon icon="wrench"/>
|
||||
<Button variant='light' onClick={() => setShowModal(true)} title={t('editor.editorToolbar.preferences')}>
|
||||
<ForkAwesomeIcon icon='wrench' />
|
||||
</Button>
|
||||
<CommonModal
|
||||
show={ showModal }
|
||||
onHide={ () => setShowModal(false) }
|
||||
titleI18nKey={ 'editor.modal.preferences.title' }
|
||||
closeButton={ true }
|
||||
icon={ 'wrench' }>
|
||||
show={showModal}
|
||||
onHide={() => setShowModal(false)}
|
||||
titleI18nKey={'editor.modal.preferences.title'}
|
||||
closeButton={true}
|
||||
icon={'wrench'}>
|
||||
<Form>
|
||||
<ListGroup>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceSelectProperty property={ EditorPreferenceProperty.THEME }
|
||||
selections={ ['one-dark', 'neat'] }/>
|
||||
<EditorPreferenceSelectProperty
|
||||
property={EditorPreferenceProperty.THEME}
|
||||
selections={['one-dark', 'neat']}
|
||||
/>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceSelectProperty property={ EditorPreferenceProperty.KEYMAP }
|
||||
selections={ ['sublime', 'emacs', 'vim'] }/>
|
||||
<EditorPreferenceSelectProperty
|
||||
property={EditorPreferenceProperty.KEYMAP}
|
||||
selections={['sublime', 'emacs', 'vim']}
|
||||
/>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceBooleanProperty property={ EditorPreferenceProperty.INDENT_WITH_TABS }/>
|
||||
<EditorPreferenceBooleanProperty property={EditorPreferenceProperty.INDENT_WITH_TABS} />
|
||||
</ListGroup.Item>
|
||||
<ShowIf condition={ !indentWithTabs }>
|
||||
<ShowIf condition={!indentWithTabs}>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceNumberProperty property={ EditorPreferenceProperty.INDENT_UNIT }/>
|
||||
<EditorPreferenceNumberProperty property={EditorPreferenceProperty.INDENT_UNIT} />
|
||||
</ListGroup.Item>
|
||||
</ShowIf>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceLigaturesSelect/>
|
||||
<EditorPreferenceLigaturesSelect />
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceSmartPasteSelect/>
|
||||
<EditorPreferenceSmartPasteSelect />
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
<EditorPreferenceInput onChange={ () => alert('This feature is not yet implemented.') }
|
||||
property={ EditorPreferenceProperty.SPELL_CHECK }
|
||||
type={ EditorPreferenceInputType.SELECT }>
|
||||
<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>
|
||||
</EditorPreferenceInput>
|
||||
|
|
|
@ -23,15 +23,19 @@ export const EmojiPickerButton: React.FC<EmojiPickerButtonProps> = ({ editor })
|
|||
return (
|
||||
<Fragment>
|
||||
<EmojiPicker
|
||||
show={ showEmojiPicker }
|
||||
onEmojiSelected={ (emoji) => {
|
||||
show={showEmojiPicker}
|
||||
onEmojiSelected={(emoji) => {
|
||||
setShowEmojiPicker(false)
|
||||
addEmoji(emoji, editor)
|
||||
} }
|
||||
onDismiss={ () => setShowEmojiPicker(false) }/>
|
||||
<Button data-cy={ 'show-emoji-picker' } variant='light' onClick={ () => setShowEmojiPicker(old => !old) }
|
||||
title={ t('editor.editorToolbar.emoji') }>
|
||||
<ForkAwesomeIcon icon="smile-o"/>
|
||||
}}
|
||||
onDismiss={() => setShowEmojiPicker(false)}
|
||||
/>
|
||||
<Button
|
||||
data-cy={'show-emoji-picker'}
|
||||
variant='light'
|
||||
onClick={() => setShowEmojiPicker((old) => !old)}
|
||||
title={t('editor.editorToolbar.emoji')}>
|
||||
<ForkAwesomeIcon icon='smile-o' />
|
||||
</Button>
|
||||
</Fragment>
|
||||
)
|
||||
|
|
|
@ -19,13 +19,12 @@ export interface EmojiPickerProps {
|
|||
onDismiss: () => void
|
||||
}
|
||||
|
||||
export const customEmojis: CustomEmoji[] = Object.keys(ForkAwesomeIcons)
|
||||
.map((name) => ({
|
||||
name: `fa-${ name }`,
|
||||
shortcodes: [`fa-${ name.toLowerCase() }`],
|
||||
url: forkawesomeIcon,
|
||||
category: 'ForkAwesome'
|
||||
}))
|
||||
export const customEmojis: CustomEmoji[] = Object.keys(ForkAwesomeIcons).map((name) => ({
|
||||
name: `fa-${name}`,
|
||||
shortcodes: [`fa-${name.toLowerCase()}`],
|
||||
url: forkawesomeIcon,
|
||||
category: 'ForkAwesome'
|
||||
}))
|
||||
|
||||
export const EMOJI_DATA_PATH = '/static/js/emoji-data.json'
|
||||
|
||||
|
@ -93,7 +92,6 @@ export const EmojiPicker: React.FC<EmojiPickerProps> = ({ show, onEmojiSelected,
|
|||
}, [darkModeEnabled])
|
||||
|
||||
return (
|
||||
<div className={ `position-absolute emoji-picker-container ${ !show ? 'd-none' : '' }` }
|
||||
ref={ pickerContainerRef }/>
|
||||
<div className={`position-absolute emoji-picker-container ${!show ? 'd-none' : ''}`} ref={pickerContainerRef} />
|
||||
)
|
||||
}
|
||||
|
|
|
@ -38,42 +38,43 @@ export const CustomTableSizeModal: React.FC<CustomTableSizeModalProps> = ({ show
|
|||
|
||||
return (
|
||||
<CommonModal
|
||||
show={ showModal }
|
||||
onHide={ () => onDismiss() }
|
||||
titleI18nKey={ 'editor.editorToolbar.table.customSize' }
|
||||
closeButton={ true }
|
||||
icon={ 'table' }>
|
||||
<div className={ 'col-lg-10 d-flex flex-row p-3 align-items-center' }>
|
||||
show={showModal}
|
||||
onHide={() => onDismiss()}
|
||||
titleI18nKey={'editor.editorToolbar.table.customSize'}
|
||||
closeButton={true}
|
||||
icon={'table'}>
|
||||
<div className={'col-lg-10 d-flex flex-row p-3 align-items-center'}>
|
||||
<Form.Control
|
||||
type={ 'number' }
|
||||
min={ 1 }
|
||||
placeholder={ t('editor.editorToolbar.table.cols') }
|
||||
isInvalid={ tableSize.columns <= 0 }
|
||||
onChange={ (event) => {
|
||||
type={'number'}
|
||||
min={1}
|
||||
placeholder={t('editor.editorToolbar.table.cols')}
|
||||
isInvalid={tableSize.columns <= 0}
|
||||
onChange={(event) => {
|
||||
const value = Number.parseInt(event.currentTarget.value)
|
||||
setTableSize(old => ({
|
||||
setTableSize((old) => ({
|
||||
rows: old.rows,
|
||||
columns: isNaN(value) ? 0 : value
|
||||
}))
|
||||
} }
|
||||
}}
|
||||
/>
|
||||
<ForkAwesomeIcon icon='times' className='mx-2' fixedWidth={ true }/>
|
||||
<ForkAwesomeIcon icon='times' className='mx-2' fixedWidth={true} />
|
||||
<Form.Control
|
||||
type={ 'number' }
|
||||
min={ 1 }
|
||||
placeholder={ t('editor.editorToolbar.table.rows') }
|
||||
isInvalid={ tableSize.rows <= 0 }
|
||||
onChange={ (event) => {
|
||||
type={'number'}
|
||||
min={1}
|
||||
placeholder={t('editor.editorToolbar.table.rows')}
|
||||
isInvalid={tableSize.rows <= 0}
|
||||
onChange={(event) => {
|
||||
const value = Number.parseInt(event.currentTarget.value)
|
||||
setTableSize(old => ({
|
||||
setTableSize((old) => ({
|
||||
rows: isNaN(value) ? 0 : value,
|
||||
columns: old.columns
|
||||
}))
|
||||
} }/>
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<ModalFooter>
|
||||
<Button onClick={ onClick } disabled={ tableSize.rows <= 0 || tableSize.columns <= 0 }>
|
||||
{ t('editor.editorToolbar.table.create') }
|
||||
<Button onClick={onClick} disabled={tableSize.rows <= 0 || tableSize.columns <= 0}>
|
||||
{t('editor.editorToolbar.table.create')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</CommonModal>
|
||||
|
|
|
@ -23,16 +23,19 @@ export const TablePickerButton: React.FC<TablePickerButtonProps> = ({ editor })
|
|||
return (
|
||||
<Fragment>
|
||||
<TablePicker
|
||||
show={ showTablePicker }
|
||||
onDismiss={ () => setShowTablePicker(false) }
|
||||
onTablePicked={ (rows, cols) => {
|
||||
show={showTablePicker}
|
||||
onDismiss={() => setShowTablePicker(false)}
|
||||
onTablePicked={(rows, cols) => {
|
||||
setShowTablePicker(false)
|
||||
addTable(editor, rows, cols)
|
||||
} }
|
||||
}}
|
||||
/>
|
||||
<Button data-cy={ 'show-table-overlay' } variant='light' onClick={ () => setShowTablePicker(old => !old) }
|
||||
title={ t('editor.editorToolbar.table.title') }>
|
||||
<ForkAwesomeIcon icon="table"/>
|
||||
<Button
|
||||
data-cy={'show-table-overlay'}
|
||||
variant='light'
|
||||
onClick={() => setShowTablePicker((old) => !old)}
|
||||
title={t('editor.editorToolbar.table.title')}>
|
||||
<ForkAwesomeIcon icon='table' />
|
||||
</Button>
|
||||
</Fragment>
|
||||
)
|
||||
|
|
|
@ -20,7 +20,7 @@ export interface TablePickerProps {
|
|||
}
|
||||
|
||||
export type TableSize = {
|
||||
rows: number,
|
||||
rows: number
|
||||
columns: number
|
||||
}
|
||||
|
||||
|
@ -45,43 +45,44 @@ export const TablePicker: React.FC<TablePickerProps> = ({ show, onDismiss, onTab
|
|||
}, [onTablePicked, tableSize])
|
||||
|
||||
return (
|
||||
<div className={ `position-absolute table-picker-container p-2 ${ !show || showDialog ? 'd-none' : '' } bg-light` }
|
||||
ref={ containerRef } role="grid">
|
||||
<p className={ 'lead' }>
|
||||
{ tableSize
|
||||
<div
|
||||
className={`position-absolute table-picker-container p-2 ${!show || showDialog ? 'd-none' : ''} bg-light`}
|
||||
ref={containerRef}
|
||||
role='grid'>
|
||||
<p className={'lead'}>
|
||||
{tableSize
|
||||
? t('editor.editorToolbar.table.size', { cols: tableSize?.columns, rows: tableSize.rows })
|
||||
: t('editor.editorToolbar.table.title')
|
||||
}
|
||||
: t('editor.editorToolbar.table.title')}
|
||||
</p>
|
||||
<div className={ 'table-container' }>
|
||||
{ createNumberRangeArray(8)
|
||||
.map((row: number) => (
|
||||
createNumberRangeArray(10)
|
||||
.map((col: number) => (
|
||||
<div
|
||||
key={ `${ row }_${ col }` }
|
||||
className={ `table-cell ${ tableSize && row < tableSize.rows && col < tableSize.columns ? 'bg-primary border-primary' : '' }` }
|
||||
onMouseEnter={ () => {
|
||||
setTableSize({
|
||||
rows: row + 1,
|
||||
columns: col + 1
|
||||
})
|
||||
} }
|
||||
title={ t('editor.editorToolbar.table.size', { cols: col + 1, rows: row + 1 }) }
|
||||
onClick={ onClick }
|
||||
/>
|
||||
)
|
||||
)
|
||||
)) }
|
||||
<div className={'table-container'}>
|
||||
{createNumberRangeArray(8).map((row: number) =>
|
||||
createNumberRangeArray(10).map((col: number) => (
|
||||
<div
|
||||
key={`${row}_${col}`}
|
||||
className={`table-cell ${
|
||||
tableSize && row < tableSize.rows && col < tableSize.columns ? 'bg-primary border-primary' : ''
|
||||
}`}
|
||||
onMouseEnter={() => {
|
||||
setTableSize({
|
||||
rows: row + 1,
|
||||
columns: col + 1
|
||||
})
|
||||
}}
|
||||
title={t('editor.editorToolbar.table.size', { cols: col + 1, rows: row + 1 })}
|
||||
onClick={onClick}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
<div className="d-flex justify-content-center mt-2">
|
||||
<Button data-cy={ 'show-custom-table-modal' } className={ 'text-center' } onClick={ () => setShowDialog(true) }>
|
||||
<ForkAwesomeIcon icon="table"/> { t('editor.editorToolbar.table.customSize') }
|
||||
<div className='d-flex justify-content-center mt-2'>
|
||||
<Button data-cy={'show-custom-table-modal'} className={'text-center'} onClick={() => setShowDialog(true)}>
|
||||
<ForkAwesomeIcon icon='table' />
|
||||
{t('editor.editorToolbar.table.customSize')}
|
||||
</Button>
|
||||
<CustomTableSizeModal
|
||||
showModal={ showDialog }
|
||||
onDismiss={ () => setShowDialog(false) }
|
||||
onTablePicked={ onTablePicked }
|
||||
showModal={showDialog}
|
||||
onDismiss={() => setShowDialog(false)}
|
||||
onTablePicked={onTablePicked}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -47,87 +47,138 @@ export const ToolBar: React.FC<ToolBarProps> = ({ editor }) => {
|
|||
|
||||
return (
|
||||
<ButtonToolbar className='bg-light'>
|
||||
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
||||
<Button data-cy={ 'format-bold' } variant='light' onClick={ () => makeSelectionBold(editor) }
|
||||
title={ t('editor.editorToolbar.bold') }>
|
||||
<ForkAwesomeIcon icon="bold"/>
|
||||
<ButtonGroup className={'mx-1 flex-wrap'}>
|
||||
<Button
|
||||
data-cy={'format-bold'}
|
||||
variant='light'
|
||||
onClick={() => makeSelectionBold(editor)}
|
||||
title={t('editor.editorToolbar.bold')}>
|
||||
<ForkAwesomeIcon icon='bold' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-italic' } variant='light' onClick={ () => makeSelectionItalic(editor) }
|
||||
title={ t('editor.editorToolbar.italic') }>
|
||||
<ForkAwesomeIcon icon="italic"/>
|
||||
<Button
|
||||
data-cy={'format-italic'}
|
||||
variant='light'
|
||||
onClick={() => makeSelectionItalic(editor)}
|
||||
title={t('editor.editorToolbar.italic')}>
|
||||
<ForkAwesomeIcon icon='italic' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-underline' } variant='light' onClick={ () => underlineSelection(editor) }
|
||||
title={ t('editor.editorToolbar.underline') }>
|
||||
<ForkAwesomeIcon icon="underline"/>
|
||||
<Button
|
||||
data-cy={'format-underline'}
|
||||
variant='light'
|
||||
onClick={() => underlineSelection(editor)}
|
||||
title={t('editor.editorToolbar.underline')}>
|
||||
<ForkAwesomeIcon icon='underline' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-strikethrough' } variant='light' onClick={ () => strikeThroughSelection(editor) }
|
||||
title={ t('editor.editorToolbar.strikethrough') }>
|
||||
<ForkAwesomeIcon icon="strikethrough"/>
|
||||
<Button
|
||||
data-cy={'format-strikethrough'}
|
||||
variant='light'
|
||||
onClick={() => strikeThroughSelection(editor)}
|
||||
title={t('editor.editorToolbar.strikethrough')}>
|
||||
<ForkAwesomeIcon icon='strikethrough' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-subscript' } variant='light' onClick={ () => subscriptSelection(editor) }
|
||||
title={ t('editor.editorToolbar.subscript') }>
|
||||
<ForkAwesomeIcon icon="subscript"/>
|
||||
<Button
|
||||
data-cy={'format-subscript'}
|
||||
variant='light'
|
||||
onClick={() => subscriptSelection(editor)}
|
||||
title={t('editor.editorToolbar.subscript')}>
|
||||
<ForkAwesomeIcon icon='subscript' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-superscript' } variant='light' onClick={ () => superscriptSelection(editor) }
|
||||
title={ t('editor.editorToolbar.superscript') }>
|
||||
<ForkAwesomeIcon icon="superscript"/>
|
||||
<Button
|
||||
data-cy={'format-superscript'}
|
||||
variant='light'
|
||||
onClick={() => superscriptSelection(editor)}
|
||||
title={t('editor.editorToolbar.superscript')}>
|
||||
<ForkAwesomeIcon icon='superscript' />
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
||||
<Button data-cy={ 'format-heading' } variant='light' onClick={ () => addHeaderLevel(editor) }
|
||||
title={ t('editor.editorToolbar.header') }>
|
||||
<ForkAwesomeIcon icon="header"/>
|
||||
<ButtonGroup className={'mx-1 flex-wrap'}>
|
||||
<Button
|
||||
data-cy={'format-heading'}
|
||||
variant='light'
|
||||
onClick={() => addHeaderLevel(editor)}
|
||||
title={t('editor.editorToolbar.header')}>
|
||||
<ForkAwesomeIcon icon='header' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-code-block' } variant='light' onClick={ () => addCodeFences(editor) }
|
||||
title={ t('editor.editorToolbar.code') }>
|
||||
<ForkAwesomeIcon icon="code"/>
|
||||
<Button
|
||||
data-cy={'format-code-block'}
|
||||
variant='light'
|
||||
onClick={() => addCodeFences(editor)}
|
||||
title={t('editor.editorToolbar.code')}>
|
||||
<ForkAwesomeIcon icon='code' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-block-quote' } variant='light' onClick={ () => addQuotes(editor) }
|
||||
title={ t('editor.editorToolbar.blockquote') }>
|
||||
<ForkAwesomeIcon icon="quote-right"/>
|
||||
<Button
|
||||
data-cy={'format-block-quote'}
|
||||
variant='light'
|
||||
onClick={() => addQuotes(editor)}
|
||||
title={t('editor.editorToolbar.blockquote')}>
|
||||
<ForkAwesomeIcon icon='quote-right' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-unordered-list' } variant='light' onClick={ () => addList(editor) }
|
||||
title={ t('editor.editorToolbar.unorderedList') }>
|
||||
<ForkAwesomeIcon icon="list"/>
|
||||
<Button
|
||||
data-cy={'format-unordered-list'}
|
||||
variant='light'
|
||||
onClick={() => addList(editor)}
|
||||
title={t('editor.editorToolbar.unorderedList')}>
|
||||
<ForkAwesomeIcon icon='list' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-ordered-list' } variant='light' onClick={ () => addOrderedList(editor) }
|
||||
title={ t('editor.editorToolbar.orderedList') }>
|
||||
<ForkAwesomeIcon icon="list-ol"/>
|
||||
<Button
|
||||
data-cy={'format-ordered-list'}
|
||||
variant='light'
|
||||
onClick={() => addOrderedList(editor)}
|
||||
title={t('editor.editorToolbar.orderedList')}>
|
||||
<ForkAwesomeIcon icon='list-ol' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-check-list' } variant='light' onClick={ () => addTaskList(editor) }
|
||||
title={ t('editor.editorToolbar.checkList') }>
|
||||
<ForkAwesomeIcon icon="check-square"/>
|
||||
<Button
|
||||
data-cy={'format-check-list'}
|
||||
variant='light'
|
||||
onClick={() => addTaskList(editor)}
|
||||
title={t('editor.editorToolbar.checkList')}>
|
||||
<ForkAwesomeIcon icon='check-square' />
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
||||
<Button data-cy={ 'format-link' } variant='light' onClick={ () => addLink(editor) }
|
||||
title={ t('editor.editorToolbar.link') }>
|
||||
<ForkAwesomeIcon icon="link"/>
|
||||
<ButtonGroup className={'mx-1 flex-wrap'}>
|
||||
<Button
|
||||
data-cy={'format-link'}
|
||||
variant='light'
|
||||
onClick={() => addLink(editor)}
|
||||
title={t('editor.editorToolbar.link')}>
|
||||
<ForkAwesomeIcon icon='link' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-image' } variant='light' onClick={ () => addImage(editor) }
|
||||
title={ t('editor.editorToolbar.image') }>
|
||||
<ForkAwesomeIcon icon="picture-o"/>
|
||||
<Button
|
||||
data-cy={'format-image'}
|
||||
variant='light'
|
||||
onClick={() => addImage(editor)}
|
||||
title={t('editor.editorToolbar.image')}>
|
||||
<ForkAwesomeIcon icon='picture-o' />
|
||||
</Button>
|
||||
<UploadImageButton editor={ editor }/>
|
||||
<UploadImageButton editor={editor} />
|
||||
</ButtonGroup>
|
||||
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
||||
<TablePickerButton editor={ editor }/>
|
||||
<Button data-cy={ 'format-add-line' } variant='light' onClick={ () => addLine(editor) }
|
||||
title={ t('editor.editorToolbar.line') }>
|
||||
<ForkAwesomeIcon icon="minus"/>
|
||||
<ButtonGroup className={'mx-1 flex-wrap'}>
|
||||
<TablePickerButton editor={editor} />
|
||||
<Button
|
||||
data-cy={'format-add-line'}
|
||||
variant='light'
|
||||
onClick={() => addLine(editor)}
|
||||
title={t('editor.editorToolbar.line')}>
|
||||
<ForkAwesomeIcon icon='minus' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-collapsable-block' } variant='light' onClick={ () => addCollapsableBlock(editor) }
|
||||
title={ t('editor.editorToolbar.collapsableBlock') }>
|
||||
<ForkAwesomeIcon icon="caret-square-o-down"/>
|
||||
<Button
|
||||
data-cy={'format-collapsable-block'}
|
||||
variant='light'
|
||||
onClick={() => addCollapsableBlock(editor)}
|
||||
title={t('editor.editorToolbar.collapsableBlock')}>
|
||||
<ForkAwesomeIcon icon='caret-square-o-down' />
|
||||
</Button>
|
||||
<Button data-cy={ 'format-add-comment' } variant='light' onClick={ () => addComment(editor) }
|
||||
title={ t('editor.editorToolbar.comment') }>
|
||||
<ForkAwesomeIcon icon="comment"/>
|
||||
<Button
|
||||
data-cy={'format-add-comment'}
|
||||
variant='light'
|
||||
onClick={() => addComment(editor)}
|
||||
title={t('editor.editorToolbar.comment')}>
|
||||
<ForkAwesomeIcon icon='comment' />
|
||||
</Button>
|
||||
<EmojiPickerButton editor={ editor }/>
|
||||
<EmojiPickerButton editor={editor} />
|
||||
</ButtonGroup>
|
||||
<ButtonGroup className={ 'mx-1 flex-wrap' }>
|
||||
<EditorPreferences/>
|
||||
<ButtonGroup className={'mx-1 flex-wrap'}>
|
||||
<EditorPreferences />
|
||||
</ButtonGroup>
|
||||
</ButtonToolbar>
|
||||
)
|
||||
|
|
|
@ -19,17 +19,20 @@ export interface UploadImageButtonProps {
|
|||
|
||||
export const UploadImageButton: React.FC<UploadImageButtonProps> = ({ editor }) => {
|
||||
const { t } = useTranslation()
|
||||
const clickRef = useRef<(() => void)>()
|
||||
const clickRef = useRef<() => void>()
|
||||
const buttonClick = useCallback(() => {
|
||||
clickRef.current?.()
|
||||
}, [])
|
||||
|
||||
const onUploadImage = useCallback((file: File) => {
|
||||
if (editor) {
|
||||
handleUpload(file, editor)
|
||||
}
|
||||
return Promise.resolve()
|
||||
}, [editor])
|
||||
const onUploadImage = useCallback(
|
||||
(file: File) => {
|
||||
if (editor) {
|
||||
handleUpload(file, editor)
|
||||
}
|
||||
return Promise.resolve()
|
||||
},
|
||||
[editor]
|
||||
)
|
||||
|
||||
if (!editor) {
|
||||
return null
|
||||
|
@ -37,10 +40,10 @@ export const UploadImageButton: React.FC<UploadImageButtonProps> = ({ editor })
|
|||
|
||||
return (
|
||||
<Fragment>
|
||||
<Button variant='light' onClick={ buttonClick } title={ t('editor.editorToolbar.uploadImage') }>
|
||||
<ForkAwesomeIcon icon={ 'upload' }/>
|
||||
<Button variant='light' onClick={buttonClick} title={t('editor.editorToolbar.uploadImage')}>
|
||||
<ForkAwesomeIcon icon={'upload'} />
|
||||
</Button>
|
||||
<UploadInput onLoad={ onUploadImage } acceptedFiles={ supportedMimeTypesJoined } onClickRef={ clickRef }/>
|
||||
<UploadInput onLoad={onUploadImage} acceptedFiles={supportedMimeTypesJoined} onClickRef={clickRef} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -30,34 +30,28 @@ const mockEditor = (content: string, line: number) => {
|
|||
}
|
||||
|
||||
describe('Check whether cursor is in codefence', () => {
|
||||
|
||||
it('returns false for empty document', () => {
|
||||
const editor = mockEditor('', 0)
|
||||
expect(isCursorInCodefence(editor))
|
||||
.toBe(false)
|
||||
expect(isCursorInCodefence(editor)).toBe(false)
|
||||
})
|
||||
|
||||
it('returns true with one open codefence directly above', () => {
|
||||
const editor = mockEditor('```\n', 1)
|
||||
expect(isCursorInCodefence(editor))
|
||||
.toBe(true)
|
||||
expect(isCursorInCodefence(editor)).toBe(true)
|
||||
})
|
||||
|
||||
it('returns true with one open codefence and empty lines above', () => {
|
||||
const editor = mockEditor('```\n\n\n', 3)
|
||||
expect(isCursorInCodefence(editor))
|
||||
.toBe(true)
|
||||
expect(isCursorInCodefence(editor)).toBe(true)
|
||||
})
|
||||
|
||||
it('returns false with one completed codefence above', () => {
|
||||
const editor = mockEditor('```\n\n```\n', 3)
|
||||
expect(isCursorInCodefence(editor))
|
||||
.toBe(false)
|
||||
expect(isCursorInCodefence(editor)).toBe(false)
|
||||
})
|
||||
|
||||
it('returns true with one completed and one open codefence above', () => {
|
||||
const editor = mockEditor('```\n\n```\n\n```\n\n', 6)
|
||||
expect(isCursorInCodefence(editor))
|
||||
.toBe(true)
|
||||
expect(isCursorInCodefence(editor)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -12,7 +12,7 @@ export const getEmojiIcon = (emoji: EmojiClickEventDetail): string => {
|
|||
}
|
||||
if (emoji.name) {
|
||||
// noinspection CheckTagEmptyBody
|
||||
return `<i class="fa ${ emoji.name }"></i>`
|
||||
return `<i class="fa ${emoji.name}"></i>`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ export const getEmojiShortCode = (emoji: EmojiClickEventDetail): string | undefi
|
|||
}
|
||||
let skinToneModifier = ''
|
||||
if ((emoji.emoji as NativeEmoji).skins && emoji.skinTone !== 0) {
|
||||
skinToneModifier = `:skin-tone-${ emoji.skinTone as number }:`
|
||||
skinToneModifier = `:skin-tone-${emoji.skinTone as number}:`
|
||||
}
|
||||
return `:${ emoji.emoji.shortcodes[0] }:${ skinToneModifier }`
|
||||
return `:${emoji.emoji.shortcodes[0]}:${skinToneModifier}`
|
||||
}
|
||||
|
|
|
@ -14,9 +14,9 @@ type ClipboardDataFormats = 'text' | 'url' | 'text/plain' | 'text/uri-list' | 't
|
|||
|
||||
export interface PasteEvent {
|
||||
clipboardData: {
|
||||
files: FileList,
|
||||
files: FileList
|
||||
getData: (format: ClipboardDataFormats) => string
|
||||
},
|
||||
}
|
||||
preventDefault: () => void
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -17,31 +17,29 @@ export const subscriptSelection = (editor: Editor): void => wrapTextWith(editor,
|
|||
export const superscriptSelection = (editor: Editor): void => wrapTextWith(editor, '^')
|
||||
export const markSelection = (editor: Editor): void => wrapTextWith(editor, '==')
|
||||
|
||||
export const addHeaderLevel = (editor: Editor): void => changeLines(editor, line => line.startsWith('#') ? `#${ line }` : `# ${ line }`)
|
||||
export const addHeaderLevel = (editor: Editor): void =>
|
||||
changeLines(editor, (line) => (line.startsWith('#') ? `#${line}` : `# ${line}`))
|
||||
export const addCodeFences = (editor: Editor): void => wrapTextWithOrJustPut(editor, '```\n', '\n```')
|
||||
export const addQuotes = (editor: Editor): void => insertOnStartOfLines(editor, '> ')
|
||||
|
||||
export const addList = (editor: Editor): void => createList(editor, () => '- ')
|
||||
export const addOrderedList = (editor: Editor): void => createList(editor, j => `${ j }. `)
|
||||
export const addOrderedList = (editor: Editor): void => createList(editor, (j) => `${j}. `)
|
||||
export const addTaskList = (editor: Editor): void => createList(editor, () => '- [ ] ')
|
||||
|
||||
export const addImage = (editor: Editor): void => addLink(editor, '!')
|
||||
|
||||
export const addLine = (editor: Editor): void => changeLines(editor, line => `${ line }\n----`)
|
||||
export const addCollapsableBlock = (editor: Editor): void => changeLines(editor, line => `${ line }\n:::spoiler Toggle label\n Toggled content\n:::`)
|
||||
export const addComment = (editor: Editor): void => changeLines(editor, line => `${ line }\n> []`)
|
||||
export const addLine = (editor: Editor): void => changeLines(editor, (line) => `${line}\n----`)
|
||||
export const addCollapsableBlock = (editor: Editor): void =>
|
||||
changeLines(editor, (line) => `${line}\n:::spoiler Toggle label\n Toggled content\n:::`)
|
||||
export const addComment = (editor: Editor): void => changeLines(editor, (line) => `${line}\n> []`)
|
||||
export const addTable = (editor: Editor, rows: number, columns: number): void => {
|
||||
const rowArray = createNumberRangeArray(rows)
|
||||
const colArray = createNumberRangeArray(columns)
|
||||
.map(col => col + 1)
|
||||
const colArray = createNumberRangeArray(columns).map((col) => col + 1)
|
||||
const head = '| # ' + colArray.join(' | # ') + ' |'
|
||||
const divider = '| ' + colArray.map(() => '----')
|
||||
.join(' | ') + ' |'
|
||||
const body = rowArray.map(() => '| ' + colArray.map(() => 'Text')
|
||||
.join(' | ') + ' |')
|
||||
.join('\n')
|
||||
const table = `${ head }\n${ divider }\n${ body }`
|
||||
changeLines(editor, line => `${ line }\n${ table }`)
|
||||
const divider = '| ' + colArray.map(() => '----').join(' | ') + ' |'
|
||||
const body = rowArray.map(() => '| ' + colArray.map(() => 'Text').join(' | ') + ' |').join('\n')
|
||||
const table = `${head}\n${divider}\n${body}`
|
||||
changeLines(editor, (line) => `${line}\n${table}`)
|
||||
}
|
||||
|
||||
export const addEmoji = (emoji: EmojiClickEventDetail, editor: Editor): void => {
|
||||
|
@ -76,11 +74,8 @@ const wrapTextWithOrJustPut = (editor: Editor, symbol: string, endSymbol?: strin
|
|||
const cursor = editor.getCursor()
|
||||
const lineNumber = cursor.line
|
||||
const line = editor.getLine(lineNumber)
|
||||
const replacement = /\s*\\n/.exec(line) ? `${ symbol }${ endSymbol ?? '' }` : `${ symbol }${ line }${ endSymbol ?? '' }`
|
||||
editor.replaceRange(replacement,
|
||||
{ line: cursor.line, ch: 0 },
|
||||
{ line: cursor.line, ch: line.length },
|
||||
'+input')
|
||||
const replacement = /\s*\\n/.exec(line) ? `${symbol}${endSymbol ?? ''}` : `${symbol}${line}${endSymbol ?? ''}`
|
||||
editor.replaceRange(replacement, { line: cursor.line, ch: 0 }, { line: cursor.line, ch: line.length }, '+input')
|
||||
}
|
||||
wrapTextWith(editor, symbol, endSymbol ?? symbol)
|
||||
}
|
||||
|
@ -93,8 +88,7 @@ export const insertOnStartOfLines = (editor: Editor, symbol: string): void => {
|
|||
const to = range.empty() ? { line: cursor.line, ch: editor.getLine(cursor.line).length } : range.to()
|
||||
const selection = editor.getRange(from, to)
|
||||
const lines = selection.split('\n')
|
||||
editor.replaceRange(lines.map(line => `${ symbol }${ line }`)
|
||||
.join('\n'), from, to, '+input')
|
||||
editor.replaceRange(lines.map((line) => `${symbol}${line}`).join('\n'), from, to, '+input')
|
||||
}
|
||||
editor.setSelections(ranges)
|
||||
}
|
||||
|
@ -105,10 +99,15 @@ export const changeLines = (editor: Editor, replaceFunction: (line: string) => s
|
|||
for (const range of ranges) {
|
||||
const lineNumber = range.empty() ? cursor.line : range.from().line
|
||||
const line = editor.getLine(lineNumber)
|
||||
editor.replaceRange(replaceFunction(line), { line: lineNumber, ch: 0 }, {
|
||||
line: lineNumber,
|
||||
ch: line.length
|
||||
}, '+input')
|
||||
editor.replaceRange(
|
||||
replaceFunction(line),
|
||||
{ line: lineNumber, ch: 0 },
|
||||
{
|
||||
line: lineNumber,
|
||||
ch: line.length
|
||||
},
|
||||
'+input'
|
||||
)
|
||||
}
|
||||
editor.setSelections(ranges)
|
||||
}
|
||||
|
@ -122,8 +121,7 @@ export const createList = (editor: Editor, listMark: (i: number) => string): voi
|
|||
|
||||
const selection = editor.getRange(from, to)
|
||||
const lines = selection.split('\n')
|
||||
editor.replaceRange(lines.map((line, i) => `${ listMark(i + 1) }${ line }`)
|
||||
.join('\n'), from, to, '+input')
|
||||
editor.replaceRange(lines.map((line, i) => `${listMark(i + 1)}${line}`).join('\n'), from, to, '+input')
|
||||
}
|
||||
editor.setSelections(ranges)
|
||||
}
|
||||
|
@ -137,9 +135,9 @@ export const addLink = (editor: Editor, prefix?: string): void => {
|
|||
const selection = editor.getRange(from, to)
|
||||
const linkRegex = /^(?:https?|ftp|mailto):/
|
||||
if (linkRegex.exec(selection)) {
|
||||
editor.replaceRange(`${ prefix || '' }[](${ selection })`, from, to, '+input')
|
||||
editor.replaceRange(`${prefix || ''}[](${selection})`, from, to, '+input')
|
||||
} else {
|
||||
editor.replaceRange(`${ prefix || '' }[${ selection }](https://)`, from, to, '+input')
|
||||
editor.replaceRange(`${prefix || ''}[${selection}](https://)`, from, to, '+input')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,6 +148,6 @@ export const insertAtCursor = (editor: Editor, text: string): void => {
|
|||
for (const range of ranges) {
|
||||
const from = range.empty() ? { line: cursor.line, ch: cursor.ch } : range.from()
|
||||
const to = range.empty() ? { line: cursor.line, ch: cursor.ch } : range.to()
|
||||
editor.replaceRange(`${ text }`, from, to, '+input')
|
||||
editor.replaceRange(`${text}`, from, to, '+input')
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue