implement attributes on Y.Text

This commit is contained in:
Kevin Jahns 2020-11-13 12:40:53 +01:00
parent e1f0324840
commit 0aca7bbefa
3 changed files with 110 additions and 5 deletions

View File

@ -21,6 +21,10 @@ import {
iterateDeletedStructs, iterateDeletedStructs,
iterateStructs, iterateStructs,
findMarker, findMarker,
typeMapDelete,
typeMapSet,
typeMapGet,
typeMapGetAll,
updateMarkerChanges, updateMarkerChanges,
ArraySearchMarker, AbstractUpdateDecoder, AbstractUpdateEncoder, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line ArraySearchMarker, AbstractUpdateDecoder, AbstractUpdateEncoder, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line
} from '../internals.js' } from '../internals.js'
@ -512,13 +516,32 @@ export class YTextEvent extends YEvent {
/** /**
* @param {YText} ytext * @param {YText} ytext
* @param {Transaction} transaction * @param {Transaction} transaction
* @param {Set<any>} subs The keys that changed
*/ */
constructor (ytext, transaction) { constructor (ytext, transaction, subs) {
super(ytext, transaction) super(ytext, transaction)
/** /**
* @type {Array<DeltaItem>|null} * @type {Array<DeltaItem>|null}
*/ */
this._delta = null this._delta = null
/**
* Whether the children changed.
* @type {Boolean}
* @private
*/
this.childListChanged = false
/**
* Set of all changed attributes.
* @type {Set<string>}
*/
this.keysChanged = new Set()
subs.forEach((sub) => {
if (sub === null) {
this.childListChanged = true
} else {
this.keysChanged.add(sub)
}
})
} }
/** /**
@ -779,7 +802,7 @@ export class YText extends AbstractType {
*/ */
_callObserver (transaction, parentSubs) { _callObserver (transaction, parentSubs) {
super._callObserver(transaction, parentSubs) super._callObserver(transaction, parentSubs)
const event = new YTextEvent(this, transaction) const event = new YTextEvent(this, transaction, parentSubs)
const doc = transaction.doc const doc = transaction.doc
// If a remote change happened, we try to cleanup potential formatting duplicates. // If a remote change happened, we try to cleanup potential formatting duplicates.
if (!transaction.local) { if (!transaction.local) {
@ -1111,6 +1134,74 @@ export class YText extends AbstractType {
} }
} }
/**
* Removes an attribute.
*
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
*
* @param {String} attributeName The attribute name that is to be removed.
*
* @public
*/
removeAttribute (attributeName) {
if (this.doc !== null) {
transact(this.doc, transaction => {
typeMapDelete(transaction, this, attributeName)
})
} else {
/** @type {Array<function>} */ (this._pending).push(() => this.removeAttribute(attributeName))
}
}
/**
* Sets or updates an attribute.
*
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
*
* @param {String} attributeName The attribute name that is to be set.
* @param {any} attributeValue The attribute value that is to be set.
*
* @public
*/
setAttribute (attributeName, attributeValue) {
if (this.doc !== null) {
transact(this.doc, transaction => {
typeMapSet(transaction, this, attributeName, attributeValue)
})
} else {
/** @type {Array<function>} */ (this._pending).push(() => this.setAttribute(attributeName, attributeValue))
}
}
/**
* Returns an attribute value that belongs to the attribute name.
*
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
*
* @param {String} attributeName The attribute name that identifies the
* queried value.
* @return {any} The queried attribute value.
*
* @public
*/
getAttribute (attributeName) {
return /** @type {any} */ (typeMapGet(this, attributeName))
}
/**
* Returns all attribute name/value pairs in a JSON Object.
*
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
*
* @param {Snapshot} [snapshot]
* @return {Object<string, any>} A JSON Object that describes the attributes.
*
* @public
*/
getAttributes (snapshot) {
return typeMapGetAll(this)
}
/** /**
* @param {AbstractUpdateEncoder} encoder * @param {AbstractUpdateEncoder} encoder
*/ */

View File

@ -1,7 +1,7 @@
import { import {
YEvent, YEvent,
YXmlElement, YXmlFragment, Transaction // eslint-disable-line YXmlText, YXmlElement, YXmlFragment, Transaction // eslint-disable-line
} from '../internals.js' } from '../internals.js'
/** /**
@ -9,7 +9,7 @@ import {
*/ */
export class YXmlEvent extends YEvent { export class YXmlEvent extends YEvent {
/** /**
* @param {YXmlElement|YXmlFragment} target The target on which the event is created. * @param {YXmlElement|YXmlText|YXmlFragment} target The target on which the event is created.
* @param {Set<string|null>} subs The set of changed attributes. `null` is included if the * @param {Set<string|null>} subs The set of changed attributes. `null` is included if the
* child list changed. * child list changed.
* @param {Transaction} transaction The transaction instance with wich the * @param {Transaction} transaction The transaction instance with wich the
@ -25,7 +25,7 @@ export class YXmlEvent extends YEvent {
this.childListChanged = false this.childListChanged = false
/** /**
* Set of all changed attributes. * Set of all changed attributes.
* @type {Set<string|null>} * @type {Set<string>}
*/ */
this.attributesChanged = new Set() this.attributesChanged = new Set()
subs.forEach((sub) => { subs.forEach((sub) => {

View File

@ -73,3 +73,17 @@ export const testTreewalker = tc => {
t.assert(xml0.querySelector('p') === paragraph1, 'querySelector found paragraph1') t.assert(xml0.querySelector('p') === paragraph1, 'querySelector found paragraph1')
compare(users) compare(users)
} }
/**
* @param {t.TestCase} tc
*/
export const testYtextAttributes = tc => {
const ydoc = new Y.Doc()
const ytext = /** @type {Y.XmlText} */ (ydoc.get('', Y.XmlText))
ytext.observe(event => {
t.compare(event.changes.keys.get('test'), { action: 'add', oldValue: undefined })
})
ytext.setAttribute('test', 42)
t.compare(ytext.getAttribute('test'), 42)
t.compare(ytext.getAttributes(), { test: 42 })
}