mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-01-27 06:21:44 +00:00
Fix autocompletion (#1736)
* Add visibility check for codemirror autocompletion Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de> * Move autocompletion trigger to extended-codemirror Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
20d9a15cff
commit
98040cbdaa
3 changed files with 38 additions and 27 deletions
|
@ -13,7 +13,7 @@ describe('Autocompletion works for', () => {
|
|||
describe('code block', () => {
|
||||
it('via enter', () => {
|
||||
cy.setCodemirrorContent('```')
|
||||
cy.get('.CodeMirror-hints').should('exist')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('@codeinput').type('{enter}')
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line').contains('```abnf')
|
||||
|
@ -22,6 +22,7 @@ describe('Autocompletion works for', () => {
|
|||
})
|
||||
it('via doubleclick', () => {
|
||||
cy.setCodemirrorContent('```')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('.CodeMirror-hints > li').first().dblclick()
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line').contains('```abnf')
|
||||
|
@ -33,7 +34,7 @@ describe('Autocompletion works for', () => {
|
|||
describe('container', () => {
|
||||
it('via enter', () => {
|
||||
cy.setCodemirrorContent(':::')
|
||||
cy.get('.CodeMirror-hints').should('exist')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('@codeinput').type('{enter}')
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line').contains(':::success')
|
||||
|
@ -42,6 +43,7 @@ describe('Autocompletion works for', () => {
|
|||
})
|
||||
it('via doubleclick', () => {
|
||||
cy.setCodemirrorContent(':::')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('.CodeMirror-hints > li').first().dblclick()
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line').contains(':::success')
|
||||
|
@ -54,13 +56,14 @@ describe('Autocompletion works for', () => {
|
|||
describe('normal emoji', () => {
|
||||
it('via enter', () => {
|
||||
cy.setCodemirrorContent(':hedg')
|
||||
cy.get('.CodeMirror-hints').should('exist')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('@codeinput').type('{enter}')
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains(':hedgehog:')
|
||||
})
|
||||
it('via doubleclick', () => {
|
||||
cy.setCodemirrorContent(':hedg')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('.CodeMirror-hints > li').first().dblclick()
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains(':hedgehog:')
|
||||
|
@ -70,13 +73,14 @@ describe('Autocompletion works for', () => {
|
|||
describe('fork-awesome-icon', () => {
|
||||
it('via enter', () => {
|
||||
cy.setCodemirrorContent(':fa-face')
|
||||
cy.get('.CodeMirror-hints').should('exist')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('@codeinput').type('{enter}')
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains(':fa-facebook:')
|
||||
})
|
||||
it('via doubleclick', () => {
|
||||
cy.setCodemirrorContent(':fa-face')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('.CodeMirror-hints > li').first().dblclick()
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains(':fa-facebook:')
|
||||
|
@ -87,7 +91,7 @@ describe('Autocompletion works for', () => {
|
|||
describe('header', () => {
|
||||
it('via enter', () => {
|
||||
cy.setCodemirrorContent('#')
|
||||
cy.get('.CodeMirror-hints').should('exist')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('@codeinput').type('{enter}')
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains('# ')
|
||||
|
@ -95,6 +99,7 @@ describe('Autocompletion works for', () => {
|
|||
})
|
||||
it('via doubleclick', () => {
|
||||
cy.setCodemirrorContent('#')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('.CodeMirror-hints > li').first().dblclick()
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains('# ')
|
||||
|
@ -105,7 +110,7 @@ describe('Autocompletion works for', () => {
|
|||
describe('images', () => {
|
||||
it('via enter', () => {
|
||||
cy.setCodemirrorContent('!')
|
||||
cy.get('.CodeMirror-hints').should('exist')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('@codeinput').type('{enter}')
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains('![image alt](https:// "title")')
|
||||
|
@ -113,6 +118,7 @@ describe('Autocompletion works for', () => {
|
|||
})
|
||||
it('via doubleclick', () => {
|
||||
cy.setCodemirrorContent('!')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('.CodeMirror-hints > li').first().dblclick()
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains('![image alt](https:// "title")')
|
||||
|
@ -123,7 +129,7 @@ describe('Autocompletion works for', () => {
|
|||
describe('links', () => {
|
||||
it('via enter', () => {
|
||||
cy.setCodemirrorContent('[')
|
||||
cy.get('.CodeMirror-hints').should('exist')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('@codeinput').type('{enter}')
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains('[link text](https:// "title") ')
|
||||
|
@ -135,6 +141,7 @@ describe('Autocompletion works for', () => {
|
|||
})
|
||||
it('via doubleclick', () => {
|
||||
cy.setCodemirrorContent('[')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('.CodeMirror-hints > li').first().dblclick()
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains('[link text](https:// "title") ')
|
||||
|
@ -149,7 +156,7 @@ describe('Autocompletion works for', () => {
|
|||
describe('pdf', () => {
|
||||
it('via enter', () => {
|
||||
cy.setCodemirrorContent('{')
|
||||
cy.get('.CodeMirror-hints').should('exist')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('@codeinput').type('{enter}')
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains('{%pdf https:// %}')
|
||||
|
@ -157,6 +164,7 @@ describe('Autocompletion works for', () => {
|
|||
})
|
||||
it('via doubleclick', () => {
|
||||
cy.setCodemirrorContent('{')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('.CodeMirror-hints > li').first().dblclick()
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains('{%pdf https:// %}')
|
||||
|
@ -167,7 +175,7 @@ describe('Autocompletion works for', () => {
|
|||
describe('collapsible blocks', () => {
|
||||
it('via enter', () => {
|
||||
cy.setCodemirrorContent('<d')
|
||||
cy.get('.CodeMirror-hints').should('exist')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('@codeinput').type('{enter}')
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains('</details>') // after selecting the hint, the last line of the inserted suggestion is active
|
||||
|
@ -175,6 +183,7 @@ describe('Autocompletion works for', () => {
|
|||
})
|
||||
it('via doubleclick', () => {
|
||||
cy.setCodemirrorContent('<d')
|
||||
cy.get('.CodeMirror-hints').should('be.visible')
|
||||
cy.get('.CodeMirror-hints > li').first().dblclick()
|
||||
cy.get('.CodeMirror-hints').should('not.exist')
|
||||
cy.get('.CodeMirror-activeline').contains('</details>')
|
||||
|
|
|
@ -20,24 +20,8 @@ import { useApplyScrollState } from './hooks/use-apply-scroll-state'
|
|||
import { MaxLengthWarning } from './max-length-warning/max-length-warning'
|
||||
import { useCreateStatusBarInfo } from './hooks/use-create-status-bar-info'
|
||||
import { useOnImageUploadFromRenderer } from './hooks/use-on-image-upload-from-renderer'
|
||||
import { allHinters, findWordAtCursor } from './autocompletion'
|
||||
import { ExtendedCodemirror } from './extended-codemirror/extended-codemirror'
|
||||
|
||||
const onChange = (editor: Editor) => {
|
||||
const searchTerm = findWordAtCursor(editor)
|
||||
for (const hinter of allHinters) {
|
||||
if (hinter.wordRegExp.test(searchTerm.text)) {
|
||||
editor.showHint({
|
||||
hint: hinter.hint,
|
||||
completeSingle: false,
|
||||
completeOnSingleClick: false,
|
||||
alignWithWord: true
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const EditorPane: React.FC<ScrollProps> = ({ scrollState, onScroll, onMakeScrollSource }) => {
|
||||
const markdownContent = useNoteMarkdownContent()
|
||||
|
||||
|
@ -76,7 +60,6 @@ export const EditorPane: React.FC<ScrollProps> = ({ scrollState, onScroll, onMak
|
|||
value={markdownContent}
|
||||
options={codeMirrorOptions}
|
||||
onPaste={onPaste}
|
||||
onChange={onChange}
|
||||
onDrop={onDrop}
|
||||
onCursorActivity={updateStatusBarInfo}
|
||||
editorDidMount={onEditorDidMount}
|
||||
|
|
|
@ -9,11 +9,29 @@ import type { IControlledCodeMirror } from 'react-codemirror2'
|
|||
import { Controlled } from 'react-codemirror2'
|
||||
import './codemirror-imports'
|
||||
import styles from './codemirror.module.scss'
|
||||
import { allHinters, findWordAtCursor } from '../autocompletion'
|
||||
import type { Editor } from 'codemirror'
|
||||
|
||||
export interface ExtendedCodemirrorProps extends IControlledCodeMirror {
|
||||
export interface ExtendedCodemirrorProps extends Omit<IControlledCodeMirror, 'onChange'> {
|
||||
ligatures?: boolean
|
||||
}
|
||||
|
||||
const onChange = (editor: Editor) => {
|
||||
const searchTerm = findWordAtCursor(editor)
|
||||
for (const hinter of allHinters) {
|
||||
if (hinter.wordRegExp.test(searchTerm.text)) {
|
||||
editor.showHint({
|
||||
container: editor.getWrapperElement(),
|
||||
hint: hinter.hint,
|
||||
completeSingle: false,
|
||||
completeOnSingleClick: false,
|
||||
alignWithWord: true
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Controlled controlled code mirror} but with several addons, different font, ligatures and other improvements.
|
||||
*
|
||||
|
@ -25,6 +43,7 @@ export const ExtendedCodemirror: React.FC<ExtendedCodemirrorProps> = ({ classNam
|
|||
return (
|
||||
<Controlled
|
||||
className={`${className ?? ''} ${ligatures ? '' : styles['no-ligatures']} ${styles['extended-codemirror']}`}
|
||||
onChange={onChange}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue