mirror of
https://github.com/ueberdosis/tiptap.git
synced 2024-11-24 03:39:01 +08:00
Refactor NodePos class to support block nodes (#4841)
Co-authored-by: bdbch <dominik@bdbch.com>
This commit is contained in:
parent
ac67aa49af
commit
56c228a4f4
@ -8,23 +8,35 @@ import { Content, Range } from './types.js'
|
||||
export class NodePos {
|
||||
private resolvedPos: ResolvedPos
|
||||
|
||||
private isBlock: boolean
|
||||
|
||||
private editor: Editor
|
||||
|
||||
constructor(pos: ResolvedPos, editor: Editor) {
|
||||
this.resolvedPos = pos
|
||||
this.editor = editor
|
||||
private get name(): string {
|
||||
return this.node.type.name
|
||||
}
|
||||
|
||||
constructor(pos: ResolvedPos, editor: Editor, isBlock = false, node: Node | null = null) {
|
||||
this.isBlock = isBlock
|
||||
this.resolvedPos = pos
|
||||
this.editor = editor
|
||||
this.currentNode = node
|
||||
}
|
||||
|
||||
private currentNode: Node | null = null
|
||||
|
||||
get node(): Node {
|
||||
return this.resolvedPos.node()
|
||||
return this.currentNode || this.resolvedPos.node()
|
||||
}
|
||||
|
||||
get element(): HTMLElement {
|
||||
return this.editor.view.domAtPos(this.pos).node as HTMLElement
|
||||
}
|
||||
|
||||
public actualDepth: number | null = null
|
||||
|
||||
get depth(): number {
|
||||
return this.resolvedPos.depth
|
||||
return this.actualDepth ?? this.resolvedPos.depth
|
||||
}
|
||||
|
||||
get pos(): number {
|
||||
@ -36,7 +48,20 @@ export class NodePos {
|
||||
}
|
||||
|
||||
set content(content: Content) {
|
||||
this.editor.commands.insertContentAt({ from: this.from, to: this.to }, content)
|
||||
let from = this.from
|
||||
let to = this.to
|
||||
|
||||
if (this.isBlock) {
|
||||
if (this.content.size === 0) {
|
||||
console.error(`You can’t set content on a block node. Tried to set content on ${this.name} at ${this.pos}`)
|
||||
return
|
||||
}
|
||||
|
||||
from = this.from + 1
|
||||
to = this.to - 1
|
||||
}
|
||||
|
||||
this.editor.commands.insertContentAt({ from, to }, content)
|
||||
}
|
||||
|
||||
get attributes() : { [key: string]: any } {
|
||||
@ -52,6 +77,10 @@ export class NodePos {
|
||||
}
|
||||
|
||||
get from(): number {
|
||||
if (this.isBlock) {
|
||||
return this.pos
|
||||
}
|
||||
|
||||
return this.resolvedPos.start(this.resolvedPos.depth)
|
||||
}
|
||||
|
||||
@ -63,6 +92,10 @@ export class NodePos {
|
||||
}
|
||||
|
||||
get to(): number {
|
||||
if (this.isBlock) {
|
||||
return this.pos + this.size
|
||||
}
|
||||
|
||||
return this.resolvedPos.end(this.resolvedPos.depth) + (this.node.isText ? 0 : 1)
|
||||
}
|
||||
|
||||
@ -78,7 +111,7 @@ export class NodePos {
|
||||
}
|
||||
|
||||
get before(): NodePos | null {
|
||||
let $pos = this.resolvedPos.doc.resolve(this.from - 2)
|
||||
let $pos = this.resolvedPos.doc.resolve(this.from - (this.isBlock ? 1 : 2))
|
||||
|
||||
if ($pos.depth !== this.depth) {
|
||||
$pos = this.resolvedPos.doc.resolve(this.from - 3)
|
||||
@ -88,7 +121,7 @@ export class NodePos {
|
||||
}
|
||||
|
||||
get after(): NodePos | null {
|
||||
let $pos = this.resolvedPos.doc.resolve(this.to + 2)
|
||||
let $pos = this.resolvedPos.doc.resolve(this.to + (this.isBlock ? 2 : 1))
|
||||
|
||||
if ($pos.depth !== this.depth) {
|
||||
$pos = this.resolvedPos.doc.resolve(this.to + 3)
|
||||
@ -101,14 +134,22 @@ export class NodePos {
|
||||
const children: NodePos[] = []
|
||||
|
||||
this.node.content.forEach((node, offset) => {
|
||||
const targetPos = this.pos + offset + 1
|
||||
const isBlock = node.isBlock && !node.isTextblock
|
||||
|
||||
const targetPos = this.pos + offset + (isBlock ? 0 : 1)
|
||||
const $pos = this.resolvedPos.doc.resolve(targetPos)
|
||||
|
||||
if ($pos.depth === this.depth) {
|
||||
if (!isBlock && $pos.depth <= this.depth) {
|
||||
return
|
||||
}
|
||||
|
||||
children.push(new NodePos($pos, this.editor))
|
||||
const childNodePos = new NodePos($pos, this.editor, isBlock, isBlock ? node : null)
|
||||
|
||||
if (isBlock) {
|
||||
childNodePos.actualDepth = this.depth + 1
|
||||
}
|
||||
|
||||
children.push(new NodePos($pos, this.editor, isBlock, isBlock ? node : null))
|
||||
})
|
||||
|
||||
return children
|
||||
@ -160,14 +201,14 @@ export class NodePos {
|
||||
let nodes: NodePos[] = []
|
||||
|
||||
// iterate through children recursively finding all nodes which match the selector with the node name
|
||||
if (!this.children || this.children.length === 0) {
|
||||
if (this.isBlock || !this.children || this.children.length === 0) {
|
||||
return nodes
|
||||
}
|
||||
|
||||
this.children.forEach(node => {
|
||||
if (node.node.type.name === selector) {
|
||||
this.children.forEach(childPos => {
|
||||
if (childPos.node.type.name === selector) {
|
||||
if (Object.keys(attributes).length > 0) {
|
||||
const nodeAttributes = node.node.attrs
|
||||
const nodeAttributes = childPos.node.attrs
|
||||
const attrKeys = Object.keys(attributes)
|
||||
|
||||
for (let index = 0; index < attrKeys.length; index += 1) {
|
||||
@ -179,14 +220,14 @@ export class NodePos {
|
||||
}
|
||||
}
|
||||
|
||||
nodes.push(node)
|
||||
nodes.push(childPos)
|
||||
|
||||
if (firstItemOnly) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
nodes = nodes.concat(node.querySelectorAll(selector))
|
||||
nodes = nodes.concat(childPos.querySelectorAll(selector))
|
||||
})
|
||||
|
||||
return nodes
|
||||
|
Loading…
Reference in New Issue
Block a user