prosemirror-transform 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -836,4 +836,4 @@ would be a no-op (an empty slice over an empty range).
836
836
  */
837
837
  declare function replaceStep(doc: Node, from: number, to?: number, slice?: Slice): Step | null;
838
838
 
839
- export { AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MapResult, Mappable, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
839
+ export { AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MapResult, type Mappable, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
package/dist/index.d.ts CHANGED
@@ -836,4 +836,4 @@ would be a no-op (an empty slice over an empty range).
836
836
  */
837
837
  declare function replaceStep(doc: Node, from: number, to?: number, slice?: Slice): Step | null;
838
838
 
839
- export { AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MapResult, Mappable, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
839
+ export { AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MapResult, type Mappable, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
package/dist/index.js CHANGED
@@ -824,7 +824,8 @@ class ReplaceAroundStep extends Step {
824
824
  }
825
825
  map(mapping) {
826
826
  let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
827
- let gapFrom = mapping.map(this.gapFrom, -1), gapTo = mapping.map(this.gapTo, 1);
827
+ let gapFrom = this.from == this.gapFrom ? from.pos : mapping.map(this.gapFrom, -1);
828
+ let gapTo = this.to == this.gapTo ? to.pos : mapping.map(this.gapTo, 1);
828
829
  if ((from.deletedAcross && to.deletedAcross) || gapFrom < from.pos || gapTo > to.pos)
829
830
  return null;
830
831
  return new ReplaceAroundStep(from.pos, to.pos, gapFrom, gapTo, this.slice, this.insert, this.structure);
@@ -936,7 +937,7 @@ function removeMark(tr, from, to, mark) {
936
937
  });
937
938
  matched.forEach(m => tr.step(new RemoveMarkStep(m.from, m.to, m.style)));
938
939
  }
939
- function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch) {
940
+ function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch, clearNewlines = true) {
940
941
  let node = tr.doc.nodeAt(pos);
941
942
  let replSteps = [], cur = pos + 1;
942
943
  for (let i = 0; i < node.childCount; i++) {
@@ -950,7 +951,7 @@ function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch)
950
951
  for (let j = 0; j < child.marks.length; j++)
951
952
  if (!parentType.allowsMarkType(child.marks[j].type))
952
953
  tr.step(new RemoveMarkStep(cur, end, child.marks[j]));
953
- if (child.isText && !parentType.spec.code) {
954
+ if (clearNewlines && child.isText && parentType.whitespace != "pre") {
954
955
  let m, newline = /\r?\n|\r/g, slice;
955
956
  while (m = newline.exec(child.text)) {
956
957
  if (!slice)
@@ -1075,15 +1076,46 @@ function setBlockType(tr, from, to, type, attrs) {
1075
1076
  let mapFrom = tr.steps.length;
1076
1077
  tr.doc.nodesBetween(from, to, (node, pos) => {
1077
1078
  if (node.isTextblock && !node.hasMarkup(type, attrs) && canChangeType(tr.doc, tr.mapping.slice(mapFrom).map(pos), type)) {
1079
+ let convertNewlines = null;
1080
+ if (type.schema.linebreakReplacement) {
1081
+ let pre = type.whitespace == "pre", supportLinebreak = !!type.contentMatch.matchType(type.schema.linebreakReplacement);
1082
+ if (pre && !supportLinebreak)
1083
+ convertNewlines = false;
1084
+ else if (!pre && supportLinebreak)
1085
+ convertNewlines = true;
1086
+ }
1078
1087
  // Ensure all markup that isn't allowed in the new node type is cleared
1079
- tr.clearIncompatible(tr.mapping.slice(mapFrom).map(pos, 1), type);
1088
+ if (convertNewlines === false)
1089
+ replaceLinebreaks(tr, node, pos, mapFrom);
1090
+ clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, undefined, convertNewlines === null);
1080
1091
  let mapping = tr.mapping.slice(mapFrom);
1081
1092
  let startM = mapping.map(pos, 1), endM = mapping.map(pos + node.nodeSize, 1);
1082
1093
  tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new Slice(Fragment.from(type.create(attrs, null, node.marks)), 0, 0), 1, true));
1094
+ if (convertNewlines === true)
1095
+ replaceNewlines(tr, node, pos, mapFrom);
1083
1096
  return false;
1084
1097
  }
1085
1098
  });
1086
1099
  }
1100
+ function replaceNewlines(tr, node, pos, mapFrom) {
1101
+ node.forEach((child, offset) => {
1102
+ if (child.isText) {
1103
+ let m, newline = /\r?\n|\r/g;
1104
+ while (m = newline.exec(child.text)) {
1105
+ let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset + m.index);
1106
+ tr.replaceWith(start, start + 1, node.type.schema.linebreakReplacement.create());
1107
+ }
1108
+ }
1109
+ });
1110
+ }
1111
+ function replaceLinebreaks(tr, node, pos, mapFrom) {
1112
+ node.forEach((child, offset) => {
1113
+ if (child.type == child.type.schema.linebreakReplacement) {
1114
+ let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset);
1115
+ tr.replaceWith(start, start + 1, node.type.schema.text("\n"));
1116
+ }
1117
+ });
1118
+ }
1087
1119
  function canChangeType(doc, pos, type) {
1088
1120
  let $pos = doc.resolve(pos), index = $pos.index();
1089
1121
  return $pos.parent.canReplaceWith(index, index + 1, type);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-transform",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "ProseMirror document transformations",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -24,7 +24,7 @@
24
24
  "url": "git://github.com/prosemirror/prosemirror-transform.git"
25
25
  },
26
26
  "dependencies": {
27
- "prosemirror-model": "^1.0.0"
27
+ "prosemirror-model": "^1.21.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@prosemirror/buildhelper": "^0.1.5",
package/src/mark.ts CHANGED
@@ -72,7 +72,9 @@ export function removeMark(tr: Transform, from: number, to: number, mark?: Mark
72
72
  matched.forEach(m => tr.step(new RemoveMarkStep(m.from, m.to, m.style)))
73
73
  }
74
74
 
75
- export function clearIncompatible(tr: Transform, pos: number, parentType: NodeType, match = parentType.contentMatch) {
75
+ export function clearIncompatible(tr: Transform, pos: number, parentType: NodeType,
76
+ match = parentType.contentMatch,
77
+ clearNewlines = true) {
76
78
  let node = tr.doc.nodeAt(pos)!
77
79
  let replSteps: Step[] = [], cur = pos + 1
78
80
  for (let i = 0; i < node.childCount; i++) {
@@ -85,7 +87,7 @@ export function clearIncompatible(tr: Transform, pos: number, parentType: NodeTy
85
87
  for (let j = 0; j < child.marks.length; j++) if (!parentType.allowsMarkType(child.marks[j].type))
86
88
  tr.step(new RemoveMarkStep(cur, end, child.marks[j]))
87
89
 
88
- if (child.isText && !parentType.spec.code) {
90
+ if (clearNewlines && child.isText && parentType.whitespace != "pre") {
89
91
  let m, newline = /\r?\n|\r/g, slice
90
92
  while (m = newline.exec(child.text!)) {
91
93
  if (!slice) slice = new Slice(Fragment.from(parentType.schema.text(" ", parentType.allowedMarks(child.marks))),
@@ -134,7 +134,8 @@ export class ReplaceAroundStep extends Step {
134
134
 
135
135
  map(mapping: Mappable) {
136
136
  let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1)
137
- let gapFrom = mapping.map(this.gapFrom, -1), gapTo = mapping.map(this.gapTo, 1)
137
+ let gapFrom = this.from == this.gapFrom ? from.pos : mapping.map(this.gapFrom, -1)
138
+ let gapTo = this.to == this.gapTo ? to.pos : mapping.map(this.gapTo, 1)
138
139
  if ((from.deletedAcross && to.deletedAcross) || gapFrom < from.pos || gapTo > to.pos) return null
139
140
  return new ReplaceAroundStep(from.pos, to.pos, gapFrom, gapTo, this.slice, this.insert, this.structure)
140
141
  }
package/src/structure.ts CHANGED
@@ -2,6 +2,7 @@ import {Slice, Fragment, NodeRange, NodeType, Node, Mark, Attrs, ContentMatch} f
2
2
 
3
3
  import {Transform} from "./transform"
4
4
  import {ReplaceStep, ReplaceAroundStep} from "./replace_step"
5
+ import {clearIncompatible} from "./mark"
5
6
 
6
7
  function canCut(node: Node, start: number, end: number) {
7
8
  return (start == 0 || node.canReplace(start, node.childCount)) &&
@@ -116,17 +117,46 @@ export function setBlockType(tr: Transform, from: number, to: number, type: Node
116
117
  let mapFrom = tr.steps.length
117
118
  tr.doc.nodesBetween(from, to, (node, pos) => {
118
119
  if (node.isTextblock && !node.hasMarkup(type, attrs) && canChangeType(tr.doc, tr.mapping.slice(mapFrom).map(pos), type)) {
120
+ let convertNewlines = null
121
+ if (type.schema.linebreakReplacement) {
122
+ let pre = type.whitespace == "pre", supportLinebreak = !!type.contentMatch.matchType(type.schema.linebreakReplacement)
123
+ if (pre && !supportLinebreak) convertNewlines = false
124
+ else if (!pre && supportLinebreak) convertNewlines = true
125
+ }
119
126
  // Ensure all markup that isn't allowed in the new node type is cleared
120
- tr.clearIncompatible(tr.mapping.slice(mapFrom).map(pos, 1), type)
127
+ if (convertNewlines === false) replaceLinebreaks(tr, node, pos, mapFrom)
128
+ clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, undefined, convertNewlines === null)
121
129
  let mapping = tr.mapping.slice(mapFrom)
122
130
  let startM = mapping.map(pos, 1), endM = mapping.map(pos + node.nodeSize, 1)
123
131
  tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1,
124
132
  new Slice(Fragment.from(type.create(attrs, null, node.marks)), 0, 0), 1, true))
133
+ if (convertNewlines === true) replaceNewlines(tr, node, pos, mapFrom)
125
134
  return false
126
135
  }
127
136
  })
128
137
  }
129
138
 
139
+ function replaceNewlines(tr: Transform, node: Node, pos: number, mapFrom: number) {
140
+ node.forEach((child, offset) => {
141
+ if (child.isText) {
142
+ let m, newline = /\r?\n|\r/g
143
+ while (m = newline.exec(child.text!)) {
144
+ let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset + m.index)
145
+ tr.replaceWith(start, start + 1, node.type.schema.linebreakReplacement!.create())
146
+ }
147
+ }
148
+ })
149
+ }
150
+
151
+ function replaceLinebreaks(tr: Transform, node: Node, pos: number, mapFrom: number) {
152
+ node.forEach((child, offset) => {
153
+ if (child.type == child.type.schema.linebreakReplacement) {
154
+ let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset)
155
+ tr.replaceWith(start, start + 1, node.type.schema.text("\n"))
156
+ }
157
+ })
158
+ }
159
+
130
160
  function canChangeType(doc: Node, pos: number, type: NodeType) {
131
161
  let $pos = doc.resolve(pos), index = $pos.index()
132
162
  return $pos.parent.canReplaceWith(index, index + 1, type)