applyRule method
Applies heuristic rule to an operation on a document
and returns
resulting Delta.
Implementation
@override
Delta? applyRule(
Document document,
int index, {
int? len,
Object? data,
Attribute? attribute,
}) {
if (data is! String || data.contains('\n')) {
return null;
}
final documentDelta = document.toDelta();
final itr = DeltaIterator(documentDelta);
len ??= 0;
var prev = itr.skip(len == 0 ? index : index + 1);
var excludeLink = false;
/// Process simple insertions at start of line
if (len == 0) {
final currLine = itr.next();
/// Prevent links extending beyond the link's text label.
excludeLink =
currLine.attributes?.containsKey(Attribute.link.key) != true &&
prev?.attributes?.containsKey(Attribute.link.key) == true;
/// Trap for previous is not text
if (prev?.data is! String) {
prev = currLine;
excludeLink = true;
} else {
final prevData = prev!.data as String;
if (prevData.endsWith('\n')) {
/// If current line is empty get attributes from a prior line
final currData =
currLine.data is String ? currLine.data as String : null;
if (currData?.startsWith('\n') == true) {
if (prevData.trimRight().isEmpty) {
final back =
DeltaIterator(documentDelta).skip(index - prevData.length);
/// Prevent link attribute from propagating over line break
if (back != null &&
back.data is String &&
back.attributes?.containsKey(Attribute.link.key) != true) {
prev = back;
}
}
} else {
prev = currLine;
excludeLink = true;
}
}
}
}
final attributes = <String, dynamic>{};
if (prev?.attributes != null) {
for (final entry in prev!.attributes!.entries) {
if (Attribute.inlineKeys.contains(entry.key)) {
attributes[entry.key] = entry.value;
}
}
}
if (attributes.isEmpty) {
return null;
}
if (excludeLink) {
attributes.remove(Attribute.link.key);
}
return Delta()
..retain(index + len)
..insert(data, attributes.isEmpty ? null : attributes);
}