Improved editor indent plugin related behaviour, added x-scroll to code blocks (#7520)
Some checks failed
CI / build (push) Has been cancelled
CI / uitest (push) Has been cancelled
CI / uitest-pg (push) Has been cancelled
CI / uitest-qms (push) Has been cancelled
CI / svelte-check (push) Has been cancelled
CI / formatting (push) Has been cancelled
CI / test (push) Has been cancelled
CI / docker-build (push) Has been cancelled
CI / dist-build (push) Has been cancelled

Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com>
This commit is contained in:
Victor Ilyushchenko 2024-12-20 17:27:16 +03:00 committed by GitHub
parent 6c9cb78493
commit 4159c3f761
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 6 deletions

View File

@ -386,6 +386,7 @@ table.proseTable {
background-color: var(--theme-button-default);
border: 1px solid var(--theme-button-border);
border-radius: .25rem;
font-size: 0.875rem;
}
.proseCodeBlock {
@ -397,13 +398,19 @@ table.proseTable {
padding: .5rem;
user-select: text;
cursor: auto;
code {
display: block;
overflow-x: auto;
white-space: pre;
word-wrap: nowrap;
scrollbar-width: auto;
font-size: 0.875rem;
}
}
pre.proseCodeBlock {
position: relative;
white-space: pre-wrap;
word-wrap: break-word;
word-break: normal;
}
pre.proseCodeBlock {
@ -496,6 +503,11 @@ pre.proseCodeBlock>pre.proseCode {
font-size: 0.875rem;
line-height: 1.5em;
overflow-x: auto;
white-space: pre;
word-wrap: nowrap;
scrollbar-width: auto;
}
.mermaidPreviewContainer {

View File

@ -15,7 +15,7 @@
import { Extension } from '@tiptap/core'
import { type Node } from '@tiptap/pm/model'
import { type EditorState, TextSelection, type Transaction } from '@tiptap/pm/state'
import { type EditorState, Plugin, TextSelection, type Transaction } from '@tiptap/pm/state'
export interface IndendOptions {
indentUnit: string
@ -44,9 +44,35 @@ export const IndentExtension = Extension.create<IndendOptions>({
})
}
}
},
addProseMirrorPlugins () {
return [...(this.parent?.() ?? []), IndentTabFocusFixer(this.options)]
}
})
function IndentTabFocusFixer (options: IndendOptions): Plugin {
return new Plugin({
props: {
handleKeyDown: (view, event) => {
const selection = view.state.selection
if (event.key !== 'Tab' || !(selection instanceof TextSelection)) return false
const lines = getLinesInSelection(view.state, selection)
const haveForbiddenNode = lines.some((line) => !options.allowedNodes.some((n) => n === line.node.type.name))
const shouldBlockEvent = lines.length > 0 && !haveForbiddenNode
if (shouldBlockEvent) {
event.preventDefault()
event.stopPropagation()
}
return shouldBlockEvent
}
}
})
}
export function adjustIndent (state: EditorState, direction: -1 | 1, options: IndendOptions): Transaction | undefined {
const { selection } = state
if (selection instanceof TextSelection) {
@ -80,14 +106,24 @@ export function adjustSelectionIndent (
if (ranges.length === 1) {
const range = ranges[0]
const withinIndent = selection.from >= range.from && selection.to <= range.from + range.indent && range.indent > 0
if (!withinIndent && direction > 0) {
const containsLine = selection.from <= range.from && selection.to >= range.to
if (!withinIndent && !containsLine && direction > 0) {
const indentOffset = indentLevelOffset(selection.from - range.from, direction)
tr.insertText(indentUnit.slice(0, indentOffset), selection.from, selection.to)
return
}
}
const isSelectionCollapsed = selection.from === selection.to
const affectedFromIndentStart = selection.from <= ranges[0].from + ranges[0].indent
const affectedFrom =
affectedFromIndentStart && !isSelectionCollapsed
? selection.from
: selection.from + indentLevelOffset(ranges[0].indent, direction)
let affectedTo = selection.to
let insertionOffset = 0
for (const range of ranges) {
if (direction > 0 ? range.text === '' : range.indent === 0) {
continue
@ -99,10 +135,13 @@ export function adjustSelectionIndent (
} else {
tr.insertText('', from, from - indentOffset)
}
insertionOffset += indentOffset
affectedTo = selection.to + insertionOffset
}
tr.setSelection(selection.map(tr.doc, tr.mapping))
const newSelection = new TextSelection(tr.doc.resolve(affectedFrom), tr.doc.resolve(affectedTo))
tr.setSelection(newSelection)
return tr
}