diff --git a/lib/src/models/documents/document.dart b/lib/src/models/documents/document.dart index bc70fba7..62a3efc4 100644 --- a/lib/src/models/documents/document.dart +++ b/lib/src/models/documents/document.dart @@ -16,14 +16,17 @@ import 'style.dart'; /// The rich text document class Document { + /// Creates new empty document. Document() : _delta = Delta()..insert('\n') { _loadDocument(_delta); } + /// Creates new document from provided JSON `data`. Document.fromJson(List data) : _delta = _transform(Delta.fromJson(data)) { _loadDocument(_delta); } + /// Creates new document from provided `delta`. Document.fromDelta(Delta delta) : _delta = delta { _loadDocument(delta); } @@ -33,10 +36,12 @@ class Document { Root get root => _root; + /// Length of this document. int get length => _root.length; Delta _delta; + /// Returns contents of this document as [Delta]. Delta toDelta() => Delta.from(_delta); final Rules _rules = Rules.getInstance(); @@ -50,8 +55,18 @@ class Document { final History _history = History(); + /// Stream of [Change]s applied to this document. Stream> get changes => _observer.stream; + /// Inserts [data] in this document at specified [index]. + /// + /// The `data` parameter can be either a String or an instance of + /// [Embeddable]. + /// + /// Applies heuristic rules before modifying this document and + /// produces a change event with its source set to [ChangeSource.local]. + /// + /// Returns an instance of [Delta] actually composed into this document. Delta insert(int index, Object? data, {int replaceLength = 0}) { assert(index >= 0); assert(data is String || data is Embeddable); @@ -67,6 +82,12 @@ class Document { return delta; } + /// Deletes [length] of characters from this document starting at [index]. + /// + /// This method applies heuristic rules before modifying this document and + /// produces a [Change] with source set to [ChangeSource.local]. + /// + /// Returns an instance of [Delta] actually composed into this document. Delta delete(int index, int len) { assert(index >= 0 && len > 0); final delta = _rules.apply(RuleType.DELETE, this, index, len: len); @@ -76,6 +97,12 @@ class Document { return delta; } + /// Replaces [length] of characters starting at [index] with [data]. + /// + /// This method applies heuristic rules before modifying this document and + /// produces a change event with its source set to [ChangeSource.local]. + /// + /// Returns an instance of [Delta] actually composed into this document. Delta replace(int index, int len, Object? data) { assert(index >= 0); assert(data is String || data is Embeddable); @@ -100,6 +127,14 @@ class Document { return delta; } + /// Formats segment of this document with specified [attribute]. + /// + /// Applies heuristic rules before modifying this document and + /// produces a change event with its source set to [ChangeSource.local]. + /// + /// Returns an instance of [Delta] actually composed into this document. + /// The returned [Delta] may be empty in which case this document remains + /// unchanged and no change event is published to the [changes] stream. Delta format(int index, int len, Attribute? attribute) { assert(index >= 0 && len >= 0 && attribute != null); @@ -128,7 +163,9 @@ class Document { return (res.node as Line).collectAllStyles(res.offset, len); } + /// Returns [Line] located at specified character [offset]. ChildQuery queryChild(int offset) { + // TODO: prevent user from moving caret after last line-break. final res = _root.queryChild(offset, true); if (res.node is Line) { return res; @@ -153,6 +190,16 @@ class Document { return Tuple2(line, segment); } + /// Composes [change] Delta into this document. + /// + /// Use this method with caution as it does not apply heuristic rules to the + /// [change]. + /// + /// It is callers responsibility to ensure that the [change] conforms to + /// the document model semantics and can be composed with the current state + /// of this document. + /// + /// In case the [change] is invalid, behavior of this method is unspecified. void compose(Delta delta, ChangeSource changeSource) { assert(!_observer.isClosed); delta.trim(); @@ -255,6 +302,7 @@ class Document { _history.clear(); } + /// Returns plain text representation of this document. String toPlainText() => _root.children.map((e) => e.toPlainText()).join(); void _loadDocument(Delta doc) { @@ -302,7 +350,11 @@ class Document { } } +/// Source of a [Change]. enum ChangeSource { + /// Change originated from a local action. Typically triggered by user. LOCAL, + + /// Change originated from a remote action. REMOTE, }