applyRule method

  1. @override
Delta? applyRule(
  1. Document document,
  2. int index, {
  3. int? len,
  4. Object? data,
  5. Attribute? attribute,
})

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);
  var prev = itr.skip(len == 0 ? index : index + 1);

  if (prev == null || prev.data is! String) return null;

  /// Trap for simple insertions at start of line
  if (len == 0) {
    final prevData = prev.data as String;
    if (prevData.endsWith('\n')) {
      /// If current line is empty get attributes from a prior line
      final currLine = itr.next();
      final currData =
          currLine.data is String ? currLine.data as String : null;
      if (currData?.isEmpty == true || currData?.startsWith('\n') == true) {
        if (prevData.trimRight().isEmpty) {
          final back =
              DeltaIterator(documentDelta).skip(index - prevData.length);
          if (back != null && back.data is String) {
            prev = back;
          }
        }
      } else {
        prev = currLine;
      }
    }
  }

  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;
  }

  final text = data;
  if (attributes.isEmpty || !attributes.containsKey(Attribute.link.key)) {
    return Delta()
      ..retain(index + (len ?? 0))
      ..insert(text, attributes);
  }

  attributes.remove(Attribute.link.key);
  final delta = Delta()
    ..retain(index + (len ?? 0))
    ..insert(text, attributes.isEmpty ? null : attributes);
  final next = itr.next();

  final nextAttributes = next.attributes ?? const <String, dynamic>{};
  if (!nextAttributes.containsKey(Attribute.link.key)) {
    return delta;
  }
  if (attributes[Attribute.link.key] == nextAttributes[Attribute.link.key]) {
    return Delta()
      ..retain(index + (len ?? 0))
      ..insert(text, attributes);
  }
  return delta;
}