Skip to content

Commit

Permalink
Bump prosemirror-transform to 1.9.0 (#54)
Browse files Browse the repository at this point in the history
- Bump prosemirror-transform to 1.9.0
- Created `CustomNodeBuilder` so that it is easier to port the
TypeScript tests when they use custom schemas.
  • Loading branch information
nlam-atlassian authored Nov 1, 2024
1 parent 9c180c1 commit b592057
Show file tree
Hide file tree
Showing 26 changed files with 2,068 additions and 710 deletions.
260 changes: 128 additions & 132 deletions model/config/ktlint/baseline.xml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,11 @@ import com.atlassian.prosemirror.testbuilder.PMNodeBuilder.Companion.pos
import com.fleeksoft.ksoup.nodes.Element
import com.fleeksoft.ksoup.nodes.Node as DOMNode
import assertk.assertions.isTrue
import com.atlassian.prosemirror.testbuilder.CustomNodeBuildCompanion
import com.atlassian.prosemirror.testbuilder.CustomNodeBuilder
import com.fleeksoft.ksoup.nodes.TextNode
import kotlin.test.assertFailsWith

class CommentNodeBuilder(
pos: Int = 0,
marks: List<Mark> = emptyList(),
override val schema: Schema = testSchema
) : NodeBuilder<CommentNodeBuilder>(pos, marks, schema) {
override val checked: Boolean
get() = false

override fun create(pos: Int, marks: List<Mark>, schema: Schema): NodeBuilder<CommentNodeBuilder> {
return CommentNodeBuilder(pos, marks, schema)
}
}

class CustomNodeBuildCompanion(schema: Schema): NodeBuildCompanion<CommentNodeBuilder>(schema) {
override val checked: Boolean
get() = false

override fun create(): CommentNodeBuilder {
return CommentNodeBuilder(schema = schema)
}
}

class DomTest {
//region DOMParser
fun test(doc: Node, html: String) {
Expand Down Expand Up @@ -201,7 +181,7 @@ class DomTest {
)
)

fun NodeBuilder<CommentNodeBuilder>.comment(func: NodeBuilder<CommentNodeBuilder>.() -> Unit) =
fun NodeBuilder<CustomNodeBuilder>.comment(func: NodeBuilder<CustomNodeBuilder>.() -> Unit) =
mark("comment", func)

val doc = CustomNodeBuildCompanion(schemaWithComment).doc {
Expand Down Expand Up @@ -285,7 +265,7 @@ class DomTest {
)
val b = CustomNodeBuildCompanion(markSchema)

fun NodeBuilder<CommentNodeBuilder>.test(func: NodeBuilder<CommentNodeBuilder>.() -> Unit) =
fun NodeBuilder<CustomNodeBuilder>.test(func: NodeBuilder<CustomNodeBuilder>.() -> Unit) =
mark("test", func)

test(
Expand Down
7 changes: 7 additions & 0 deletions test-builder/config/ktlint/baseline.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<baseline version="1.0">
<file name="src/commonMain/kotlin/com/atlassian/prosemirror/testbuilder/CustomNodeBuilder.kt">
<error line="14" column="25" source="standard:function-signature" />
<error line="14" column="35" source="standard:function-signature" />
<error line="14" column="54" source="standard:function-signature" />
<error line="14" column="68" source="standard:function-signature" />
<error line="19" column="47" source="standard:colon-spacing" />
</file>
<file name="src/commonMain/kotlin/com/atlassian/prosemirror/testbuilder/NodeBuilder.kt">
<error line="12" column="26" source="standard:multiline-expression-wrapping" />
<error line="24" column="1" source="standard:no-empty-first-line-in-class-body" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.atlassian.prosemirror.testbuilder

import com.atlassian.prosemirror.model.Mark
import com.atlassian.prosemirror.model.Schema

class CustomNodeBuilder(
pos: Int = 0,
marks: List<Mark> = emptyList(),
override val schema: Schema
) : NodeBuilder<CustomNodeBuilder>(pos, marks, schema) {
override val checked: Boolean
get() = false

override fun create(pos: Int, marks: List<Mark>, schema: Schema): NodeBuilder<CustomNodeBuilder> {
return CustomNodeBuilder(pos, marks, schema)
}
}

class CustomNodeBuildCompanion(schema: Schema): NodeBuildCompanion<CustomNodeBuilder>(schema) {
override val checked: Boolean
get() = false

override fun create(): CustomNodeBuilder {
return CustomNodeBuilder(schema = schema)
}
}
2 changes: 1 addition & 1 deletion transform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,5 @@ transformations or determining whether they are even possible.
@dropPoint

## Versioning
This module is a port of version [1.6.0](https://github.com/ProseMirror/prosemirror-transform/releases/tag/1.6.0)
This module is a port of version [1.9.0](https://github.com/ProseMirror/prosemirror-transform/releases/tag/1.9.0)
of prosemirror-transform
995 changes: 560 additions & 435 deletions transform/config/ktlint/baseline.xml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package com.atlassian.prosemirror.transform

import com.atlassian.prosemirror.model.Fragment
import com.atlassian.prosemirror.model.Node
import com.atlassian.prosemirror.model.RangeError
import com.atlassian.prosemirror.model.Schema
import com.atlassian.prosemirror.model.Slice
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonObjectBuilder
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.booleanOrNull
import kotlinx.serialization.json.put
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonPrimitive

/// Update an attribute in a specific node.
class AttrStep(
/// The position of the target node.
val pos: Int,
/// The attribute to set.
val attr: String,
// The attribute's new value.
val value: Any?
) : Step() {
override val from: Int
get() = 0
override val to: Int
get() = 0

override fun apply(doc: Node): StepResult {
val node = doc.nodeAt(pos) ?: return StepResult.fail("No node at attribute step's position")
val attrs = node.attrs.toMutableMap()
attrs[attr] = value
val updated = node.type.create(attrs, null as Fragment?, node.marks)
return StepResult.fromReplace(doc, pos, pos + 1, Slice(Fragment.from(updated), 0, if (node.isLeaf) 0 else 1))
}

override fun getMap() = StepMap.empty

override fun invert(doc: Node): Step {
return AttrStep(pos, attr, doc.nodeAt(pos)!!.attrs[attr])
}

override fun map(mapping: Mappable): Step? {
val pos = mapping.mapResult(this.pos, 1)
return if (pos.deletedAfter) null else AttrStep(pos.pos, attr, value)
}

override fun toJSON() =
buildJsonObject {
put("stepType", "attr")
put("pos", pos)
put("attr", attr)
put("value", value)
}

companion object : StepJsonParser<AttrStep> {
init {
jsonID("attr", this)
}
override fun fromJSON(schema: Schema, json: JsonObject): AttrStep {
val pos = json["pos"]?.jsonPrimitive?.intOrNull ?: throw RangeError("Invalid input for AttrStep.fromJSON")
val attr = json["attr"]?.jsonPrimitive?.contentOrNull ?: throw RangeError("Invalid input for AttrStep.fromJSON")
val value = json["value"]?.jsonPrimitive?.anyOrNull()
return AttrStep(pos, attr, value)
}
}
}

/// Update an attribute in the doc node.
class DocAttrStep(
/// The attribute to set.
val attr: String,
// The attribute's new value.
val value: Any?
) : Step() {
override val from: Int
get() = 0
override val to: Int
get() = 0

override fun apply(doc: Node): StepResult {
val attrs = doc.attrs.toMutableMap()
attrs[attr] = value
val updated = doc.type.create(attrs, doc.content, doc.marks)
return StepResult.ok(updated)
}

override fun getMap() = StepMap.empty

override fun invert(doc: Node): Step {
return DocAttrStep(attr, doc.attrs[attr])
}

override fun map(mapping: Mappable): Step {
return this
}

override fun toJSON() =
buildJsonObject {
put("stepType", "docAttr")
put("attr", attr)
put("value", value)
}

companion object : StepJsonParser<DocAttrStep> {
init {
jsonID("docAttr", this)
}

override fun fromJSON(schema: Schema, json: JsonObject): DocAttrStep {
val attr = json["attr"]?.jsonPrimitive?.contentOrNull ?: throw RangeError("Invalid input for DocAttrStep.fromJSON")
val value = json["value"]?.jsonPrimitive?.anyOrNull()
return DocAttrStep(attr, value)
}
}
}

fun JsonObjectBuilder.put(key: String, value: Any?): JsonElement? = value?.let {
when (it) {
is String -> put(key, it)
is Int -> put(key, it)
is Boolean -> put(key, it)
else -> put(key, it.toString())
}
}

fun JsonPrimitive.anyOrNull(): Any? = intOrNull ?: booleanOrNull ?: contentOrNull
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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 com.atlassian.prosemirror.model.Whitespace
import kotlin.math.max
import kotlin.math.min

Expand Down Expand Up @@ -126,31 +127,49 @@ fun removeMark(tr: Transform, from: Int, to: Int, mark: MarkType?) {
}
}

fun clearIncompatible(tr: Transform, pos: Int, parentType: NodeType, match: ContentMatch? = parentType.contentMatch) {
fun clearIncompatible(
tr: Transform,
pos: Int,
parentType: NodeType,
match: ContentMatch? = parentType.contentMatch,
clearNewlines: Boolean = true
) {
var match = match ?: parentType.contentMatch
val node = tr.doc.nodeAt(pos)!!
val delSteps = mutableListOf<Step>()
val replSteps = mutableListOf<Step>()
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))
replSteps.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]))
}
if (clearNewlines && child.isText && parentType.whitespace != Whitespace.PRE) {
val newline = Regex("\r?\n|\r")
var slice: Slice? = null
val text = child.text ?: ""
newline.findAll(text).forEach {
if (slice == null) {
slice = Slice(Fragment.from(parentType.schema.text(" ", parentType.allowedMarks(child.marks))),
0, 0)
}
replSteps.add(ReplaceStep(cur + it.range.first, cur + it.range.last + 1, slice!!))
}
}
}
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])
for (i in replSteps.size - 1 downTo 0) {
tr.step(replSteps[i])
}
}
Loading

0 comments on commit b592057

Please sign in to comment.