lib0 1.0.0-rc.28 → 1.0.0-rc.29

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lib0",
3
- "version": "1.0.0-rc.28",
3
+ "version": "1.0.0-rc.29",
4
4
  "description": "isomorphic utility functions",
5
5
  "sideEffects": false,
6
6
  "type": "module",
@@ -96,21 +96,28 @@ const contentFmt = (conf, attribution, isData) => {
96
96
 
97
97
  /**
98
98
  * Build the `y-attributed-attrs` format value from a child node's attribute-op attributions — the
99
- * lift that lets the *parent* op carry a node's attr provenance (attr ops have no format slot). For a
100
- * `modifyAttr` op a `null` attribution is an instruction *clear* (⇒ `{ <key>: null }`); for a settled
101
- * `setAttr`/`deleteAttr` op `null` is "none" (skipped).
99
+ * lift that lets the *parent* op carry a node's attr provenance (attr ops have no format slot).
100
+ * Whether a `null` attribution clears or is skipped depends on the *container context* `instr`, not
101
+ * only the op kind: inside a `modify` op (`instr` true) the node delta is a change, so a
102
+ * `setAttr(key, value, null)` means "the attr is no longer attributed" (e.g. a suggestion was
103
+ * accepted — `diff` emits exactly this op when only the attribution went away) ⇒ emit the
104
+ * `{ <key>: null }` clear instruction. Inside an `insert` op (`instr` false) the node delta is
105
+ * settled data, where `null` is simply "unattributed" ⇒ skip. A `modifyAttr` op is an instruction in
106
+ * either context. The emitted map is *partial* — downstream consumers must merge it per-key
107
+ * (`null` deletes, value sets), never replace the whole map.
102
108
  *
103
109
  * @param {Conf} conf
104
110
  * @param {import('../delta.js').DeltaAny} node
111
+ * @param {boolean} instr `true` when `node` is a change (`modify` op value), `false` for settled data (`insert` op element)
105
112
  * @return {{[k:string]:any}|undefined}
106
113
  */
107
- const attrsFmt = (conf, node) => {
114
+ const attrsFmt = (conf, node, instr) => {
108
115
  const handler = conf.attrs
109
116
  if (handler == null) return undefined
110
117
  /** @type {{[k:string]:any}} */
111
118
  const map = {}
112
119
  for (const op of node.attrs) {
113
- const isInstr = delta.$modifyAttrOp.check(op) // modifyAttr carries an attribution *instruction*; setAttr/deleteAttr resolved data
120
+ const isInstr = instr || delta.$modifyAttrOp.check(op)
114
121
  const a = op.attribution
115
122
  if (a === undefined) continue // instruction skip
116
123
  if (a === null) {
@@ -202,7 +209,7 @@ const transform = (conf, d, fwd) => {
202
209
  // children needing distinct `y-attributed-attrs` land in their own insert ops automatically
203
210
  for (const el of op.insert) {
204
211
  if (delta.$deltaAny.check(el)) {
205
- out.insert([transform(conf, el, true).b], combineFmt(op.format, contentFmt(conf, op.attribution, true), attrsFmt(conf, el)))
212
+ out.insert([transform(conf, el, true).b], combineFmt(op.format, contentFmt(conf, op.attribution, true), attrsFmt(conf, el, false)))
206
213
  } else {
207
214
  out.insert([el], combineFmt(op.format, contentFmt(conf, op.attribution, true)))
208
215
  }
@@ -210,7 +217,7 @@ const transform = (conf, d, fwd) => {
210
217
  } else if (delta.$deleteOp.check(op)) {
211
218
  out.delete(op.delete)
212
219
  } else { // $modifyOp
213
- out.modify(transform(conf, op.value, true).b, combineFmt(op.format, contentFmt(conf, op.attribution, false), attrsFmt(conf, op.value)))
220
+ out.modify(transform(conf, op.value, true).b, combineFmt(op.format, contentFmt(conf, op.attribution, false), attrsFmt(conf, op.value, true)))
214
221
  }
215
222
  }
216
223
  } else {