delete.dart 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import '../quill_delta.dart';
  2. import '../document/attribute.dart';
  3. import 'rule.dart';
  4. abstract class DeleteRule extends Rule {
  5. const DeleteRule();
  6. @override
  7. RuleType get type => RuleType.DELETE;
  8. @override
  9. void validateArgs(int? length, Object? data, Attribute? attribute) {
  10. assert(length != null);
  11. assert(data == null);
  12. assert(attribute == null);
  13. }
  14. }
  15. class CatchAllDeleteRule extends DeleteRule {
  16. const CatchAllDeleteRule();
  17. @override
  18. Delta applyRule(Delta document, int index,
  19. {int? length, Object? data, Attribute? attribute}) {
  20. return Delta()
  21. ..retain(index)
  22. ..delete(length!);
  23. }
  24. }
  25. class PreserveLineStyleOnMergeRule extends DeleteRule {
  26. const PreserveLineStyleOnMergeRule();
  27. @override
  28. Delta? applyRule(Delta document, int index,
  29. {int? length, Object? data, Attribute? attribute}) {
  30. final it = DeltaIterator(document)..skip(index);
  31. var op = it.next(1);
  32. if (op.data != '\n') {
  33. return null;
  34. }
  35. final isNotPlain = op.isNotPlain;
  36. final attrs = op.attributes;
  37. it.skip(length! - 1);
  38. final delta = Delta()
  39. ..retain(index)
  40. ..delete(length);
  41. while (it.hasNext) {
  42. op = it.next();
  43. final text = op.data is String ? (op.data as String?)! : '';
  44. final lineBreak = text.indexOf('\n');
  45. if (lineBreak == -1) {
  46. delta.retain(op.length!);
  47. continue;
  48. }
  49. var attributes = op.attributes == null
  50. ? null
  51. : op.attributes!.map<String, dynamic>(
  52. (key, dynamic value) => MapEntry<String, dynamic>(key, null));
  53. if (isNotPlain) {
  54. attributes ??= <String, dynamic>{};
  55. attributes.addAll(attrs!);
  56. }
  57. delta..retain(lineBreak)..retain(1, attributes);
  58. break;
  59. }
  60. return delta;
  61. }
  62. }
  63. class EnsureEmbedLineRule extends DeleteRule {
  64. const EnsureEmbedLineRule();
  65. @override
  66. Delta? applyRule(Delta document, int index,
  67. {int? length, Object? data, Attribute? attribute}) {
  68. final it = DeltaIterator(document);
  69. var op = it.skip(index);
  70. int? indexDelta = 0, lengthDelta = 0, remain = length;
  71. var embedFound = op != null && op.data is! String;
  72. final hasLineBreakBefore =
  73. !embedFound && (op == null || (op.data as String).endsWith('\n'));
  74. if (embedFound) {
  75. var candidate = it.next(1);
  76. if (remain != null) {
  77. remain--;
  78. if (candidate.data == '\n') {
  79. indexDelta++;
  80. lengthDelta--;
  81. candidate = it.next(1);
  82. remain--;
  83. if (candidate.data == '\n') {
  84. lengthDelta++;
  85. }
  86. }
  87. }
  88. }
  89. op = it.skip(remain!);
  90. if (op != null &&
  91. (op.data is String ? op.data as String? : '')!.endsWith('\n')) {
  92. final candidate = it.next(1);
  93. if (candidate.data is! String && !hasLineBreakBefore) {
  94. embedFound = true;
  95. lengthDelta--;
  96. }
  97. }
  98. if (!embedFound) {
  99. return null;
  100. }
  101. return Delta()
  102. ..retain(index + indexDelta)
  103. ..delete(length! + lengthDelta);
  104. }
  105. }