mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-22 03:05:19 -04:00
feat(editor): add basic codemirror autocompletion suggestions
Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
parent
4956a99ced
commit
61032cb745
23 changed files with 284 additions and 2 deletions
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { regexCompletion } from './regex-completion'
|
||||
import type { CompletionContext, CompletionResult } from '@codemirror/autocomplete'
|
||||
|
||||
export const codeFenceRegex = /(?:^|\s)`(?:`|``|``\w+)?$/
|
||||
|
||||
/**
|
||||
* Returns a {@link CompletionSource} for a regex-matching autocompletion with a single completion entry.
|
||||
*
|
||||
* @param regexToMatch The regex to match in front of the cursor
|
||||
* @param replace The string to insert as completion
|
||||
* @param description An optional description to show besides the suggestion
|
||||
* @return A function to test and perform the configured completion.
|
||||
*/
|
||||
export const basicCompletion = (
|
||||
regexToMatch: RegExp,
|
||||
replace: string,
|
||||
description?: string
|
||||
): ((_: CompletionContext) => CompletionResult | null) => {
|
||||
return regexCompletion(regexToMatch, [{ label: replace, detail: description }])
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete'
|
||||
|
||||
/**
|
||||
* Returns a {@link CompletionSource} for a regex-matching autocompletion.
|
||||
*
|
||||
* @param regexToMatch The regex to match in front of the cursor
|
||||
* @param options The options to return
|
||||
* @return A function to test and perform the configured completions.
|
||||
*/
|
||||
export const regexCompletion =
|
||||
(regexToMatch: RegExp, options: Completion[]) =>
|
||||
(context: CompletionContext): CompletionResult | null => {
|
||||
const match = context.matchBefore(regexToMatch)
|
||||
if (!match || (match.from === match.to && !context.explicit)) {
|
||||
return null
|
||||
}
|
||||
return {
|
||||
from: match.from,
|
||||
options
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import { cypressAttribute, cypressId } from '../../../utils/cypress-attribute'
|
|||
import { findLanguageByCodeBlockName } from '../../markdown-renderer/extensions/base/code-block-markdown-extension/find-language-by-code-block-name'
|
||||
import type { ScrollProps } from '../synced-scroll/scroll-props'
|
||||
import styles from './extended-codemirror/codemirror.module.scss'
|
||||
import { useCodeMirrorAutocompletionsExtension } from './hooks/codemirror-extensions/use-code-mirror-autocompletions-extension'
|
||||
import { useCodeMirrorFileInsertExtension } from './hooks/codemirror-extensions/use-code-mirror-file-insert-extension'
|
||||
import { useCodeMirrorRemoteCursorsExtension } from './hooks/codemirror-extensions/use-code-mirror-remote-cursor-extensions'
|
||||
import { useCodeMirrorScrollWatchExtension } from './hooks/codemirror-extensions/use-code-mirror-scroll-watch-extension'
|
||||
|
@ -31,7 +32,6 @@ import { useLinter } from './linter/linter'
|
|||
import { MaxLengthWarning } from './max-length-warning/max-length-warning'
|
||||
import { StatusBar } from './status-bar/status-bar'
|
||||
import { ToolBar } from './tool-bar/tool-bar'
|
||||
import { autocompletion } from '@codemirror/autocomplete'
|
||||
import { markdown, markdownLanguage } from '@codemirror/lang-markdown'
|
||||
import { languages } from '@codemirror/language-data'
|
||||
import { lintGutter } from '@codemirror/lint'
|
||||
|
@ -62,6 +62,8 @@ export const EditorPane: React.FC<EditorPaneProps> = ({ scrollState, onScroll, o
|
|||
const fileInsertExtension = useCodeMirrorFileInsertExtension()
|
||||
const spellCheckExtension = useCodeMirrorSpellCheckExtension()
|
||||
const cursorActivityExtension = useCursorActivityCallback()
|
||||
const autoCompletionExtension = useCodeMirrorAutocompletionsExtension()
|
||||
|
||||
const updateViewContextExtension = useUpdateCodeMirrorReference()
|
||||
|
||||
const remoteCursorsExtension = useCodeMirrorRemoteCursorsExtension(messageTransporter)
|
||||
|
@ -90,7 +92,7 @@ export const EditorPane: React.FC<EditorPaneProps> = ({ scrollState, onScroll, o
|
|||
editorScrollExtension,
|
||||
tablePasteExtensions,
|
||||
fileInsertExtension,
|
||||
autocompletion(),
|
||||
autoCompletionExtension,
|
||||
cursorActivityExtension,
|
||||
updateViewContextExtension,
|
||||
yjsExtension,
|
||||
|
@ -99,6 +101,7 @@ export const EditorPane: React.FC<EditorPaneProps> = ({ scrollState, onScroll, o
|
|||
[
|
||||
linterExtension,
|
||||
remoteCursorsExtension,
|
||||
autoCompletionExtension,
|
||||
editorScrollExtension,
|
||||
tablePasteExtensions,
|
||||
fileInsertExtension,
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { optionalAppExtensions } from '../../../../../extensions/extra-integrations/optional-app-extensions'
|
||||
import { autocompletion } from '@codemirror/autocomplete'
|
||||
import type { Extension } from '@codemirror/state'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
/**
|
||||
* Returns a configured autocompletion extension that uses the autocompletions from the app extensions.
|
||||
*/
|
||||
export const useCodeMirrorAutocompletionsExtension = (): Extension => {
|
||||
return useMemo(() => {
|
||||
return autocompletion({
|
||||
override: optionalAppExtensions.flatMap((extension) => extension.buildAutocompletion())
|
||||
})
|
||||
}, [])
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue