mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-19 14:55:31 +00:00
UBERF-4317 Apply mappings to table of contents decorations (#4006)
Signed-off-by: Alexander Onnikov <alexander.onnikov@xored.com>
This commit is contained in:
parent
b5f261318f
commit
f0ba202f28
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
import { Extension } from '@tiptap/core'
|
import { Extension } from '@tiptap/core'
|
||||||
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||||
import { EditorState, Plugin, PluginKey } from '@tiptap/pm/state'
|
import { EditorState, Plugin, PluginKey, Transaction } from '@tiptap/pm/state'
|
||||||
import { Decoration, DecorationSet } from '@tiptap/pm/view'
|
import { Decoration, DecorationSet } from '@tiptap/pm/view'
|
||||||
import slugify from 'slugify'
|
import slugify from 'slugify'
|
||||||
import { Heading } from '../../types'
|
import { Heading } from '../../types'
|
||||||
@ -59,42 +59,15 @@ export const HeadingsExtension: Extension<HeadingsOptions, HeadingsStorage> = Ex
|
|||||||
|
|
||||||
options.onChange?.(headings)
|
options.onChange?.(headings)
|
||||||
|
|
||||||
return { decorations }
|
return { decorations: DecorationSet.create(state.doc, decorations) }
|
||||||
},
|
},
|
||||||
|
|
||||||
apply (tr, value, oldState, newState) {
|
apply (tr, value, oldState, newState) {
|
||||||
if (!tr.docChanged) {
|
const headingUpdate = hasHeadingUpdate(tr)
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
let headingUpdate = false
|
|
||||||
|
|
||||||
tr.mapping.maps.forEach((map, index) =>
|
|
||||||
map.forEach((oldStart, oldEnd, newStart, newEnd) => {
|
|
||||||
const oldDoc = tr.docs[index]
|
|
||||||
const newDoc = tr.docs[index + 1] ?? tr.doc
|
|
||||||
|
|
||||||
oldDoc.nodesBetween(oldStart, oldEnd, (node) => {
|
|
||||||
if (headingUpdate) {
|
|
||||||
return false
|
|
||||||
} else if (node.type.name === 'heading') {
|
|
||||||
headingUpdate = true
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
newDoc.nodesBetween(newStart, newEnd, (node) => {
|
|
||||||
if (headingUpdate) {
|
|
||||||
return false
|
|
||||||
} else if (node.type.name === 'heading') {
|
|
||||||
headingUpdate = true
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!headingUpdate) {
|
if (!headingUpdate) {
|
||||||
return value
|
const { decorations } = value
|
||||||
|
return { decorations: decorations.map(tr.mapping, tr.doc) }
|
||||||
}
|
}
|
||||||
|
|
||||||
const decorations = getHeadingDecorations(newState, prefixId)
|
const decorations = getHeadingDecorations(newState, prefixId)
|
||||||
@ -103,7 +76,7 @@ export const HeadingsExtension: Extension<HeadingsOptions, HeadingsStorage> = Ex
|
|||||||
options.onChange?.(headings)
|
options.onChange?.(headings)
|
||||||
storage.headings = headings
|
storage.headings = headings
|
||||||
|
|
||||||
return { decorations }
|
return { decorations: DecorationSet.create(tr.doc, decorations) }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
@ -111,7 +84,7 @@ export const HeadingsExtension: Extension<HeadingsOptions, HeadingsStorage> = Ex
|
|||||||
const pluginState = this.getState(state)
|
const pluginState = this.getState(state)
|
||||||
if (pluginState !== undefined) {
|
if (pluginState !== undefined) {
|
||||||
const { decorations } = pluginState
|
const { decorations } = pluginState
|
||||||
return DecorationSet.create(state.doc, decorations)
|
return decorations
|
||||||
}
|
}
|
||||||
|
|
||||||
return DecorationSet.empty
|
return DecorationSet.empty
|
||||||
@ -124,6 +97,40 @@ export const HeadingsExtension: Extension<HeadingsOptions, HeadingsStorage> = Ex
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function hasHeadingUpdate (tr: Transaction): boolean {
|
||||||
|
if (!tr.docChanged) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let found = false
|
||||||
|
|
||||||
|
tr.mapping.maps.forEach((map, index) =>
|
||||||
|
map.forEach((oldStart, oldEnd, newStart, newEnd) => {
|
||||||
|
const oldDoc = tr.docs[index]
|
||||||
|
const newDoc = tr.docs[index + 1] ?? tr.doc
|
||||||
|
|
||||||
|
oldDoc.nodesBetween(oldStart, oldEnd, (node) => {
|
||||||
|
if (found) {
|
||||||
|
return false
|
||||||
|
} else if (node.type.name === 'heading') {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
newDoc.nodesBetween(newStart, newEnd, (node) => {
|
||||||
|
if (found) {
|
||||||
|
return false
|
||||||
|
} else if (node.type.name === 'heading') {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
function getHeadingDecorations (state: EditorState, idPrefix: string): Decoration[] {
|
function getHeadingDecorations (state: EditorState, idPrefix: string): Decoration[] {
|
||||||
const decorations: Decoration[] = []
|
const decorations: Decoration[] = []
|
||||||
const alreadySeen: Map<string, number> = new Map<string, number>()
|
const alreadySeen: Map<string, number> = new Map<string, number>()
|
||||||
|
Loading…
Reference in New Issue
Block a user