applyRule method
Applies heuristic rule to an operation on a document
and returns
resulting Delta.
Implementation
@override
Delta? applyRule(Delta document, int index, {int? len, Object? data, Attribute? attribute}) {
if (data is! String || data != '\n') {
return null;
}
final itr = DeltaIterator(document);
final prev = itr.skip(index), cur = itr.next();
final blockStyle = Style.fromJson(cur.attributes).getBlockExceptHeader();
// We are not in a block, ignore.
if (cur.isPlain || blockStyle == null) {
return null;
}
// We are not on an empty line, ignore.
if (!_isEmptyLine(prev, cur)) {
return null;
}
// We are on an empty line. Now we need to determine if we are on the
// last line of a block.
// First check if `cur` length is greater than 1, this would indicate
// that it contains multiple newline characters which share the same style.
// This would mean we are not on the last line yet.
// `cur.value as String` is safe since we already called isEmptyLine and
// know it contains a newline
if ((cur.value as String).length > 1) {
// We are not on the last line of this block, ignore.
return null;
}
// Keep looking for the next newline character to see if it shares the same
// block style as `cur`.
final nextNewLine = _getNextNewLine(itr);
if (nextNewLine.operation != null &&
nextNewLine.operation!.attributes != null &&
Style.fromJson(nextNewLine.operation!.attributes).getBlockExceptHeader() == blockStyle) {
// We are not at the end of this block, ignore.
return null;
}
// Here we now know that the line after `cur` is not in the same block
// therefore we can exit this block.
final attributes = cur.attributes ?? <String, dynamic>{};
final k = attributes.keys.firstWhere(Attribute.blockKeysExceptHeader.contains);
attributes[k] = null;
// retain(1) should be '\n', set it with no attribute
return Delta()
..retain(index + (len ?? 0))
..retain(1, attributes);
}