diff --git a/lib/src/models/rules/delete.dart b/lib/src/models/rules/delete.dart index 06c057eb..91e884d9 100644 --- a/lib/src/models/rules/delete.dart +++ b/lib/src/models/rules/delete.dart @@ -16,15 +16,33 @@ abstract class DeleteRule extends Rule { } } +class EnsureLastLineBreakDeleteRule extends DeleteRule { + const EnsureLastLineBreakDeleteRule(); + + @override + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { + final itr = DeltaIterator(document)..skip(index + len!); + + return Delta() + ..retain(index) + ..delete(itr.hasNext ? len : len - 1); + } +} + +/// Fallback rule for delete operations which simply deletes specified text +/// range without any special handling. class CatchAllDeleteRule extends DeleteRule { const CatchAllDeleteRule(); @override Delta applyRule(Delta document, int index, {int? len, Object? data, Attribute? attribute}) { + final itr = DeltaIterator(document)..skip(index + len!); + return Delta() ..retain(index) - ..delete(len!); + ..delete(itr.hasNext ? len : len - 1); } } @@ -44,6 +62,14 @@ class PreserveLineStyleOnMergeRule extends DeleteRule { final attrs = op.attributes; itr.skip(len! - 1); + + if (!itr.hasNext) { + // User attempts to delete the last newline character, prevent it. + return Delta() + ..retain(index) + ..delete(len - 1); + } + final delta = Delta() ..retain(index) ..delete(len); diff --git a/lib/src/models/rules/rule.dart b/lib/src/models/rules/rule.dart index a2649499..c9a0f911 100644 --- a/lib/src/models/rules/rule.dart +++ b/lib/src/models/rules/rule.dart @@ -46,6 +46,7 @@ class Rules { const EnsureEmbedLineRule(), const PreserveLineStyleOnMergeRule(), const CatchAllDeleteRule(), + const EnsureLastLineBreakDeleteRule() ]); static Rules getInstance() => _instance;