Browse Source

Added heuristic rule to preserve block styles on paste

Anatoly Pulyaevskiy 6 years ago
parent
commit
825d06b8e6

+ 5
- 0
packages/notus/CHANGELOG.md View File

@@ -1,3 +1,8 @@
1
+## 0.1.3
2
+
3
+- Fixed handling of user input around embeds.
4
+- Added new heuristic rule to preserve block style on paste
5
+
1 6
 ## 0.1.2
2 7
 
3 8
 * Upgraded dependency on quiver_hashcode to 2.0.0.

+ 1
- 0
packages/notus/lib/src/heuristics.dart View File

@@ -23,6 +23,7 @@ class NotusHeuristics {
23 23
       // attributes.
24 24
     ],
25 25
     insertRules: [
26
+      PreserveBlockStyleOnPasteRule(),
26 27
       ForceNewlineForInsertsAroundEmbedRule(),
27 28
       PreserveLineStyleOnSplitRule(),
28 29
       AutoExitBlockRule(),

+ 68
- 1
packages/notus/lib/src/heuristics/insert_rules.dart View File

@@ -72,8 +72,9 @@ class PreserveLineStyleOnSplitRule extends InsertRule {
72 72
   }
73 73
 }
74 74
 
75
-/// Resets format for a newly inserted line when insert occurred at the end
76 75
 /// of a line (right before a line-break).
76
+
77
+/// Resets format for a newly inserted line when insert occurred at the end
77 78
 class ResetLineFormatOnNewLineRule extends InsertRule {
78 79
   const ResetLineFormatOnNewLineRule();
79 80
 
@@ -256,3 +257,69 @@ class ForceNewlineForInsertsAroundEmbedRule extends InsertRule {
256 257
     return null;
257 258
   }
258 259
 }
260
+
261
+/// Preserves block style when user pastes text containing line-breaks.
262
+/// This rule may also be activated for changes triggered by auto-correct.
263
+class PreserveBlockStyleOnPasteRule extends InsertRule {
264
+  const PreserveBlockStyleOnPasteRule();
265
+
266
+  bool isEdgeLineSplit(Operation before, Operation after) {
267
+    if (before == null) return true; // split at the beginning of a doc
268
+    return before.data.endsWith('\n') || after.data.startsWith('\n');
269
+  }
270
+
271
+  @override
272
+  Delta apply(Delta document, int index, String text) {
273
+    if (!text.contains('\n') || text.length == 1) {
274
+      // Only interested in text containing at least one line-break and at least
275
+      // one more character.
276
+      return null;
277
+    }
278
+
279
+    DeltaIterator iter = new DeltaIterator(document);
280
+    iter.skip(index);
281
+
282
+    // Look for next line-break.
283
+    Map<String, dynamic> lineStyle;
284
+    while (iter.hasNext) {
285
+      final op = iter.next();
286
+      int lf = op.data.indexOf('\n');
287
+      if (lf >= 0) {
288
+        lineStyle = op.attributes;
289
+        break;
290
+      }
291
+    }
292
+
293
+    Map<String, dynamic> resetStyle = null;
294
+    Map<String, dynamic> blockStyle = null;
295
+    if (lineStyle != null) {
296
+      if (lineStyle.containsKey(NotusAttribute.heading.key)) {
297
+        resetStyle = NotusAttribute.heading.unset.toJson();
298
+      }
299
+
300
+      if (lineStyle.containsKey(NotusAttribute.block.key)) {
301
+        blockStyle = <String, dynamic>{
302
+          NotusAttribute.block.key: lineStyle[NotusAttribute.block.key]
303
+        };
304
+      }
305
+    }
306
+
307
+    final lines = text.split('\n');
308
+    Delta result = new Delta()..retain(index);
309
+    for (int i = 0; i < lines.length; i++) {
310
+      final line = lines[i];
311
+      if (line.isNotEmpty) {
312
+        result.insert(line);
313
+      }
314
+      if (i == 0) {
315
+        result.insert('\n', lineStyle);
316
+      } else if (i == lines.length - 1) {
317
+        if (resetStyle != null) result.retain(1, resetStyle);
318
+      } else {
319
+        result.insert('\n', blockStyle);
320
+      }
321
+    }
322
+
323
+    return result;
324
+  }
325
+}

+ 1
- 1
packages/notus/pubspec.yaml View File

@@ -1,6 +1,6 @@
1 1
 name: notus
2 2
 description: Platform-agnostic rich text document model based on Delta format and used in Zefyr editor.
3
-version: 0.1.2
3
+version: 0.1.3
4 4
 author: Anatoly Pulyaevskiy <anatoly.pulyaevskiy@gmail.com>
5 5
 homepage: https://github.com/memspace/zefyr
6 6
 

+ 20
- 2
packages/notus/test/heuristics/insert_rules_test.dart View File

@@ -73,8 +73,7 @@ void main() {
73 73
     });
74 74
 
75 75
     test('applies at the beginning of a document', () {
76
-      final doc = new Delta()
77
-        ..insert('\n', NotusAttribute.h1.toJson());
76
+      final doc = new Delta()..insert('\n', NotusAttribute.h1.toJson());
78 77
       final actual = rule.apply(doc, 0, '\n');
79 78
       expect(actual, isNotNull);
80 79
       final expected = new Delta()
@@ -212,4 +211,23 @@ void main() {
212 211
       expect(actual, isNull);
213 212
     });
214 213
   });
214
+
215
+  group('$PreserveBlockStyleOnPasteRule', () {
216
+    final rule = new PreserveBlockStyleOnPasteRule();
217
+
218
+    test('applies in a block', () {
219
+      final doc = new Delta()
220
+        ..insert('One and two')
221
+        ..insert('\n', ul)
222
+        ..insert('Three')
223
+        ..insert('\n', ul);
224
+      final actual = rule.apply(doc, 8, 'also \n');
225
+      final expected = new Delta()
226
+        ..retain(8)
227
+        ..insert('also ')
228
+        ..insert('\n', ul);
229
+      expect(actual, isNotNull);
230
+      expect(actual, expected);
231
+    });
232
+  });
215 233
 }

+ 2
- 1
packages/zefyr/CHANGELOG.md View File

@@ -2,7 +2,8 @@
2 2
 
3 3
 * Breaking change: `ZefyrImageDelegate.createImageProvider` replaced with
4 4
   `ZefyrImageDelegate.buildImage`.
5
-* Fixed: Prevent redundant updates on composing range for Android.
5
+* Fixed redundant updates on composing range for Android.
6
+* Added TextCapitalization.sentences
6 7
 
7 8
 ## 0.1.2
8 9
 

+ 8
- 0
packages/zefyr/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist View File

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>IDEDidComputeMac32BitWarning</key>
6
+	<true/>
7
+</dict>
8
+</plist>

+ 8
- 0
packages/zefyr/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist View File

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>IDEDidComputeMac32BitWarning</key>
6
+	<true/>
7
+</dict>
8
+</plist>

+ 8
- 0
packages/zefyr/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings View File

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>BuildSystemType</key>
6
+	<string>Original</string>
7
+</dict>
8
+</plist>