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:
Tilman Vatteroth 2021-12-31 14:00:33 +01:00 committed by GitHub
parent 20d9a15cff
commit 98040cbdaa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 27 deletions

View file

@ -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>')

View file

@ -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}

View file

@ -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}
/>
)