applyRule method

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

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