Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package com.atlassian.prosemirror.transform
import com.atlassian.prosemirror.model.ContentMatch
import com.atlassian.prosemirror.model.Fragment
import com.atlassian.prosemirror.model.Mark
import com.atlassian.prosemirror.model.MarkType
import com.atlassian.prosemirror.model.Node
import com.atlassian.prosemirror.model.NodeType
import com.atlassian.prosemirror.model.Slice
import kotlin.math.max
import kotlin.math.min
@Suppress("ComplexMethod")
fun addMark(tr: Transform, from: Int, to: Int, mark: Mark) {
val removed = mutableListOf()
val added = mutableListOf()
var removing: RemoveMarkStep? = null
var adding: AddMarkStep? = null
tr.doc.nodesBetween(from, to, { node: Node, pos: Int, parent: Node?, index: Int ->
if (!node.isInline) return@nodesBetween true
val marks = node.marks
if (!mark.isInSet(marks) && parent!!.type.allowsMarkType(mark.type)) {
val start = max(pos, from)
val end = min(pos + node.nodeSize, to)
val newSet = mark.addToSet(marks)
for (mark in marks) {
if (!mark.isInSet(newSet)) {
val r = removing
if (r != null && r.to == start && r.mark == mark) {
r.to = end
} else {
removing = RemoveMarkStep(start, end, mark).also { removed.add(it) }
}
}
}
val currentAdding = adding
if (currentAdding != null && currentAdding.to == start) {
currentAdding.to = end
} else {
adding = AddMarkStep(start, end, mark).also { added.add(it) }
}
}
false
})
removed.forEach { s -> tr.step(s) }
added.forEach { s -> tr.step(s) }
}
data class MatchedMark(val style: Mark, val from: Int, var to: Int, var step: Int)
fun removeMark(tr: Transform, from: Int, to: Int, mark: Mark?) {
val matched = mutableListOf()
var step = 0
tr.doc.nodesBetween(from, to, { node: Node, pos: Int, parent: Node?, index: Int ->
if (!node.isInline) return@nodesBetween true
step++
var toRemove: List? = null
if (mark != null) {
if (mark.isInSet(node.marks)) toRemove = listOf(mark)
} else {
toRemove = node.marks
}
if (toRemove != null && toRemove.isNotEmpty()) {
val end = min(pos + node.nodeSize, to)
for (style in toRemove) {
var found: MatchedMark? = null
for (m in matched) {
if (m.step == step - 1 && style == m.style) found = m
}
if (found != null) {
found.to = end
found.step = step
} else {
matched.add(MatchedMark(style, from = max(pos, from), to = end, step))
}
}
}
false
})
matched.forEach { m ->
tr.step(RemoveMarkStep(m.from, m.to, m.style))
}
}
fun removeMark(tr: Transform, from: Int, to: Int, mark: MarkType?) {
data class MatchedMark(val style: Mark, val from: Int, var to: Int, var step: Int)
val matched = mutableListOf()
var step = 0
tr.doc.nodesBetween(from, to, { node: Node, pos: Int, parent: Node?, index: Int ->
if (!node.isInline) return@nodesBetween false
step++
var toRemove: MutableList? = null
if (mark != null) {
var set = node.marks
var found = mark.isInSet(set)
while (found != null) {
if (toRemove == null) toRemove = mutableListOf()
toRemove.add(found)
set = found.removeFromSet(set)
found = mark.isInSet(set)
}
} else {
toRemove = node.marks.toMutableList()
}
if (toRemove != null && toRemove.isNotEmpty()) {
val end = min(pos + node.nodeSize, to)
for (style in toRemove) {
var found: MatchedMark? = null
for (m in matched) {
if (m.step == step - 1 && style == m.style) found = m
}
if (found != null) {
found.to = end
found.step = step
} else {
matched.add(MatchedMark(style, from = max(pos, from), to = end, step))
}
}
}
false
})
matched.forEach { m ->
tr.step(RemoveMarkStep(m.from, m.to, m.style))
}
}
fun clearIncompatible(tr: Transform, pos: Int, parentType: NodeType, match: ContentMatch? = parentType.contentMatch) {
var match = match ?: parentType.contentMatch
val node = tr.doc.nodeAt(pos)!!
val delSteps = mutableListOf()
var cur = pos + 1
for (i in 0 until node.childCount) {
val child = node.child(i)
val end = cur + child.nodeSize
val allowed = match.matchType(child.type)
if (allowed == null) {
delSteps.add(ReplaceStep(cur, end, Slice.empty))
} else {
match = allowed
for (j in 0 until child.marks.size)
if (!parentType.allowsMarkType(child.marks[j].type)) {
tr.step(RemoveMarkStep(cur, end, child.marks[j]))
}
}
cur = end
}
if (!match.validEnd) {
val fill = match.fillBefore(Fragment.empty, true)
tr.replace(cur, cur, Slice(fill!!, 0, 0))
}
for (i in delSteps.size - 1 downTo 0) {
tr.step(delSteps[i])
}
}