Skip to content

Commit

Permalink
Improved editor indent plugin related behaviour, added x-scroll to co…
Browse files Browse the repository at this point in the history
…de blocks (#7520)

Signed-off-by: Victor Ilyushchenko <[email protected]>
  • Loading branch information
mr1name authored Dec 20, 2024
1 parent 6c9cb78 commit 4159c3f
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 6 deletions.
18 changes: 15 additions & 3 deletions packages/theme/styles/prose.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
45 changes: 42 additions & 3 deletions plugins/text-editor-resources/src/components/extension/indent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand Down

0 comments on commit 4159c3f

Please sign in to comment.