From 7d3f48958df56346214d3a95cb56d6de237af583 Mon Sep 17 00:00:00 2001
From: Alan Mantoux
Date: Thu, 10 Sep 2026 15:12:43 +0200
Subject: [PATCH 1/2] Fix selector positioning around bottom toolbars
---
.../lib/src/widgets/editor_toolbar.dart | 60 ++++++++++---
.../test/widgets/editor_toolbar_test.dart | 88 ++++++++++++++++++-
2 files changed, 134 insertions(+), 14 deletions(-)
diff --git a/packages/fleather/lib/src/widgets/editor_toolbar.dart b/packages/fleather/lib/src/widgets/editor_toolbar.dart
index 7f4f16d4..7ec73bb1 100644
--- a/packages/fleather/lib/src/widgets/editor_toolbar.dart
+++ b/packages/fleather/lib/src/widgets/editor_toolbar.dart
@@ -1274,14 +1274,32 @@ class SelectorScopeState extends State {
final RenderBox presenter = context.findRenderObject() as RenderBox;
final RenderBox overlayBox =
overlay.context.findRenderObject() as RenderBox;
- final offset = Offset(0.0, presenter.size.height);
+ final presenterRect = Rect.fromPoints(
+ presenter.localToGlobal(Offset.zero, ancestor: overlayBox),
+ presenter.localToGlobal(
+ presenter.size.bottomRight(Offset.zero),
+ ancestor: overlayBox,
+ ),
+ );
+ // Toolbar padding belongs to the area selectors must avoid as well.
+ // Keep horizontal alignment with the button, but clear the whole toolbar.
+ final toolbar = context.findAncestorStateOfType<_FleatherToolbarState>();
+ final toolbarBox = toolbar?.context.findRenderObject() as RenderBox?;
+ final toolbarRect = toolbarBox == null
+ ? presenterRect
+ : Rect.fromPoints(
+ toolbarBox.localToGlobal(Offset.zero, ancestor: overlayBox),
+ toolbarBox.localToGlobal(
+ toolbarBox.size.bottomRight(Offset.zero),
+ ancestor: overlayBox,
+ ),
+ );
final position = RelativeRect.fromSize(
- Rect.fromPoints(
- presenter.localToGlobal(offset, ancestor: overlayBox),
- presenter.localToGlobal(
- presenter.size.bottomRight(Offset.zero) + offset,
- ancestor: overlayBox,
- ),
+ Rect.fromLTRB(
+ presenterRect.left,
+ toolbarRect.top,
+ presenterRect.right,
+ toolbarRect.bottom,
),
overlayBox.size,
);
@@ -1376,8 +1394,6 @@ class _SelectorLayout extends SingleChildLayoutDelegate {
// childSize: The size of the menu, when fully open, as determined by
// getConstraintsForChild.
- final double y = position.top;
-
// Find the ideal horizontal position.
double x;
if (position.right > childSize.width) {
@@ -1395,13 +1411,31 @@ class _SelectorLayout extends SingleChildLayoutDelegate {
}
}
- final Offset wantedPosition = Offset(x, y);
- final Offset originCenter = position.toRect(Offset.zero & size).center;
+ final Rect presenter = position.toRect(Offset.zero & size);
+ final Offset originCenter = presenter.center;
final Iterable subScreens =
DisplayFeatureSubScreen.subScreensInBounds(
Offset.zero & size, avoidBounds);
final Rect subScreen = _closestScreen(subScreens, originCenter);
- return _fitInsideScreen(subScreen, childSize, wantedPosition);
+ final double spaceBelow =
+ subScreen.bottom -
+ padding.bottom -
+ _selectorScreenPadding -
+ presenter.bottom -
+ _selectorScreenPadding;
+ final double spaceAbove =
+ presenter.top -
+ _selectorScreenPadding -
+ subScreen.top -
+ padding.top -
+ _selectorScreenPadding;
+ // Prefer below the presenter, but flip above it when that offers more room.
+ final bool showAbove =
+ childSize.height > spaceBelow && spaceAbove > spaceBelow;
+ final double y = showAbove
+ ? presenter.top - _selectorScreenPadding - childSize.height
+ : presenter.bottom + _selectorScreenPadding;
+ return _fitInsideScreen(subScreen, childSize, Offset(x, y));
}
Rect _closestScreen(Iterable screens, Offset point) {
@@ -1430,7 +1464,7 @@ class _SelectorLayout extends SingleChildLayoutDelegate {
padding.right;
}
if (y < screen.top + _selectorScreenPadding + padding.top) {
- y = _selectorScreenPadding + padding.top;
+ y = screen.top + _selectorScreenPadding + padding.top;
} else if (y + childSize.height >
screen.bottom - _selectorScreenPadding - padding.bottom) {
y = screen.bottom -
diff --git a/packages/fleather/test/widgets/editor_toolbar_test.dart b/packages/fleather/test/widgets/editor_toolbar_test.dart
index c5e98810..f6cd6dfb 100644
--- a/packages/fleather/test/widgets/editor_toolbar_test.dart
+++ b/packages/fleather/test/widgets/editor_toolbar_test.dart
@@ -452,6 +452,92 @@ void main() {
});
group('SelectorScope', () {
+ for (final isAtBottom in [false, true]) {
+ for (final keyboardHeight in [0.0, 200.0]) {
+ for (final isBackground in [false, true]) {
+ testWidgets(
+ '${isBackground ? 'Background' : 'Text'} color selector opens '
+ '${isAtBottom ? 'above' : 'below'} the toolbar '
+ 'with keyboard height $keyboardHeight',
+ (tester) async {
+ const padding = EdgeInsets.all(24);
+ final controller = FleatherController();
+ addTearDown(controller.dispose);
+ await tester.pumpWidget(
+ MaterialApp(
+ builder: (context, child) => MediaQuery(
+ data: MediaQuery.of(context).copyWith(
+ padding: padding,
+ viewInsets: EdgeInsets.only(bottom: keyboardHeight),
+ ),
+ child: child!,
+ ),
+ home: Scaffold(
+ body: SafeArea(
+ child: Column(
+ children: [
+ if (isAtBottom) const Spacer(),
+ FleatherToolbar(
+ children: [
+ ColorButton(
+ controller: controller,
+ attributeKey: isBackground
+ ? ParchmentAttribute.backgroundColor
+ : ParchmentAttribute.foregroundColor,
+ nullColorLabel: isBackground
+ ? 'No color'
+ : 'Automatic',
+ builder: (context, value) =>
+ const Icon(Icons.palette),
+ ),
+ ],
+ ),
+ if (!isAtBottom) const Spacer(),
+ ],
+ ),
+ ),
+ ),
+ ),
+ );
+ await tester.tap(find.byType(ColorButton));
+ await tester.pumpAndSettle();
+
+ final selector = find.byKey(const Key('color_selector'));
+ expect(selector, findsOneWidget);
+ final selectorRect = tester.getRect(selector);
+ final toolbarRect = tester.getRect(find.byType(FleatherToolbar));
+ if (isAtBottom) {
+ expect(selectorRect.bottom, lessThanOrEqualTo(toolbarRect.top));
+ } else {
+ expect(
+ selectorRect.top,
+ greaterThanOrEqualTo(toolbarRect.bottom),
+ );
+ }
+ expect(selectorRect.overlaps(toolbarRect), isFalse);
+
+ final screen = tester.getRect(find.byType(Scaffold));
+ expect(selectorRect.left, greaterThanOrEqualTo(padding.left));
+ expect(
+ selectorRect.right,
+ lessThanOrEqualTo(screen.right - padding.right),
+ );
+ expect(selectorRect.top, greaterThanOrEqualTo(padding.top));
+ expect(
+ selectorRect.bottom,
+ lessThanOrEqualTo(
+ screen.bottom - padding.bottom - keyboardHeight,
+ ),
+ );
+ expect(tester.takeException(), isNull);
+ await tester.pumpWidget(const SizedBox());
+ await tester.pumpAndSettle(throttleDuration);
+ },
+ );
+ }
+ }
+ }
+
testWidgets('Correctly places the selector in a visible area of screen',
(WidgetTester tester) async {
const padding = EdgeInsets.all(32);
@@ -502,7 +588,7 @@ void main() {
);
expect(
tester.getRect(find.byKey(const Key('heading_selector'))).bottom,
- tester.getRect(find.byType(Scaffold)).bottom - padding.bottom - 8,
+ lessThan(tester.getRect(find.byType(SelectHeadingButton)).top),
);
});
});
From 836e461eb2c253fc3ea4e773da1e62e46b9c07b1 Mon Sep 17 00:00:00 2001
From: Alan Mantoux
Date: Thu, 10 Sep 2026 15:18:32 +0200
Subject: [PATCH 2/2] fmt
---
.../lib/src/widgets/editor_toolbar.dart | 6 +-
.../test/widgets/editor_toolbar_test.dart | 5 +-
packages/parchment/example/main.dart | 6 +-
packages/parchment/lib/src/codecs/html.dart | 212 +++--
.../parchment/lib/src/codecs/html_utils.dart | 11 +-
.../parchment/lib/src/codecs/markdown.dart | 171 ++--
packages/parchment/lib/src/document.dart | 58 +-
.../lib/src/document/attributes.dart | 20 +-
.../parchment/lib/src/document/embeds.dart | 27 +-
packages/parchment/lib/src/document/leaf.dart | 19 +-
packages/parchment/lib/src/document/line.dart | 40 +-
packages/parchment/lib/src/document/node.dart | 6 +-
packages/parchment/lib/src/heuristics.dart | 8 +-
.../lib/src/heuristics/delete_rules.dart | 3 +-
.../lib/src/heuristics/format_rules.dart | 32 +-
.../lib/src/heuristics/insert_rules.dart | 6 +-
packages/parchment/test/codecs/html_test.dart | 866 +++++++++---------
.../parchment/test/codecs/markdown_test.dart | 156 ++--
.../test/document/attributes_test.dart | 20 +-
.../parchment/test/document/block_test.dart | 26 +-
.../parchment/test/document/leaf_test.dart | 27 +-
.../parchment/test/document/line_test.dart | 30 +-
packages/parchment/test/document_test.dart | 56 +-
.../test/heuristics/format_rules_test.dart | 10 +-
.../test/heuristics/insert_rules_test.dart | 42 +-
25 files changed, 1101 insertions(+), 762 deletions(-)
diff --git a/packages/fleather/lib/src/widgets/editor_toolbar.dart b/packages/fleather/lib/src/widgets/editor_toolbar.dart
index 7ec73bb1..59f79500 100644
--- a/packages/fleather/lib/src/widgets/editor_toolbar.dart
+++ b/packages/fleather/lib/src/widgets/editor_toolbar.dart
@@ -1417,14 +1417,12 @@ class _SelectorLayout extends SingleChildLayoutDelegate {
DisplayFeatureSubScreen.subScreensInBounds(
Offset.zero & size, avoidBounds);
final Rect subScreen = _closestScreen(subScreens, originCenter);
- final double spaceBelow =
- subScreen.bottom -
+ final double spaceBelow = subScreen.bottom -
padding.bottom -
_selectorScreenPadding -
presenter.bottom -
_selectorScreenPadding;
- final double spaceAbove =
- presenter.top -
+ final double spaceAbove = presenter.top -
_selectorScreenPadding -
subScreen.top -
padding.top -
diff --git a/packages/fleather/test/widgets/editor_toolbar_test.dart b/packages/fleather/test/widgets/editor_toolbar_test.dart
index f6cd6dfb..07f44bd9 100644
--- a/packages/fleather/test/widgets/editor_toolbar_test.dart
+++ b/packages/fleather/test/widgets/editor_toolbar_test.dart
@@ -484,9 +484,8 @@ void main() {
attributeKey: isBackground
? ParchmentAttribute.backgroundColor
: ParchmentAttribute.foregroundColor,
- nullColorLabel: isBackground
- ? 'No color'
- : 'Automatic',
+ nullColorLabel:
+ isBackground ? 'No color' : 'Automatic',
builder: (context, value) =>
const Icon(Icons.palette),
),
diff --git a/packages/parchment/example/main.dart b/packages/parchment/example/main.dart
index c03df9fa..a2bed24c 100644
--- a/packages/parchment/example/main.dart
+++ b/packages/parchment/example/main.dart
@@ -3,8 +3,10 @@ import 'package:parchment/parchment.dart';
void main() {
final doc = ParchmentDocument();
// Modify this document with insert, delete and format operations
- doc.insert(0,
- 'Parchment package provides rich text document model for Fleather editor');
+ doc.insert(
+ 0,
+ 'Parchment package provides rich text document model for Fleather editor',
+ );
doc.format(0, 5, ParchmentAttribute.bold); // Makes first word bold.
doc.format(0, 0, ParchmentAttribute.h1); // Makes first line a heading.
doc.delete(23, 10); // Deletes "rich text " segment.
diff --git a/packages/parchment/lib/src/codecs/html.dart b/packages/parchment/lib/src/codecs/html.dart
index 8d65e81d..c90659d1 100644
--- a/packages/parchment/lib/src/codecs/html.dart
+++ b/packages/parchment/lib/src/codecs/html.dart
@@ -157,22 +157,28 @@ class _ParchmentHtmlEncoder extends Converter {
// current and candidate are both blocks
static bool isNestedList(ParchmentStyle parent, ParchmentStyle child) {
final currentListAttribute = parent.values.firstWhereOrNull(
- (e) => e == ParchmentAttribute.ol || e == ParchmentAttribute.ul);
+ (e) => e == ParchmentAttribute.ol || e == ParchmentAttribute.ul,
+ );
final candidateListAttribute = child.values.firstWhereOrNull(
- (e) => e == ParchmentAttribute.ol || e == ParchmentAttribute.ul);
+ (e) => e == ParchmentAttribute.ol || e == ParchmentAttribute.ul,
+ );
if (currentListAttribute == null || candidateListAttribute == null) {
return false;
}
int currentLevel = parent.values
- .firstWhere((e) => e.key == ParchmentAttribute.indent.key,
- orElse: () => ParchmentAttribute.indent.withLevel(0))
+ .firstWhere(
+ (e) => e.key == ParchmentAttribute.indent.key,
+ orElse: () => ParchmentAttribute.indent.withLevel(0),
+ )
.value ??
0;
int candidateLevel = child.values
- .firstWhere((e) => e.key == ParchmentAttribute.indent.key,
- orElse: () => ParchmentAttribute.indent.withLevel(0))
+ .firstWhere(
+ (e) => e.key == ParchmentAttribute.indent.key,
+ orElse: () => ParchmentAttribute.indent.withLevel(0),
+ )
.value ??
0;
return currentLevel < candidateLevel;
@@ -180,11 +186,15 @@ class _ParchmentHtmlEncoder extends Converter {
// Check if both attributes are lists of different type with same indentation
bool isDifferentListTypeWithSameIndentationLevel(
- ParchmentStyle parent, ParchmentStyle child) {
+ ParchmentStyle parent,
+ ParchmentStyle child,
+ ) {
final currentListAttribute = parent.values.firstWhereOrNull(
- (e) => e == ParchmentAttribute.ol || e == ParchmentAttribute.ul);
+ (e) => e == ParchmentAttribute.ol || e == ParchmentAttribute.ul,
+ );
final candidateListAttribute = child.values.firstWhereOrNull(
- (e) => e == ParchmentAttribute.ol || e == ParchmentAttribute.ul);
+ (e) => e == ParchmentAttribute.ol || e == ParchmentAttribute.ul,
+ );
if (currentListAttribute == null || candidateListAttribute == null) {
return false;
@@ -195,13 +205,17 @@ class _ParchmentHtmlEncoder extends Converter {
}
int currentLevel = parent.values
- .firstWhere((e) => e.key == ParchmentAttribute.indent.key,
- orElse: () => ParchmentAttribute.indent.withLevel(0))
+ .firstWhere(
+ (e) => e.key == ParchmentAttribute.indent.key,
+ orElse: () => ParchmentAttribute.indent.withLevel(0),
+ )
.value ??
0;
int candidateLevel = child.values
- .firstWhere((e) => e.key == ParchmentAttribute.indent.key,
- orElse: () => ParchmentAttribute.indent.withLevel(0))
+ .firstWhere(
+ (e) => e.key == ParchmentAttribute.indent.key,
+ orElse: () => ParchmentAttribute.indent.withLevel(0),
+ )
.value ??
0;
@@ -231,9 +245,15 @@ class _ParchmentHtmlEncoder extends Converter {
final subOp = Operation.insert('\n', op.attributes);
final currentLineStart = state.nextLineStartPosition;
state.nextLineStartPosition = _handleNewLineLineStyle(
- subOp, buffer, state.nextLineStartPosition);
- int padding =
- _handleNewLineBlockStyle(subOp, state, currentLineStart);
+ subOp,
+ buffer,
+ state.nextLineStartPosition,
+ );
+ int padding = _handleNewLineBlockStyle(
+ subOp,
+ state,
+ currentLineStart,
+ );
state.nextLineStartPosition += padding;
}
}
@@ -241,8 +261,11 @@ class _ParchmentHtmlEncoder extends Converter {
if (_isNewLine(op)) {
state.isSingleLine = false;
final currentLineStart = state.nextLineStartPosition;
- state.nextLineStartPosition =
- _handleNewLineLineStyle(op, buffer, state.nextLineStartPosition);
+ state.nextLineStartPosition = _handleNewLineLineStyle(
+ op,
+ buffer,
+ state.nextLineStartPosition,
+ );
int padding = _handleNewLineBlockStyle(op, state, currentLineStart);
state.nextLineStartPosition += padding;
}
@@ -270,8 +293,10 @@ class _ParchmentHtmlEncoder extends Converter {
}
/// Closes all open blocks and returns the ending position.
- int _closeOpenBlocks(_EncoderState state,
- {bool beforePlainParagraphHandling = false}) {
+ int _closeOpenBlocks(
+ _EncoderState state, {
+ bool beforePlainParagraphHandling = false,
+ }) {
final openBlockTags = state.openBlockTags;
final buffer = state.buffer;
final numToClose = openBlockTags.length;
@@ -290,7 +315,8 @@ class _ParchmentHtmlEncoder extends Converter {
// Handles the case where a nested list is followed by a plain paragraph
bool isBlockTagNested = openBlockTags.length >= 2 &&
openBlockTags[0].style.lineAttributes.firstWhereOrNull(
- (e) => e.key == ParchmentAttribute.indent.key) !=
+ (e) => e.key == ParchmentAttribute.indent.key,
+ ) !=
null;
if (i == numToClose - 1 &&
(!beforePlainParagraphHandling || isBlockTagNested)) {
@@ -310,10 +336,14 @@ class _ParchmentHtmlEncoder extends Converter {
}
void _processInlineTags(
- Operation op, StringBuffer buffer, List<_HtmlInlineTag> openInlineTags) {
+ Operation op,
+ StringBuffer buffer,
+ List<_HtmlInlineTag> openInlineTags,
+ ) {
final parchmentStyle = ParchmentStyle.fromJson(op.attributes);
- final Set inlineAttributes =
- Set.from(parchmentStyle.inlineAttributes);
+ final Set inlineAttributes = Set.from(
+ parchmentStyle.inlineAttributes,
+ );
// Close any tag absent from inline attributes
// Closing tags effectively adds the opening tag at the appropriate position
@@ -388,7 +418,9 @@ class _ParchmentHtmlEncoder extends Converter {
if (i == lines.length - 1) {
// Done with set of paragraphs, add last paragraph to block stack.
openBlockTags.insert(
- 0, _HtmlBlockTag(ParchmentStyle(), initialPosition, buffer.length));
+ 0,
+ _HtmlBlockTag(ParchmentStyle(), initialPosition, buffer.length),
+ );
if (lines[i].isNotEmpty) {
// Elements that do not belong to a paragraph but to block of next op
_writeData(subOp, buffer);
@@ -403,8 +435,10 @@ class _ParchmentHtmlEncoder extends Converter {
position = buffer.length;
}
- assert(openBlockTags.length <= 1,
- 'At most one paragraph should be pushed in stack');
+ assert(
+ openBlockTags.length <= 1,
+ 'At most one paragraph should be pushed in stack',
+ );
state.nextLineStartPosition = position;
}
@@ -412,7 +446,10 @@ class _ParchmentHtmlEncoder extends Converter {
// returns the start position in the buffer of the next line that will be
// processed
int _handleNewLineLineStyle(
- Operation op, StringBuffer buffer, int currentLineStart) {
+ Operation op,
+ StringBuffer buffer,
+ int currentLineStart,
+ ) {
final opStyle = ParchmentStyle.fromJson(op.attributes);
final newLineTag = _HtmlLineTag(opStyle, currentLineStart);
if (newLineTag.style.isNotEmpty) {
@@ -424,7 +461,10 @@ class _ParchmentHtmlEncoder extends Converter {
// used to write html tags of blocks themselves.
// returns padding induced by ex-post addition of block tags
int _handleNewLineBlockStyle(
- Operation op, _EncoderState state, int currentLineStart) {
+ Operation op,
+ _EncoderState state,
+ int currentLineStart,
+ ) {
final buffer = state.buffer;
final openBlockTags = state.openBlockTags;
final opStyle = ParchmentStyle.fromJson(op.attributes);
@@ -452,26 +492,32 @@ class _ParchmentHtmlEncoder extends Converter {
if (isNestedList(opStyle, openBlockTags[0].style)) {
final currentBlockTag = openBlockTags[0];
_writeBlockTag(
- buffer, currentBlockTag..closingPosition = currentLineStart);
+ buffer,
+ currentBlockTag..closingPosition = currentLineStart,
+ );
openBlockTags.removeAt(0);
// This handle the case where a new list (different list style) is directly
// succeeding another list that ends with a nest list item
if (isDifferentListTypeWithSameIndentationLevel(
- opStyle, openBlockTags[0].style)) {
+ opStyle,
+ openBlockTags[0].style,
+ )) {
final nextBlockTag = openBlockTags[0];
_writeBlockTag(
- buffer,
- nextBlockTag
- ..closingPosition =
- currentLineStart + currentBlockTag.inducedPadding);
+ buffer,
+ nextBlockTag
+ ..closingPosition =
+ currentLineStart + currentBlockTag.inducedPadding,
+ );
openBlockTags.removeAt(0);
// If no previous style, let caller write surrounding tags
if (openBlockTags.isEmpty) {
var newBlockTag = _HtmlBlockTag(
- opStyle,
- currentLineStart +
- nextBlockTag.inducedPadding +
- currentBlockTag.inducedPadding);
+ opStyle,
+ currentLineStart +
+ nextBlockTag.inducedPadding +
+ currentBlockTag.inducedPadding,
+ );
// If no previous style, let caller write surrounding tags
openBlockTags.insert(0, newBlockTag..closingPosition = buffer.length);
}
@@ -508,12 +554,7 @@ class _ParchmentHtmlEncoder extends Converter {
}
buffer.clear();
- buffer.writeAll([
- preHtml,
- openTag,
- innerHtml,
- closeTag,
- ]);
+ buffer.writeAll([preHtml, openTag, innerHtml, closeTag]);
}
void _writeBlockTag(StringBuffer buffer, _HtmlBlockTag tag) {
@@ -657,8 +698,9 @@ class _HtmlLineTag extends _HtmlTag {
}
_HtmlLineTag(ParchmentStyle style, super.openingPosition)
- : style = ParchmentStyle()
- .putAll(style.lineAttributes.where((e) => isLineAttribute(e)));
+ : style = ParchmentStyle().putAll(
+ style.lineAttributes.where((e) => isLineAttribute(e)),
+ );
final ParchmentStyle style;
@@ -681,8 +723,9 @@ class _HtmlLineTag extends _HtmlTag {
}
String? get alignmentCss {
- var alignment = style.values
- .firstWhereOrNull((e) => e.key == ParchmentAttribute.alignment.key);
+ var alignment = style.values.firstWhereOrNull(
+ (e) => e.key == ParchmentAttribute.alignment.key,
+ );
if (alignment == null) return null;
@@ -713,8 +756,9 @@ class _HtmlLineTag extends _HtmlTag {
style.values.contains(ParchmentAttribute.ol)) {
return null;
}
- var indentation = style.values
- .firstWhereOrNull((e) => e.key == ParchmentAttribute.indent.key);
+ var indentation = style.values.firstWhereOrNull(
+ (e) => e.key == ParchmentAttribute.indent.key,
+ );
if (indentation == null) return null;
int value = indentation.value;
@@ -725,8 +769,9 @@ class _HtmlLineTag extends _HtmlTag {
String? get directionAttribute {
if (_directionAttribute == null) {
- var direction = style.values
- .firstWhereOrNull((e) => e.key == ParchmentAttribute.direction.key);
+ var direction = style.values.firstWhereOrNull(
+ (e) => e.key == ParchmentAttribute.direction.key,
+ );
if (direction == null) {
return _directionAttribute;
@@ -768,8 +813,9 @@ class _HtmlLineTag extends _HtmlTag {
openTag += '';
}
if (attr.value == ParchmentAttribute.cl.value) {
- final checked = style.values
- .firstWhereOrNull((e) => e.key == ParchmentAttribute.checked.key);
+ final checked = style.values.firstWhereOrNull(
+ (e) => e.key == ParchmentAttribute.checked.key,
+ );
final checkedAttribute =
checked != null && checked.value ? ' checked' : '';
// Checkboxes disabled so user cannot toggle them.
@@ -840,10 +886,13 @@ class _HtmlBlockTag extends _HtmlTag {
attribute.key == ParchmentAttribute.indent.key;
}
- _HtmlBlockTag(ParchmentStyle style, super.openingPosition,
- [int? closingPosition])
- : style = ParchmentStyle()
- .putAll(style.lineAttributes.where((e) => isBlockAttribute(e))),
+ _HtmlBlockTag(
+ ParchmentStyle style,
+ super.openingPosition, [
+ int? closingPosition,
+ ]) : style = ParchmentStyle().putAll(
+ style.lineAttributes.where((e) => isBlockAttribute(e)),
+ ),
closingPosition = closingPosition ?? openingPosition;
final ParchmentStyle style;
@@ -853,7 +902,10 @@ class _HtmlBlockTag extends _HtmlTag {
_HtmlBlockTag withPadding(int padding) {
return _HtmlBlockTag(
- style, openingPosition + padding, closingPosition + padding);
+ style,
+ openingPosition + padding,
+ closingPosition + padding,
+ );
}
@override
@@ -952,8 +1004,11 @@ class _ParchmentHtmlDecoder extends Converter {
node.localName == 'h6');
}
- Delta _parseNode(html.Node node,
- [ParchmentStyle? inlineStyle, ParchmentStyle? blockStyle]) {
+ Delta _parseNode(
+ html.Node node, [
+ ParchmentStyle? inlineStyle,
+ ParchmentStyle? blockStyle,
+ ]) {
inlineStyle ??= ParchmentStyle();
blockStyle ??= ParchmentStyle();
Delta delta = Delta();
@@ -1005,7 +1060,9 @@ class _ParchmentHtmlDecoder extends Converter {
}
ParchmentStyle _updateInlineStyle(
- html.Element element, ParchmentStyle inlineStyle) {
+ html.Element element,
+ ParchmentStyle inlineStyle,
+ ) {
ParchmentStyle updated = inlineStyle;
if (element.localName == 'strong') {
updated = updated.put(ParchmentAttribute.bold);
@@ -1016,8 +1073,9 @@ class _ParchmentHtmlDecoder extends Converter {
} else if (element.localName == 'em') {
updated = updated.put(ParchmentAttribute.italic);
} else if (element.localName == 'a') {
- final link =
- ParchmentAttribute.link.withValue(element.attributes['href']);
+ final link = ParchmentAttribute.link.withValue(
+ element.attributes['href'],
+ );
updated = inlineStyle.put(link);
} else if (element.localName == 'span') {
final css = element.attributes['style'];
@@ -1026,14 +1084,16 @@ class _ParchmentHtmlDecoder extends Converter {
if (style.startsWith('background-color')) {
final sValue = style.split(':')[1].trim();
final color = colorValueFromCSS(sValue);
- updated =
- updated.put(ParchmentAttribute.backgroundColor.withColor(color));
+ updated = updated.put(
+ ParchmentAttribute.backgroundColor.withColor(color),
+ );
}
if (style.startsWith('color')) {
final sValue = style.split(':')[1].trim();
final color = colorValueFromCSS(sValue);
- updated =
- updated.put(ParchmentAttribute.foregroundColor.withColor(color));
+ updated = updated.put(
+ ParchmentAttribute.foregroundColor.withColor(color),
+ );
}
}
}
@@ -1041,7 +1101,9 @@ class _ParchmentHtmlDecoder extends Converter {
}
ParchmentStyle _updateBlockStyle(
- html.Element element, ParchmentStyle blockStyle) {
+ html.Element element,
+ ParchmentStyle blockStyle,
+ ) {
ParchmentStyle updated = blockStyle;
if (element.localName == 'h1') {
updated = updated.put(ParchmentAttribute.h1);
@@ -1066,15 +1128,17 @@ class _ParchmentHtmlDecoder extends Converter {
} else if (element.localName == 'ol') {
if (_hasList(updated)) {
final indentLevel = updated.value(ParchmentAttribute.indent) ?? 0;
- updated =
- updated.put(ParchmentAttribute.indent.withLevel(indentLevel + 1));
+ updated = updated.put(
+ ParchmentAttribute.indent.withLevel(indentLevel + 1),
+ );
}
updated = updated.put(ParchmentAttribute.ol);
} else if (element.localName == 'ul') {
if (_hasList(updated)) {
final indentLevel = updated.value(ParchmentAttribute.indent) ?? 0;
- updated =
- updated.put(ParchmentAttribute.indent.withLevel(indentLevel + 1));
+ updated = updated.put(
+ ParchmentAttribute.indent.withLevel(indentLevel + 1),
+ );
}
updated = updated.put(ParchmentAttribute.ul);
} else if (element.localName == 'input' &&
diff --git a/packages/parchment/lib/src/codecs/html_utils.dart b/packages/parchment/lib/src/codecs/html_utils.dart
index 4120b3e2..ef3d1fc7 100644
--- a/packages/parchment/lib/src/codecs/html_utils.dart
+++ b/packages/parchment/lib/src/codecs/html_utils.dart
@@ -3,7 +3,7 @@
A: (0xff000000 & colorValue) >> 24,
R: (0x00ff0000 & colorValue) >> 16,
G: (0x0000ff00 & colorValue) >> 8,
- B: (0x000000ff & colorValue) >> 0
+ B: (0x000000ff & colorValue) >> 0,
);
}
@@ -78,7 +78,8 @@ List _chooseSplit(String cssColor) {
split = cssColor.split(' ');
if (split.length < 3) {
throw ArgumentError(
- 'CSS color - rgb(a) must have at least 3 components. Received $cssColor');
+ 'CSS color - rgb(a) must have at least 3 components. Received $cssColor',
+ );
}
final clean = [];
@@ -95,11 +96,13 @@ List _chooseSplit(String cssColor) {
}
if (hasSlash && clean.length != 4) {
throw ArgumentError(
- 'CSS color - expected 4 components. Received $cssColor');
+ 'CSS color - expected 4 components. Received $cssColor',
+ );
}
if (!hasSlash && clean.length != 3) {
throw ArgumentError(
- 'CSS color : expecting 3 components. Received $cssColor');
+ 'CSS color : expecting 3 components. Received $cssColor',
+ );
}
return clean;
}
diff --git a/packages/parchment/lib/src/codecs/markdown.dart b/packages/parchment/lib/src/codecs/markdown.dart
index 18e141ae..12bc9cb3 100644
--- a/packages/parchment/lib/src/codecs/markdown.dart
+++ b/packages/parchment/lib/src/codecs/markdown.dart
@@ -78,10 +78,18 @@ class _ParchmentMarkdownDecoder extends Converter {
if (style?.isInline ?? true) {
_handleSpan(line, delta, true, style);
} else {
- _handleSpan(line, delta, false,
- ParchmentStyle().putAll(style?.inlineAttributes ?? []));
- _handleSpan('\n', delta, false,
- ParchmentStyle().putAll(style?.lineAttributes ?? []));
+ _handleSpan(
+ line,
+ delta,
+ false,
+ ParchmentStyle().putAll(style?.inlineAttributes ?? []),
+ );
+ _handleSpan(
+ '\n',
+ delta,
+ false,
+ ParchmentStyle().putAll(style?.lineAttributes ?? []),
+ );
}
}
}
@@ -141,8 +149,9 @@ class _ParchmentMarkdownDecoder extends Converter {
_handleSpan(span, delta, false, style);
ParchmentStyle blockStyle = ParchmentStyle().put(ParchmentAttribute.ol);
if (indent > 0) {
- blockStyle =
- blockStyle.put(ParchmentAttribute.indent.withLevel(indent));
+ blockStyle = blockStyle.put(
+ ParchmentAttribute.indent.withLevel(indent),
+ );
}
_handleSpan('\n', delta, false, blockStyle);
return true;
@@ -161,10 +170,18 @@ class _ParchmentMarkdownDecoder extends Converter {
final match = _ulRegExp.matchAsPrefix(line);
final span = match?.group(2);
if (span != null) {
- _handleSpan(span, delta, false,
- ParchmentStyle().putAll(newStyle.inlineAttributes));
_handleSpan(
- '\n', delta, false, ParchmentStyle().putAll(newStyle.lineAttributes));
+ span,
+ delta,
+ false,
+ ParchmentStyle().putAll(newStyle.inlineAttributes),
+ );
+ _handleSpan(
+ '\n',
+ delta,
+ false,
+ ParchmentStyle().putAll(newStyle.lineAttributes),
+ );
return true;
}
return false;
@@ -176,8 +193,9 @@ class _ParchmentMarkdownDecoder extends Converter {
return false;
}
- ParchmentStyle newStyle =
- (style ?? ParchmentStyle()).put(ParchmentAttribute.cl);
+ ParchmentStyle newStyle = (style ?? ParchmentStyle()).put(
+ ParchmentAttribute.cl,
+ );
final match = _clRegExp.matchAsPrefix(line);
final span = match?.group(3);
@@ -186,10 +204,18 @@ class _ParchmentMarkdownDecoder extends Converter {
newStyle = newStyle.put(ParchmentAttribute.checked);
}
if (span != null) {
- _handleSpan(span, delta, false,
- ParchmentStyle().putAll(newStyle.inlineAttributes));
_handleSpan(
- '\n', delta, false, ParchmentStyle().putAll(newStyle.lineAttributes));
+ span,
+ delta,
+ false,
+ ParchmentStyle().putAll(newStyle.inlineAttributes),
+ );
+ _handleSpan(
+ '\n',
+ delta,
+ false,
+ ParchmentStyle().putAll(newStyle.lineAttributes),
+ );
return true;
}
return false;
@@ -200,17 +226,26 @@ class _ParchmentMarkdownDecoder extends Converter {
final levelTag = match?.group(1);
if (levelTag != null) {
final level = levelTag.length;
- final newStyle = (style ?? ParchmentStyle())
- .put(ParchmentAttribute.heading.withValue(level));
+ final newStyle = (style ?? ParchmentStyle()).put(
+ ParchmentAttribute.heading.withValue(level),
+ );
final span = match?.group(2);
if (span == null) {
return false;
}
- _handleSpan(span, delta, false,
- ParchmentStyle().putAll(newStyle.inlineAttributes));
_handleSpan(
- '\n', delta, false, ParchmentStyle().putAll(newStyle.lineAttributes));
+ span,
+ delta,
+ false,
+ ParchmentStyle().putAll(newStyle.inlineAttributes),
+ );
+ _handleSpan(
+ '\n',
+ delta,
+ false,
+ ParchmentStyle().putAll(newStyle.lineAttributes),
+ );
return true;
}
@@ -218,7 +253,11 @@ class _ParchmentMarkdownDecoder extends Converter {
}
void _handleSpan(
- String span, Delta delta, bool addNewLine, ParchmentStyle? outerStyle) {
+ String span,
+ Delta delta,
+ bool addNewLine,
+ ParchmentStyle? outerStyle,
+ ) {
var start = _handleStyles(span, delta, outerStyle);
span = span.substring(start);
@@ -255,14 +294,18 @@ class _ParchmentMarkdownDecoder extends Converter {
if (match.start > start) {
if (span.substring(match.start - 1, match.start) == '[') {
delta.insert(
- span.substring(start, match.start - 1), outerStyle?.toJson());
+ span.substring(start, match.start - 1),
+ outerStyle?.toJson(),
+ );
start = match.start -
1 +
_handleLinks(span.substring(match.start - 1), delta, outerStyle);
continue;
} else {
delta.insert(
- span.substring(start, match.start), outerStyle?.toJson());
+ span.substring(start, match.start),
+ outerStyle?.toJson(),
+ );
}
}
@@ -300,19 +343,20 @@ class _ParchmentMarkdownDecoder extends Converter {
ParchmentStyle _fromStyleTag(String styleTag) {
assert(
- (styleTag == '`') |
- (styleTag == '~~') |
- (styleTag == '_') |
- (styleTag == '*') |
- (styleTag == '__') |
- (styleTag == '**') |
- (styleTag == '__*') |
- (styleTag == '**_') |
- (styleTag == '_**') |
- (styleTag == '*__') |
- (styleTag == '***') |
- (styleTag == '___'),
- 'Invalid style tag \'$styleTag\'');
+ (styleTag == '`') |
+ (styleTag == '~~') |
+ (styleTag == '_') |
+ (styleTag == '*') |
+ (styleTag == '__') |
+ (styleTag == '**') |
+ (styleTag == '__*') |
+ (styleTag == '**_') |
+ (styleTag == '_**') |
+ (styleTag == '*__') |
+ (styleTag == '***') |
+ (styleTag == '___'),
+ 'Invalid style tag \'$styleTag\'',
+ );
assert(styleTag.isNotEmpty, 'Style tag must not be empty');
if (styleTag == '`') {
return ParchmentStyle().put(ParchmentAttribute.inlineCode);
@@ -321,8 +365,10 @@ class _ParchmentMarkdownDecoder extends Converter {
return ParchmentStyle().put(ParchmentAttribute.strikethrough);
}
if (styleTag.length == 3) {
- return ParchmentStyle()
- .putAll([ParchmentAttribute.bold, ParchmentAttribute.italic]);
+ return ParchmentStyle().putAll([
+ ParchmentAttribute.bold,
+ ParchmentAttribute.italic,
+ ]);
}
if (styleTag.length == 2) {
return ParchmentStyle().put(ParchmentAttribute.bold);
@@ -344,8 +390,9 @@ class _ParchmentMarkdownDecoder extends Converter {
if (text == null || href == null) {
return start;
}
- final newStyle = (outerStyle ?? ParchmentStyle())
- .put(ParchmentAttribute.link.fromString(href));
+ final newStyle = (outerStyle ?? ParchmentStyle()).put(
+ ParchmentAttribute.link.fromString(href),
+ );
_handleSpan(text, delta, false, newStyle);
start = match.end;
@@ -376,7 +423,10 @@ class _ParchmentMarkdownEncoder extends Converter {
}
void handleText(
- StringBuffer buffer, TextNode node, ParchmentStyle currentInlineStyle) {
+ StringBuffer buffer,
+ TextNode node,
+ ParchmentStyle currentInlineStyle,
+ ) {
final style = node.style;
final rightPadding = _trimRight(buffer);
@@ -459,9 +509,9 @@ class _ParchmentMarkdownEncoder extends Converter {
lineBuffer.write(currentItemOrders[currentLevel]);
} else if (node.style.containsSame(ParchmentAttribute.cl)) {
lineBuffer.write('- [');
- if ((lineNode as LineNode)
- .style
- .contains(ParchmentAttribute.checked)) {
+ if ((lineNode as LineNode).style.contains(
+ ParchmentAttribute.checked,
+ )) {
lineBuffer.write('X');
} else {
lineBuffer.write(' ');
@@ -492,8 +542,11 @@ class _ParchmentMarkdownEncoder extends Converter {
return buffer.toString();
}
- void _writeAttribute(StringBuffer buffer, ParchmentAttribute? attribute,
- {bool close = false}) {
+ void _writeAttribute(
+ StringBuffer buffer,
+ ParchmentAttribute? attribute, {
+ bool close = false,
+ }) {
if (attribute == ParchmentAttribute.bold) {
_writeBoldTag(buffer);
} else if (attribute == ParchmentAttribute.italic) {
@@ -503,13 +556,19 @@ class _ParchmentMarkdownEncoder extends Converter {
} else if (attribute == ParchmentAttribute.strikethrough) {
_writeStrikeThoughTag(buffer);
} else if (attribute?.key == ParchmentAttribute.link.key) {
- _writeLinkTag(buffer, attribute as ParchmentAttribute,
- close: close);
+ _writeLinkTag(
+ buffer,
+ attribute as ParchmentAttribute,
+ close: close,
+ );
} else if (attribute?.key == ParchmentAttribute.heading.key) {
_writeHeadingTag(buffer, attribute as ParchmentAttribute);
} else if (attribute?.key == ParchmentAttribute.block.key) {
- _writeBlockTag(buffer, attribute as ParchmentAttribute,
- close: close);
+ _writeBlockTag(
+ buffer,
+ attribute as ParchmentAttribute,
+ close: close,
+ );
} else if (attribute?.key == ParchmentAttribute.checked.key) {
// no-op already handled in handleBlock
} else if (attribute?.key == ParchmentAttribute.indent.key) {
@@ -535,8 +594,11 @@ class _ParchmentMarkdownEncoder extends Converter {
buffer.write('~~');
}
- void _writeLinkTag(StringBuffer buffer, ParchmentAttribute link,
- {bool close = false}) {
+ void _writeLinkTag(
+ StringBuffer buffer,
+ ParchmentAttribute link, {
+ bool close = false,
+ }) {
if (close) {
buffer.write('](${link.value})');
} else {
@@ -549,8 +611,11 @@ class _ParchmentMarkdownEncoder extends Converter {
buffer.write('${'#' * level} ');
}
- void _writeBlockTag(StringBuffer buffer, ParchmentAttribute block,
- {bool close = false}) {
+ void _writeBlockTag(
+ StringBuffer buffer,
+ ParchmentAttribute block, {
+ bool close = false,
+ }) {
if (block == ParchmentAttribute.code) {
if (close) {
buffer.write('\n```');
diff --git a/packages/parchment/lib/src/document.dart b/packages/parchment/lib/src/document.dart
index c3aee4b9..b35e11de 100644
--- a/packages/parchment/lib/src/document.dart
+++ b/packages/parchment/lib/src/document.dart
@@ -38,25 +38,27 @@ class ParchmentChange {
/// A rich text document.
class ParchmentDocument {
/// Creates new empty Parchment document.
- ParchmentDocument(
- {ParchmentHeuristics heuristics = ParchmentHeuristics.fallback})
- : _heuristics = heuristics,
+ ParchmentDocument({
+ ParchmentHeuristics heuristics = ParchmentHeuristics.fallback,
+ }) : _heuristics = heuristics,
_delta = Delta()..insert('\n') {
_loadDocument(_delta);
}
/// Creates new ParchmentDocument from provided JSON `data`.
- ParchmentDocument.fromJson(List data,
- {ParchmentHeuristics heuristics = ParchmentHeuristics.fallback})
- : _heuristics = heuristics,
+ ParchmentDocument.fromJson(
+ List data, {
+ ParchmentHeuristics heuristics = ParchmentHeuristics.fallback,
+ }) : _heuristics = heuristics,
_delta = _migrateDelta(Delta.fromJson(data)) {
_loadDocument(_delta);
}
/// Creates new ParchmentDocument from provided `delta`.
- ParchmentDocument.fromDelta(Delta delta,
- {ParchmentHeuristics heuristics = ParchmentHeuristics.fallback})
- : _heuristics = heuristics,
+ ParchmentDocument.fromDelta(
+ Delta delta, {
+ ParchmentHeuristics heuristics = ParchmentHeuristics.fallback,
+ }) : _heuristics = heuristics,
_delta = _migrateDelta(delta) {
_loadDocument(_delta);
}
@@ -148,8 +150,10 @@ class ParchmentDocument {
final dataIsNotEmpty = (data is String) ? data.isNotEmpty : true;
- assert(index >= 0 && (dataIsNotEmpty || length > 0),
- 'With index $index, length $length and text "$data"');
+ assert(
+ index >= 0 && (dataIsNotEmpty || length > 0),
+ 'With index $index, length $length and text "$data"',
+ );
var delta = Delta();
@@ -180,8 +184,12 @@ class ParchmentDocument {
var change = Delta();
- final formatChange =
- _heuristics.applyFormatRules(this, index, length, attribute);
+ final formatChange = _heuristics.applyFormatRules(
+ this,
+ index,
+ length,
+ attribute,
+ );
if (formatChange.isNotEmpty) {
compose(formatChange, ChangeSource.local);
change = change.compose(formatChange);
@@ -251,8 +259,10 @@ class ParchmentDocument {
_delta = _delta.compose(change);
if (_delta != _root.toDelta()) {
- throw StateError('Compose produced inconsistent results. '
- 'This is likely due to a bug in the library. Tried to compose change $change from $source.');
+ throw StateError(
+ 'Compose produced inconsistent results. '
+ 'This is likely due to a bug in the library. Tried to compose change $change from $source.',
+ );
}
_controller.add(ParchmentChange(before, change, source));
}
@@ -268,8 +278,10 @@ class ParchmentDocument {
//
void _checkMutable() {
- assert(!_controller.isClosed,
- 'Cannot modify Parchment document after it was closed.');
+ assert(
+ !_controller.isClosed,
+ 'Cannot modify Parchment document after it was closed.',
+ );
}
/// Key of the embed attribute used in Parchment 0.x (prior to 1.0).
@@ -308,8 +320,10 @@ class ParchmentDocument {
/// Loads [document] delta into this document.
void _loadDocument(Delta doc) {
- assert((doc.last.data as String).endsWith('\n'),
- 'Invalid document delta. Document delta must always end with a line-break.');
+ assert(
+ (doc.last.data as String).endsWith('\n'),
+ 'Invalid document delta. Document delta must always end with a line-break.',
+ );
var offset = 0;
for (final op in doc.toList()) {
final style =
@@ -318,8 +332,10 @@ class ParchmentDocument {
final data = _normalizeData(op.data);
_root.insert(offset, data, style);
} else {
- throw ArgumentError.value(doc,
- 'Document Delta can only contain insert operations but ${op.key} found.');
+ throw ArgumentError.value(
+ doc,
+ 'Document Delta can only contain insert operations but ${op.key} found.',
+ );
}
offset += op.length;
}
diff --git a/packages/parchment/lib/src/document/attributes.dart b/packages/parchment/lib/src/document/attributes.dart
index 120ee711..040e03f9 100644
--- a/packages/parchment/lib/src/document/attributes.dart
+++ b/packages/parchment/lib/src/document/attributes.dart
@@ -200,7 +200,9 @@ class ParchmentAttribute implements ParchmentAttributeBuilder {
static ParchmentAttribute _fromKeyValue(String key, dynamic value) {
if (!_registry.containsKey(key)) {
throw ArgumentError.value(
- key, 'No attribute with key "$key" registered.');
+ key,
+ 'No attribute with key "$key" registered.',
+ );
}
final builder = _registry[key]!;
return builder.withValue(value);
@@ -383,8 +385,10 @@ class ParchmentStyle {
/// Returns JSON-serializable representation of this style.
Map? toJson() => _data.isEmpty
? null
- : _data.map((String _, ParchmentAttribute value) =>
- MapEntry(value.key, value.value));
+ : _data.map(
+ (String _, ParchmentAttribute value) =>
+ MapEntry(value.key, value.value),
+ );
@override
bool operator ==(Object other) {
@@ -396,8 +400,9 @@ class ParchmentStyle {
@override
int get hashCode {
- final hashes =
- _data.entries.map((entry) => Object.hash(entry.key, entry.value));
+ final hashes = _data.entries.map(
+ (entry) => Object.hash(entry.key, entry.value),
+ );
return Object.hashAll(hashes);
}
@@ -638,6 +643,9 @@ class IndentAttributeBuilder extends ParchmentAttributeBuilder {
return unset;
}
return ParchmentAttribute._(
- key, scope, math.min(_maxIndentationLevel, level));
+ key,
+ scope,
+ math.min(_maxIndentationLevel, level),
+ );
}
}
diff --git a/packages/parchment/lib/src/document/embeds.dart b/packages/parchment/lib/src/document/embeds.dart
index aa05f311..7e46f7c4 100644
--- a/packages/parchment/lib/src/document/embeds.dart
+++ b/packages/parchment/lib/src/document/embeds.dart
@@ -19,10 +19,14 @@ class EmbeddableObject {
this.type, {
required this.inline,
Map data = const {},
- }) : assert(!data.containsKey(kTypeKey),
- 'The "$kTypeKey" key is reserved in $EmbeddableObject data and cannot be used.'),
- assert(!data.containsKey(kInlineKey),
- 'The "$kInlineKey" key is reserved in $EmbeddableObject data and cannot be used.'),
+ }) : assert(
+ !data.containsKey(kTypeKey),
+ 'The "$kTypeKey" key is reserved in $EmbeddableObject data and cannot be used.',
+ ),
+ assert(
+ !data.containsKey(kInlineKey),
+ 'The "$kInlineKey" key is reserved in $EmbeddableObject data and cannot be used.',
+ ),
_data = Map.from(data);
/// The type of this object.
@@ -61,8 +65,9 @@ class EmbeddableObject {
int get hashCode {
if (_data.isEmpty) return Object.hash(type, inline);
- final dataHash =
- Object.hashAll(_data.entries.map((e) => Object.hash(e.key, e.value)));
+ final dataHash = Object.hashAll(
+ _data.entries.map((e) => Object.hash(e.key, e.value)),
+ );
return Object.hash(type, inline, dataHash);
}
@@ -76,10 +81,7 @@ class EmbeddableObject {
/// An object which can be embedded on the same line (inline) with regular text.
class SpanEmbed extends EmbeddableObject {
- SpanEmbed(
- super.type, {
- super.data,
- }) : super(inline: true);
+ SpanEmbed(super.type, {super.data}) : super(inline: true);
}
/// An object which occupies an entire line in a document and cannot co-exist
@@ -92,10 +94,7 @@ class SpanEmbed extends EmbeddableObject {
/// of embedded objects and allows users to define their own types.
class BlockEmbed extends EmbeddableObject {
/// Creates a new block embed of specified [type] and containing [data].
- BlockEmbed(
- super.type, {
- super.data,
- }) : super(inline: false);
+ BlockEmbed(super.type, {super.data}) : super(inline: false);
static final BlockEmbed horizontalRule = BlockEmbed('hr');
diff --git a/packages/parchment/lib/src/document/leaf.dart b/packages/parchment/lib/src/document/leaf.dart
index dc5cbc1d..dd305386 100644
--- a/packages/parchment/lib/src/document/leaf.dart
+++ b/packages/parchment/lib/src/document/leaf.dart
@@ -93,9 +93,10 @@ abstract base class LeafNode extends Node with StyledNode {
/// if provided [index] is `0`.
LeafNode isolate(int index, int length) {
assert(
- index >= 0 && index < this.length && (index + length <= this.length),
- 'Index or length is out of bounds. Index: $index, length: $length. '
- 'Actual node length: ${this.length}.');
+ index >= 0 && index < this.length && (index + length <= this.length),
+ 'Index or length is out of bounds. Index: $index, length: $length. '
+ 'Actual node length: ${this.length}.',
+ );
// Since `index < this.length` (guarded by assert) below line
// always returns a new node.
final target = splitAt(index)!;
@@ -113,8 +114,10 @@ abstract base class LeafNode extends Node with StyledNode {
@override
void applyStyle(ParchmentStyle value) {
- assert(value.isInline || value.isEmpty,
- 'Style cannot be applied to this leaf node: $value');
+ assert(
+ value.isInline || value.isEmpty,
+ 'Style cannot be applied to this leaf node: $value',
+ );
super.applyStyle(value);
}
@@ -139,8 +142,10 @@ abstract base class LeafNode extends Node with StyledNode {
@override
void insert(int index, Object data, ParchmentStyle? style) {
- assert(index >= 0 && (index <= length),
- 'Index out of bounds. Must be between 0 and $length, but got $index.');
+ assert(
+ index >= 0 && (index <= length),
+ 'Index out of bounds. Must be between 0 and $length, but got $index.',
+ );
final node = LeafNode(data);
if (index == length) {
insertAfter(node);
diff --git a/packages/parchment/lib/src/document/line.dart b/packages/parchment/lib/src/document/line.dart
index 752149ff..1a763c14 100644
--- a/packages/parchment/lib/src/document/line.dart
+++ b/packages/parchment/lib/src/document/line.dart
@@ -21,8 +21,12 @@ final class LineNode extends ContainerNode with StyledNode {
if (childCount == 1 && children.single is EmbedNode) {
return !(children.single as EmbedNode).value.inline;
}
- assert(children.every((child) =>
- child is TextNode || (child is EmbedNode && child.value.inline)));
+ assert(
+ children.every(
+ (child) =>
+ child is TextNode || (child is EmbedNode && child.value.inline),
+ ),
+ );
return false;
}
@@ -67,8 +71,10 @@ final class LineNode extends ContainerNode with StyledNode {
///
/// This is an equivalent of inserting a line-break character at [index].
LineNode splitAt(int index) {
- assert(index == 0 || (index > 0 && index < length),
- 'Index is out of bounds. Index: $index. Actual node length: $length.');
+ assert(
+ index == 0 || (index > 0 && index < length),
+ 'Index is out of bounds. Index: $index. Actual node length: $length.',
+ );
final line = clone();
insertAfter(line);
@@ -248,16 +254,23 @@ final class LineNode extends ContainerNode with StyledNode {
if (isLineFormat) {
assert(
- style.values
- .every((attr) => attr.scope == ParchmentAttributeScope.line),
- 'It is not allowed to apply inline attributes to line itself.');
+ style.values.every(
+ (attr) => attr.scope == ParchmentAttributeScope.line,
+ ),
+ 'It is not allowed to apply inline attributes to line itself.',
+ );
_formatAndOptimize(style);
} else {
// Otherwise forward to children as it's an inline format update.
- assert(index + local != thisLength,
- 'It is not allowed to apply inline attributes to line itself.');
- assert(style.values
- .every((attr) => attr.scope == ParchmentAttributeScope.inline));
+ assert(
+ index + local != thisLength,
+ 'It is not allowed to apply inline attributes to line itself.',
+ );
+ assert(
+ style.values.every(
+ (attr) => attr.scope == ParchmentAttributeScope.inline,
+ ),
+ );
super.retain(index, local, style);
}
@@ -321,8 +334,9 @@ final class LineNode extends ContainerNode with StyledNode {
final blockStyle = newStyle.get(ParchmentAttribute.block)!;
if (parent is BlockNode) {
- final parentStyle =
- (parent as BlockNode).style.get(ParchmentAttribute.block);
+ final parentStyle = (parent as BlockNode).style.get(
+ ParchmentAttribute.block,
+ );
if (blockStyle == ParchmentAttribute.block.unset) {
unwrap();
} else if (blockStyle != parentStyle) {
diff --git a/packages/parchment/lib/src/document/node.dart b/packages/parchment/lib/src/document/node.dart
index d3e4544a..e26ea2cb 100644
--- a/packages/parchment/lib/src/document/node.dart
+++ b/packages/parchment/lib/src/document/node.dart
@@ -267,8 +267,10 @@ abstract base class ContainerNode extends Node {
/// Content length of this node's children. To get number of children in this
/// node use [childCount].
@override
- int get length => _length ??=
- _children.fold(0, (current, node) => current + node.length);
+ int get length => _length ??= _children.fold(
+ 0,
+ (current, node) => current + node.length,
+ );
@override
void insert(int index, Object data, ParchmentStyle? style) {
diff --git a/packages/parchment/lib/src/heuristics.dart b/packages/parchment/lib/src/heuristics.dart
index afa9c609..0dc210ac 100644
--- a/packages/parchment/lib/src/heuristics.dart
+++ b/packages/parchment/lib/src/heuristics.dart
@@ -70,8 +70,12 @@ class ParchmentHeuristics {
/// Applies heuristic rules to specified format operation based on current
/// state of Parchment [document].
- Delta applyFormatRules(ParchmentDocument document, int index, int length,
- ParchmentAttribute value) {
+ Delta applyFormatRules(
+ ParchmentDocument document,
+ int index,
+ int length,
+ ParchmentAttribute value,
+ ) {
final delta = document.toDelta();
for (var rule in formatRules) {
final result = rule.apply(delta, index, length, value);
diff --git a/packages/parchment/lib/src/heuristics/delete_rules.dart b/packages/parchment/lib/src/heuristics/delete_rules.dart
index 2cace65d..b81fdb5b 100644
--- a/packages/parchment/lib/src/heuristics/delete_rules.dart
+++ b/packages/parchment/lib/src/heuristics/delete_rules.dart
@@ -94,7 +94,8 @@ class PreserveLineStyleOnMergeRule extends DeleteRule {
Map? _unsetAttributes(Map? attributes) {
if (attributes == null) return null;
return attributes.map(
- (String key, dynamic value) => MapEntry(key, null));
+ (String key, dynamic value) => MapEntry(key, null),
+ );
}
}
diff --git a/packages/parchment/lib/src/heuristics/format_rules.dart b/packages/parchment/lib/src/heuristics/format_rules.dart
index 6e48e64b..8ab974d1 100644
--- a/packages/parchment/lib/src/heuristics/format_rules.dart
+++ b/packages/parchment/lib/src/heuristics/format_rules.dart
@@ -10,7 +10,11 @@ abstract class FormatRule {
/// Applies heuristic rule to a retain (format) operation on a [document] and
/// returns resulting [Delta].
Delta? apply(
- Delta document, int index, int length, ParchmentAttribute attribute);
+ Delta document,
+ int index,
+ int length,
+ ParchmentAttribute attribute,
+ );
}
/// Produces Delta with line-level attributes applied strictly to
@@ -20,7 +24,11 @@ class ResolveLineFormatRule extends FormatRule {
@override
Delta? apply(
- Delta document, int index, int length, ParchmentAttribute attribute) {
+ Delta document,
+ int index,
+ int length,
+ ParchmentAttribute attribute,
+ ) {
if (attribute.scope != ParchmentAttributeScope.line) return null;
var result = Delta()..retain(index);
@@ -57,8 +65,12 @@ class ResolveLineFormatRule extends FormatRule {
return result;
}
- Delta _applyAttribute(String text, Operation op, ParchmentAttribute attribute,
- {bool firstOnly = false}) {
+ Delta _applyAttribute(
+ String text,
+ Operation op,
+ ParchmentAttribute attribute, {
+ bool firstOnly = false,
+ }) {
final result = Delta();
var offset = 0;
var lf = text.indexOf('\n');
@@ -97,7 +109,11 @@ class ResolveInlineFormatRule extends FormatRule {
@override
Delta? apply(
- Delta document, int index, int length, ParchmentAttribute attribute) {
+ Delta document,
+ int index,
+ int length,
+ ParchmentAttribute attribute,
+ ) {
if (attribute.scope != ParchmentAttributeScope.inline) return null;
final result = Delta()..retain(index);
@@ -137,7 +153,11 @@ class FormatLinkAtCaretPositionRule extends FormatRule {
@override
Delta? apply(
- Delta document, int index, int length, ParchmentAttribute attribute) {
+ Delta document,
+ int index,
+ int length,
+ ParchmentAttribute attribute,
+ ) {
if (attribute.key != ParchmentAttribute.link.key) return null;
// If user selection is not collapsed we let it fallback to default rule
// which simply applies the attribute to selected range.
diff --git a/packages/parchment/lib/src/heuristics/insert_rules.dart b/packages/parchment/lib/src/heuristics/insert_rules.dart
index f549ba08..0a166d10 100644
--- a/packages/parchment/lib/src/heuristics/insert_rules.dart
+++ b/packages/parchment/lib/src/heuristics/insert_rules.dart
@@ -359,7 +359,7 @@ class PreserveBlockStyleOnInsertRule extends InsertRule {
if (!lineStyle.containsKey(ParchmentAttribute.block.key)) return null;
final blockStyle = {
- ParchmentAttribute.block.key: lineStyle[ParchmentAttribute.block.key]
+ ParchmentAttribute.block.key: lineStyle[ParchmentAttribute.block.key],
};
Map resetStyle = {};
@@ -447,7 +447,9 @@ class InsertBlockEmbedsRule extends InsertRule {
}
Map? _getLineStyle(
- DeltaIterator iterator, Operation current) {
+ DeltaIterator iterator,
+ Operation current,
+ ) {
final currentText = current.data is String ? current.data as String : '';
if (currentText.contains('\n')) {
diff --git a/packages/parchment/test/codecs/html_test.dart b/packages/parchment/test/codecs/html_test.dart
index 410c0a1b..43948185 100644
--- a/packages/parchment/test/codecs/html_test.dart
+++ b/packages/parchment/test/codecs/html_test.dart
@@ -16,7 +16,7 @@ void main() {
test('plain text', () {
final doc = ParchmentDocument.fromJson([
- {'insert': 'Something in the way mmmm...\n'}
+ {'insert': 'Something in the way mmmm...\n'},
]);
expect(codec.encode(doc), 'Something in the way mmmm...');
});
@@ -26,12 +26,14 @@ void main() {
{'insert': 'Something '},
{
'insert': 'in the way',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
- {'insert': ' mmmm...\n'}
+ {'insert': ' mmmm...\n'},
]);
expect(
- codec.encode(doc), 'Something in the way mmmm...');
+ codec.encode(doc),
+ 'Something in the way mmmm...',
+ );
});
test('background color', () {
@@ -39,12 +41,14 @@ void main() {
{'insert': 'Something '},
{
'insert': 'in the way',
- 'attributes': {'bg': 0xFFFF0000}
+ 'attributes': {'bg': 0xFFFF0000},
},
- {'insert': ' mmmm...\n'}
+ {'insert': ' mmmm...\n'},
]);
- expect(codec.encode(doc),
- 'Something in the way mmmm...');
+ expect(
+ codec.encode(doc),
+ 'Something in the way mmmm...',
+ );
});
test('text color', () {
@@ -52,52 +56,58 @@ void main() {
{'insert': 'Something '},
{
'insert': 'in the way',
- 'attributes': {'fg': 0xFFFF0000}
+ 'attributes': {'fg': 0xFFFF0000},
},
- {'insert': ' mmmm...\n'}
+ {'insert': ' mmmm...\n'},
]);
- expect(codec.encode(doc),
- 'Something in the way mmmm...');
+ expect(
+ codec.encode(doc),
+ 'Something in the way mmmm...',
+ );
});
test('italic + code + underlined + strikethrough text', () {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Something ',
- 'attributes': {'s': true, 'u': true}
+ 'attributes': {'s': true, 'u': true},
},
{
'insert': 'in the way',
- 'attributes': {'i': true}
+ 'attributes': {'i': true},
},
{
'insert': ' mmmm...',
- 'attributes': {'c': true}
+ 'attributes': {'c': true},
},
- {'insert': '\n'}
+ {'insert': '\n'},
]);
- expect(codec.encode(doc),
- 'Something in the way mmmm...');
+ expect(
+ codec.encode(doc),
+ 'Something in the way mmmm...',
+ );
});
test('embedded inline attributes text', () {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Something ',
- 'attributes': {'a': 'https://wikipedia.org', 'u': true}
+ 'attributes': {'a': 'https://wikipedia.org', 'u': true},
},
{
'insert': 'in the way',
- 'attributes': {'i': true, 'u': true}
+ 'attributes': {'i': true, 'u': true},
},
{
'insert': ' mmmm...',
- 'attributes': {'u': true}
+ 'attributes': {'u': true},
},
- {'insert': '\n'}
+ {'insert': '\n'},
]);
- expect(codec.encode(doc),
- 'Something in the way mmmm...');
+ expect(
+ codec.encode(doc),
+ 'Something in the way mmmm...',
+ );
});
test('tangled inline tags', () {
@@ -105,20 +115,22 @@ void main() {
{'insert': 'AAA'},
{
'insert': 'BB',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{
'insert': 'B',
- 'attributes': {'b': true, 's': true}
+ 'attributes': {'b': true, 's': true},
},
{
'insert': 'CCC',
- 'attributes': {'s': true}
+ 'attributes': {'s': true},
},
- {'insert': '\n'}
+ {'insert': '\n'},
]);
- expect(codec.encode(doc),
- 'AAABBBCCC');
+ expect(
+ codec.encode(doc),
+ 'AAABBBCCC',
+ );
});
test('html escaping', () {
@@ -128,34 +140,37 @@ void main() {
'HTML special characters like < > & are escaped, but not \' " /.\n',
},
]);
- expect(codec.encode(doc),
- 'HTML special characters like < > & are escaped, but not \' " /.');
+ expect(
+ codec.encode(doc),
+ 'HTML special characters like < > & are escaped, but not \' " /.',
+ );
});
- test('multiple line breaks in a row should render as actual line breaks',
- () {
- // This has three blank lines between the Line 1/Line2 pair.
- // The Line3/Line4 pair does not have blank lines, but both pairs should render to the
- // same height. The Line5/Line6 pair has 3 blank lines but also were emboldened in Fleather.
- // The blank line after Line5 has a space in it just to distinguish it from a completely
- // blank line.
- final doc = ParchmentDocument.fromJson([
- {
- 'insert':
- 'Line 1\n\n\n\nLine 2\nLine3\nnot blank1\nnot blank2\nnot blank3\nLine 4\n'
- },
- {
- 'insert': 'Line 5',
- 'attributes': {'b': true}
- },
- {'insert': '\n \n\n\n'},
- {
- 'insert': 'Line 6',
- 'attributes': {'b': true}
- },
- {'insert': '\n'}
- ]);
- expect(
+ test(
+ 'multiple line breaks in a row should render as actual line breaks',
+ () {
+ // This has three blank lines between the Line 1/Line2 pair.
+ // The Line3/Line4 pair does not have blank lines, but both pairs should render to the
+ // same height. The Line5/Line6 pair has 3 blank lines but also were emboldened in Fleather.
+ // The blank line after Line5 has a space in it just to distinguish it from a completely
+ // blank line.
+ final doc = ParchmentDocument.fromJson([
+ {
+ 'insert':
+ 'Line 1\n\n\n\nLine 2\nLine3\nnot blank1\nnot blank2\nnot blank3\nLine 4\n',
+ },
+ {
+ 'insert': 'Line 5',
+ 'attributes': {'b': true},
+ },
+ {'insert': '\n \n\n\n'},
+ {
+ 'insert': 'Line 6',
+ 'attributes': {'b': true},
+ },
+ {'insert': '\n'},
+ ]);
+ expect(
codec.encode(doc),
'Line 1
'
'
'
@@ -171,45 +186,48 @@ void main() {
'
'
'
'
'
'
- 'Line 6
');
- });
+ 'Line 6
',
+ );
+ },
+ );
test('several styled lines in a row', () {
// Tests that we don't generate nested tags.
final doc = ParchmentDocument.fromJson([
{
'insert': 'Bold',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{'insert': '\n'},
{
'insert': 'Italic',
- 'attributes': {'i': true}
+ 'attributes': {'i': true},
},
{'insert': '\n'},
{
'insert': 'Bold',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{'insert': '\n'},
{
'insert': 'Italic',
- 'attributes': {'i': true}
+ 'attributes': {'i': true},
},
{'insert': '\n'},
{
'insert': 'Bold',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{'insert': '\n'},
]);
expect(
- codec.encode(doc),
- '
Bold
'
- 'Italic
'
- 'Bold
'
- 'Italic
'
- 'Bold
');
+ codec.encode(doc),
+ 'Bold
'
+ 'Italic
'
+ 'Bold
'
+ 'Italic
'
+ 'Bold
',
+ );
});
});
@@ -219,7 +237,7 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 1}
+ 'attributes': {'heading': 1},
},
]);
@@ -231,8 +249,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 2}
- }
+ 'attributes': {'heading': 2},
+ },
]);
expect(codec.encode(doc), 'Hello World!
');
@@ -243,8 +261,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 3}
- }
+ 'attributes': {'heading': 3},
+ },
]);
expect(codec.encode(doc), 'Hello World!
');
@@ -255,8 +273,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 4}
- }
+ 'attributes': {'heading': 4},
+ },
]);
expect(codec.encode(doc), 'Hello World!
');
@@ -267,8 +285,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 5}
- }
+ 'attributes': {'heading': 5},
+ },
]);
expect(codec.encode(doc), 'Hello World!
');
@@ -279,8 +297,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 6}
- }
+ 'attributes': {'heading': 6},
+ },
]);
expect(codec.encode(doc), 'Hello World!
');
@@ -300,17 +318,19 @@ void main() {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Hello World!',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{'insert': '\n'},
{
'insert': 'Bye World!',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
- {'insert': '\n'}
+ {'insert': '\n'},
]);
- expect(codec.encode(doc),
- 'Hello World!
Bye World!
');
+ expect(
+ codec.encode(doc),
+ 'Hello World!
Bye World!
',
+ );
});
});
@@ -320,12 +340,14 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'quote'}
- }
+ 'attributes': {'block': 'quote'},
+ },
]);
- expect(codec.encode(doc),
- 'Hello World!
');
+ expect(
+ codec.encode(doc),
+ 'Hello World!
',
+ );
});
test('Consecutive with same style', () {
@@ -333,19 +355,20 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'quote'}
+ 'attributes': {'block': 'quote'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'quote'}
- }
+ 'attributes': {'block': 'quote'},
+ },
]);
expect(
- codec.encode(doc),
- 'Hello World!
'
- 'Hello World!
');
+ codec.encode(doc),
+ 'Hello World!
'
+ 'Hello World!
',
+ );
});
test('Consecutive with different styles', () {
@@ -353,19 +376,20 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'quote'}
+ 'attributes': {'block': 'quote'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'quote', 'alignment': 'center'}
- }
+ 'attributes': {'block': 'quote', 'alignment': 'center'},
+ },
]);
expect(
- codec.encode(doc),
- 'Hello World!
'
- 'Hello World!
');
+ codec.encode(doc),
+ 'Hello World!
'
+ 'Hello World!
',
+ );
});
});
@@ -374,18 +398,18 @@ void main() {
{'insert': 'void main() {'},
{
'insert': '\n\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{'insert': ' print("Hello World!");'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{'insert': '}'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
- }
+ 'attributes': {'block': 'code'},
+ },
]);
expect(
@@ -403,7 +427,7 @@ void main() {
{'insert': 'some code'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{'insert': 'Hello world\n'},
]);
@@ -419,13 +443,13 @@ void main() {
{'insert': 'some code'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{
'insert': 'Hello world',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
- {'insert': '\n'}
+ {'insert': '\n'},
]);
expect(
codec.encode(doc),
@@ -439,17 +463,17 @@ void main() {
{'insert': 'Hello world\n'},
{
'insert': 'Another',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{'insert': ' one\n'},
{'insert': 'some '},
{
'insert': 'quote',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{
'insert': '\n',
- 'attributes': {'block': 'quote'}
+ 'attributes': {'block': 'quote'},
},
]);
expect(
@@ -464,16 +488,16 @@ void main() {
final doc = ParchmentDocument.fromJson([
{
'insert':
- 'Hello world\nHello world\nHello world\nHello world\nsome code'
+ 'Hello world\nHello world\nHello world\nHello world\nsome code',
},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{'insert': 'Hello world\nsome quote'},
{
'insert': '\n',
- 'attributes': {'block': 'quote'}
+ 'attributes': {'block': 'quote'},
},
{'insert': 'Hello world\n'},
]);
@@ -495,38 +519,42 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'This is Fleather!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
- }
+ 'attributes': {'block': 'ol'},
+ },
]);
- expect(codec.encode(doc),
- '- Hello World!
- This is Fleather!
');
+ expect(
+ codec.encode(doc),
+ '- Hello World!
- This is Fleather!
',
+ );
});
test('List with bold', () {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Hello World!',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'This is Fleather!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
- }
+ 'attributes': {'block': 'ol'},
+ },
]);
- expect(codec.encode(doc),
- '- Hello World!
- This is Fleather!
');
+ expect(
+ codec.encode(doc),
+ '- Hello World!
- This is Fleather!
',
+ );
});
test('Unordered list', () {
@@ -534,17 +562,19 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
+ 'attributes': {'block': 'ul'},
},
{'insert': 'This is Fleather!'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
- }
+ 'attributes': {'block': 'ul'},
+ },
]);
- expect(codec.encode(doc),
- '- Hello World!
- This is Fleather!
');
+ expect(
+ codec.encode(doc),
+ '- Hello World!
- This is Fleather!
',
+ );
});
test('Successive list', () {
@@ -552,23 +582,23 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'This is Fleather!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': '\nHello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
+ 'attributes': {'block': 'ul'},
},
{'insert': 'This is Fleather!'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
- }
+ 'attributes': {'block': 'ul'},
+ },
]);
expect(
@@ -590,21 +620,22 @@ void main() {
{'insert': 'item'},
{
'insert': '\n',
- 'attributes': {'block': 'cl', 'checked': true}
+ 'attributes': {'block': 'cl', 'checked': true},
},
{'insert': 'item'},
{
'insert': '\n',
- 'attributes': {'block': 'cl'}
- }
+ 'attributes': {'block': 'cl'},
+ },
]);
expect(
- codec.encode(doc),
- '');
+ codec.encode(doc),
+ '',
+ );
});
test('Checklist followed by a link', () {
@@ -612,28 +643,29 @@ void main() {
{'insert': 'Check - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'cl', 'checked': true}
+ 'attributes': {'block': 'cl', 'checked': true},
},
{'insert': 'Check - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'cl'}
+ 'attributes': {'block': 'cl'},
},
{'insert': 'A link to a '},
{
'insert': 'site',
- 'attributes': {'a': 'https://example.com'}
+ 'attributes': {'a': 'https://example.com'},
},
- {'insert': '.\n'}
+ {'insert': '.\n'},
]);
expect(
- codec.encode(doc),
- ''
- 'A link to a site.
');
+ codec.encode(doc),
+ ''
+ 'A link to a site.
',
+ );
});
test('Checklist followed by a paragraph', () {
@@ -641,22 +673,23 @@ void main() {
{'insert': 'Check - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'cl', 'checked': true}
+ 'attributes': {'block': 'cl', 'checked': true},
},
{'insert': 'Check - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'cl'}
+ 'attributes': {'block': 'cl'},
},
{'insert': 'Paragraph\n'},
]);
expect(
- codec.encode(doc),
- ''
- 'Paragraph
');
+ codec.encode(doc),
+ ''
+ 'Paragraph
',
+ );
});
});
@@ -667,11 +700,13 @@ void main() {
'insert': 'Hello World!',
'attributes': {'a': 'http://fake.link'},
},
- {'insert': '\n'}
+ {'insert': '\n'},
]);
expect(
- codec.encode(doc), 'Hello World!');
+ codec.encode(doc),
+ 'Hello World!',
+ );
});
test('Italic', () {
@@ -680,11 +715,13 @@ void main() {
'insert': 'Hello World!',
'attributes': {'a': 'http://fake.link', 'i': true},
},
- {'insert': '\n'}
+ {'insert': '\n'},
]);
- expect(codec.encode(doc),
- 'Hello World!');
+ expect(
+ codec.encode(doc),
+ 'Hello World!',
+ );
});
test('In list', () {
@@ -696,11 +733,13 @@ void main() {
{
'insert': '\n',
'attributes': {'block': 'ul'},
- }
+ },
]);
- expect(codec.encode(doc),
- '');
+ expect(
+ codec.encode(doc),
+ '',
+ );
});
});
@@ -712,12 +751,14 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'direction': 'rtl'}
- }
+ 'attributes': {'direction': 'rtl'},
+ },
]);
- expect(codec.encode(doc),
- 'Hello World!
Hello World!
');
+ expect(
+ codec.encode(doc),
+ 'Hello World!
Hello World!
',
+ );
});
test('In list', () {
@@ -733,13 +774,15 @@ void main() {
'attributes': {
'direction': 'rtl',
'block': 'ol',
- 'alignment': 'center'
+ 'alignment': 'center',
},
},
]);
- expect(codec.encode(doc),
- '- Hello World!
- Hello World!
');
+ expect(
+ codec.encode(doc),
+ '- Hello World!
- Hello World!
',
+ );
});
});
@@ -749,11 +792,13 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'alignment': 'center'}
- }
+ 'attributes': {'alignment': 'center'},
+ },
]);
- expect(codec.encode(doc),
- 'Hello World!
');
+ expect(
+ codec.encode(doc),
+ 'Hello World!
',
+ );
});
test('all paragraph alignments', () {
@@ -761,23 +806,23 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'alignment': null}
+ 'attributes': {'alignment': null},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'alignment': 'right'}
+ 'attributes': {'alignment': 'right'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'alignment': 'center'}
+ 'attributes': {'alignment': 'center'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'alignment': 'justify'}
- }
+ 'attributes': {'alignment': 'justify'},
+ },
]);
expect(
codec.encode(doc),
@@ -793,32 +838,33 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'alignment': null}
+ 'attributes': {'block': 'ol', 'alignment': null},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'alignment': 'right'}
+ 'attributes': {'block': 'ol', 'alignment': 'right'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'alignment': 'center'}
+ 'attributes': {'block': 'ol', 'alignment': 'center'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'alignment': 'justify'}
- }
+ 'attributes': {'block': 'ol', 'alignment': 'justify'},
+ },
]);
expect(
- codec.encode(doc),
- ''
- '- Hello World!
'
- '- Hello World!
'
- '- Hello World!
'
- '- Hello World!
'
- '
');
+ codec.encode(doc),
+ ''
+ '- Hello World!
'
+ '- Hello World!
'
+ '- Hello World!
'
+ '- Hello World!
'
+ '
',
+ );
});
});
@@ -828,49 +874,50 @@ void main() {
{'insert': 'item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
{'insert': 'sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 2}
+ 'attributes': {'block': 'ol', 'indent': 2},
},
{'insert': 'sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 2}
+ 'attributes': {'block': 'ol', 'indent': 2},
},
{'insert': 'sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
{'insert': 'item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
]);
expect(
- codec.encode(doc),
- ''
- '- item
'
- ''
- '- sub-item
'
- ''
- '- sub-sub-item
'
- '- sub-sub-item
'
- '
'
- '- sub-item
'
- '
'
- '- item
'
- '
');
+ codec.encode(doc),
+ ''
+ '- item
'
+ ''
+ '- sub-item
'
+ ''
+ '- sub-sub-item
'
+ '- sub-sub-item
'
+ '
'
+ '- sub-item
'
+ '
'
+ '- item
'
+ '
',
+ );
});
test('Multiple nested lists - 4 levels', () {
@@ -878,62 +925,62 @@ void main() {
{'insert': 'item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
{'insert': 'sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 2}
+ 'attributes': {'block': 'ol', 'indent': 2},
},
{'insert': 'sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 2}
+ 'attributes': {'block': 'ol', 'indent': 2},
},
{'insert': 'sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
{'insert': 'item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
{'insert': 'sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 2}
+ 'attributes': {'block': 'ul', 'indent': 2},
},
{'insert': 'sub-sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 3}
+ 'attributes': {'block': 'ol', 'indent': 3},
},
{'insert': 'sub-sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 3}
+ 'attributes': {'block': 'ol', 'indent': 3},
},
{'insert': 'sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 2}
+ 'attributes': {'block': 'ul', 'indent': 2},
},
{'insert': 'sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
]);
@@ -972,27 +1019,29 @@ void main() {
{'insert': 'Level 1 - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'Level 1 - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'Level 2 - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 1}
+ 'attributes': {'block': 'ol', 'indent': 1},
},
{'insert': 'Level 2 - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 1}
+ 'attributes': {'block': 'ol', 'indent': 1},
},
- {'insert': 'No longer in list\n'}
+ {'insert': 'No longer in list\n'},
]);
- expect(codec.encode(doc),
- 'Test
- Level 1 - 1
- Level 1 - 2
- Level 2 - 1
- Level 2 - 2
No longer in list
');
+ expect(
+ codec.encode(doc),
+ 'Test
- Level 1 - 1
- Level 1 - 2
- Level 2 - 1
- Level 2 - 2
No longer in list
',
+ );
});
test('Extreme multi-level lists with trailing paragraph', () {
@@ -1001,44 +1050,44 @@ void main() {
{'insert': 'Level 1 - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'Level 1 - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'Level 2 - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 1}
+ 'attributes': {'block': 'ol', 'indent': 1},
},
{'insert': 'Level 2 - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 1}
+ 'attributes': {'block': 'ol', 'indent': 1},
},
{'insert': 'Level 3 - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 2}
+ 'attributes': {'block': 'ol', 'indent': 2},
},
{'insert': 'Level 3 - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 2}
+ 'attributes': {'block': 'ol', 'indent': 2},
},
{'insert': 'Level 4 - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 3}
+ 'attributes': {'block': 'ol', 'indent': 3},
},
{'insert': 'Level 4 - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 3}
+ 'attributes': {'block': 'ol', 'indent': 3},
},
- {'insert': 'No longer in list\n'}
+ {'insert': 'No longer in list\n'},
]);
expect(
codec.encode(doc),
@@ -1069,37 +1118,39 @@ void main() {
{'insert': 'Level 1 - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'Level 1 - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'Level 2 - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 1}
+ 'attributes': {'block': 'ol', 'indent': 1},
},
{'insert': 'Level 2 - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 1}
+ 'attributes': {'block': 'ol', 'indent': 1},
},
{'insert': 'No longer in list\n'},
{'insert': 'In a new list - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'In a new list - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
]);
- expect(codec.encode(doc),
- 'Test
- Level 1 - 1
- Level 1 - 2
- Level 2 - 1
- Level 2 - 2
No longer in list
- In a new list - 1
- In a new list - 2
');
+ expect(
+ codec.encode(doc),
+ 'Test
- Level 1 - 1
- Level 1 - 2
- Level 2 - 1
- Level 2 - 2
No longer in list
- In a new list - 1
- In a new list - 2
',
+ );
});
test('Successive multi-level lists', () {
@@ -1107,33 +1158,33 @@ void main() {
{'insert': 'Unordered'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
+ 'attributes': {'block': 'ul'},
},
{'insert': 'Sub - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 1}
+ 'attributes': {'block': 'ol', 'indent': 1},
},
{'insert': 'Ordered - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'Sub - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
{'insert': 'Sub - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
{'insert': 'Ordered - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
- }
+ 'attributes': {'block': 'ol'},
+ },
]);
expect(
codec.encode(doc),
@@ -1159,38 +1210,38 @@ void main() {
{'insert': 'Unordered'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
+ 'attributes': {'block': 'ul'},
},
{'insert': 'Sub - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 1}
+ 'attributes': {'block': 'ol', 'indent': 1},
},
{'insert': 'Sub - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 1}
+ 'attributes': {'block': 'ol', 'indent': 1},
},
{'insert': '\n'},
{'insert': 'Ordered - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'Sub - 1'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 1}
+ 'attributes': {'block': 'ol', 'indent': 1},
},
{'insert': 'Sub - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 1}
+ 'attributes': {'block': 'ol', 'indent': 1},
},
{'insert': 'Ordered - 2'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
]);
expect(
@@ -1219,13 +1270,14 @@ void main() {
{'insert': 'Something in the way...\nSomething in the way...'},
{
'insert': '\n',
- 'attributes': {'indent': 1}
+ 'attributes': {'indent': 1},
},
]);
expect(
- codec.encode(doc),
- 'Something in the way...
'
- 'Something in the way...
');
+ codec.encode(doc),
+ 'Something in the way...
'
+ 'Something in the way...
',
+ );
});
test('Quotes with indent', () {
@@ -1233,13 +1285,14 @@ void main() {
{'insert': 'Something in the way...\nSomething in the way...'},
{
'insert': '\n',
- 'attributes': {'block': 'quote', 'indent': 1}
+ 'attributes': {'block': 'quote', 'indent': 1},
},
]);
expect(
- codec.encode(doc),
- 'Something in the way...
'
- 'Something in the way...
');
+ codec.encode(doc),
+ 'Something in the way...
'
+ 'Something in the way...
',
+ );
});
test('Quote with embedded heading', () {
@@ -1247,17 +1300,19 @@ void main() {
{'insert': 'Quote'},
{
'insert': '\n',
- 'attributes': {'block': 'quote'}
+ 'attributes': {'block': 'quote'},
},
{'insert': 'header'},
{
'insert': '\n',
- 'attributes': {'block': 'quote', 'heading': 1}
+ 'attributes': {'block': 'quote', 'heading': 1},
},
{'insert': 'Not in quote\n'},
]);
- expect(codec.encode(doc),
- 'Quote
header
Not in quote
');
+ expect(
+ codec.encode(doc),
+ 'Quote
header
Not in quote
',
+ );
});
});
@@ -1266,7 +1321,7 @@ void main() {
final html =
'
';
final doc = ParchmentDocument.fromJson([
- {'insert': '\n'}
+ {'insert': '\n'},
]);
doc.insert(0, BlockEmbed.image('http://fake.link/image.png'));
@@ -1277,12 +1332,15 @@ void main() {
final html =
'
';
final doc = ParchmentDocument.fromJson([
- {'insert': '\n'}
+ {'insert': '\n'},
]);
doc.insert(
- 0,
- BlockEmbed.image('http://fake.link/image.png',
- data: {'style': 'max-width: 100%; object-fit: cover;'}));
+ 0,
+ BlockEmbed.image(
+ 'http://fake.link/image.png',
+ data: {'style': 'max-width: 100%; object-fit: cover;'},
+ ),
+ );
expect(codec.encode(doc), html);
});
@@ -1290,7 +1348,7 @@ void main() {
test('Line', () {
final html = '
';
final doc = ParchmentDocument.fromJson([
- {'insert': '\n'}
+ {'insert': '\n'},
]);
doc.insert(0, BlockEmbed.horizontalRule);
@@ -1309,7 +1367,7 @@ void main() {
test('Plain paragraph', () {
final html = 'Hello World!';
final doc = ParchmentDocument.fromJson([
- {'insert': 'Hello World!\n'}
+ {'insert': 'Hello World!\n'},
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1321,9 +1379,9 @@ void main() {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Hello',
- 'attributes': {'bg': 0xffff0000}
+ 'attributes': {'bg': 0xffff0000},
},
- {'insert': ' world!\n'}
+ {'insert': ' world!\n'},
]);
expect(codec.decode(htmlRGBA).toDelta(), doc.toDelta());
@@ -1335,9 +1393,9 @@ void main() {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Hello',
- 'attributes': {'fg': 0xffff0000}
+ 'attributes': {'fg': 0xffff0000},
},
- {'insert': ' world!\n'}
+ {'insert': ' world!\n'},
]);
expect(codec.decode(htmlRGBA).toDelta(), doc.toDelta());
@@ -1348,7 +1406,7 @@ void main() {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Hello World!',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{'insert': '\n'},
]);
@@ -1361,7 +1419,7 @@ void main() {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Hello World!',
- 'attributes': {'u': true}
+ 'attributes': {'u': true},
},
{'insert': '\n'},
]);
@@ -1374,7 +1432,7 @@ void main() {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Hello World!',
- 'attributes': {'s': true}
+ 'attributes': {'s': true},
},
{'insert': '\n'},
]);
@@ -1387,7 +1445,7 @@ void main() {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Hello World!',
- 'attributes': {'i': true}
+ 'attributes': {'i': true},
},
{'insert': '\n'},
]);
@@ -1400,7 +1458,7 @@ void main() {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Hello World!',
- 'attributes': {'i': true, 'b': true}
+ 'attributes': {'i': true, 'b': true},
},
{'insert': '\n'},
]);
@@ -1414,17 +1472,17 @@ void main() {
{'insert': 'AAA'},
{
'insert': 'BB',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{
'insert': 'B',
- 'attributes': {'b': true, 's': true}
+ 'attributes': {'b': true, 's': true},
},
{
'insert': 'CCC',
- 'attributes': {'s': true}
+ 'attributes': {'s': true},
},
- {'insert': '\n'}
+ {'insert': '\n'},
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
});
@@ -1435,17 +1493,17 @@ void main() {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Something ',
- 'attributes': {'a': 'https://wikipedia.org', 'u': true}
+ 'attributes': {'a': 'https://wikipedia.org', 'u': true},
},
{
'insert': 'in the way',
- 'attributes': {'i': true, 'u': true}
+ 'attributes': {'i': true, 'u': true},
},
{
'insert': ' mmmm...',
- 'attributes': {'u': true}
+ 'attributes': {'u': true},
},
- {'insert': '\n'}
+ {'insert': '\n'},
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
});
@@ -1458,7 +1516,7 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 1}
+ 'attributes': {'heading': 1},
},
]);
@@ -1471,8 +1529,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 2}
- }
+ 'attributes': {'heading': 2},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1484,8 +1542,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 3}
- }
+ 'attributes': {'heading': 3},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1497,8 +1555,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 4}
- }
+ 'attributes': {'heading': 4},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1510,8 +1568,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 5}
- }
+ 'attributes': {'heading': 5},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1523,8 +1581,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'heading': 6}
- }
+ 'attributes': {'heading': 6},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1536,9 +1594,7 @@ void main() {
test('simple', () {
final html = 'Hello World!
';
final doc = ParchmentDocument.fromJson([
- {
- 'insert': 'Hello World!\n',
- }
+ {'insert': 'Hello World!\n'},
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
});
@@ -1547,26 +1603,23 @@ void main() {
final html = 'Hello World!
';
final doc = ParchmentHtmlCodec().decode(html);
expect(
- doc.toDelta(),
- Delta()
- ..insert('Hello World!')
- ..insert('\n', {'indent': 1}));
+ doc.toDelta(),
+ Delta()
+ ..insert('Hello World!')
+ ..insert('\n', {'indent': 1}),
+ );
});
test('Paragraph with link', () {
final html =
'Hello World!Hello World! Another hello world!
';
final doc = ParchmentDocument.fromJson([
- {
- 'insert': 'Hello World!',
- },
+ {'insert': 'Hello World!'},
{
'insert': 'Hello World!',
'attributes': {'a': 'http://fake.link'},
},
- {
- 'insert': ' Another hello world!\n',
- }
+ {'insert': ' Another hello world!\n'},
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1576,26 +1629,18 @@ void main() {
final html =
'Hello World!Hello World! Another hello world!
Hello World!Hello World! Another hello world!
';
final doc = ParchmentDocument.fromJson([
- {
- 'insert': 'Hello World!',
- },
+ {'insert': 'Hello World!'},
{
'insert': 'Hello World!',
'attributes': {'a': 'http://fake.link'},
},
- {
- 'insert': ' Another hello world!\n',
- },
- {
- 'insert': 'Hello World!',
- },
+ {'insert': ' Another hello world!\n'},
+ {'insert': 'Hello World!'},
{
'insert': 'Hello World!',
'attributes': {'a': 'http://fake.link'},
},
- {
- 'insert': ' Another hello world!\n',
- }
+ {'insert': ' Another hello world!\n'},
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1608,8 +1653,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'quote'}
- }
+ 'attributes': {'block': 'quote'},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1624,18 +1669,18 @@ void main() {
{'insert': 'void main() {'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{'insert': ' print("Hello world!");'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{'insert': '}'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
- }
+ 'attributes': {'block': 'code'},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1648,7 +1693,7 @@ void main() {
{'insert': 'some code'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{'insert': 'Hello world\n'},
]);
@@ -1663,17 +1708,17 @@ void main() {
{'insert': 'Hello world\n'},
{
'insert': 'Another',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{'insert': ' one\n'},
{'insert': 'some '},
{
'insert': 'quote',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{
'insert': '\n',
- 'attributes': {'block': 'quote'}
+ 'attributes': {'block': 'quote'},
},
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1685,13 +1730,13 @@ void main() {
{'insert': 'an item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'another item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
- }
+ 'attributes': {'block': 'ol'},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1701,12 +1746,12 @@ void main() {
final doc = ParchmentDocument.fromJson([
{
'insert': 'Hello World!',
- 'attributes': {'b': true}
+ 'attributes': {'b': true},
},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
- }
+ 'attributes': {'block': 'ol'},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1718,13 +1763,13 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
+ 'attributes': {'block': 'ul'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
- }
+ 'attributes': {'block': 'ul'},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1738,8 +1783,8 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'alignment': 'center'}
- }
+ 'attributes': {'alignment': 'center'},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
});
@@ -1753,18 +1798,18 @@ void main() {
{'insert': 'Hello World!\nHello World!'},
{
'insert': '\n',
- 'attributes': {'alignment': 'right'}
+ 'attributes': {'alignment': 'right'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'alignment': 'center'}
+ 'attributes': {'alignment': 'center'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'alignment': 'justify'}
- }
+ 'attributes': {'alignment': 'justify'},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
});
@@ -1780,23 +1825,23 @@ void main() {
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'alignment': 'right'}
+ 'attributes': {'block': 'ol', 'alignment': 'right'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'alignment': 'center'}
+ 'attributes': {'block': 'ol', 'alignment': 'center'},
},
{'insert': 'Hello World!'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'alignment': 'justify'}
- }
+ 'attributes': {'block': 'ol', 'alignment': 'justify'},
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
});
@@ -1832,62 +1877,62 @@ void main() {
{'insert': 'item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
{'insert': 'sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 2}
+ 'attributes': {'block': 'ol', 'indent': 2},
},
{'insert': 'sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 2}
+ 'attributes': {'block': 'ol', 'indent': 2},
},
{'insert': 'sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
{'insert': 'item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol'}
+ 'attributes': {'block': 'ol'},
},
{'insert': 'sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
{'insert': 'sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 2}
+ 'attributes': {'block': 'ul', 'indent': 2},
},
{'insert': 'sub-sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 3}
+ 'attributes': {'block': 'ol', 'indent': 3},
},
{'insert': 'sub-sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ol', 'indent': 3}
+ 'attributes': {'block': 'ol', 'indent': 3},
},
{'insert': 'sub-sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 2}
+ 'attributes': {'block': 'ul', 'indent': 2},
},
{'insert': 'sub-item'},
{
'insert': '\n',
- 'attributes': {'block': 'ul', 'indent': 1}
+ 'attributes': {'block': 'ul', 'indent': 1},
},
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1899,7 +1944,7 @@ void main() {
String html = '

'
'
a
';
final doc = ParchmentDocument.fromJson([
- {'insert': '\n'}
+ {'insert': '\n'},
]);
doc.insert(0, 'a');
doc.insert(0, BlockEmbed.image('http://another.fake.link/image.png'));
@@ -1911,7 +1956,7 @@ void main() {
test('Image (no style)', () {
final html = '
';
final doc = ParchmentDocument.fromJson([
- {'insert': '\n'}
+ {'insert': '\n'},
]);
doc.insert(0, BlockEmbed.image('http://fake.link/image.png'));
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1921,14 +1966,15 @@ void main() {
final html =
'
';
final doc = ParchmentDocument.fromJson([
- {'insert': '\n'}
+ {'insert': '\n'},
]);
doc.insert(
- 0,
- BlockEmbed.image('http://fake.link/image.png', data: {
- 'width': 100,
- 'height': 100,
- }));
+ 0,
+ BlockEmbed.image(
+ 'http://fake.link/image.png',
+ data: {'width': 100, 'height': 100},
+ ),
+ );
expect(codec.decode(html).toDelta(), doc.toDelta());
});
@@ -1936,7 +1982,7 @@ void main() {
test('Line', () {
final html = '
';
final doc = ParchmentDocument.fromJson([
- {'insert': '\n'}
+ {'insert': '\n'},
]);
doc.insert(0, BlockEmbed.horizontalRule);
@@ -1952,7 +1998,7 @@ void main() {
'insert': 'Hello World!',
'attributes': {'a': 'http://fake.link'},
},
- {'insert': '\n'}
+ {'insert': '\n'},
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1966,7 +2012,7 @@ void main() {
'insert': 'Hello World!',
'attributes': {'a': 'http://fake.link', 'i': true},
},
- {'insert': '\n'}
+ {'insert': '\n'},
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1983,7 +2029,7 @@ void main() {
{
'insert': '\n',
'attributes': {'block': 'ul'},
- }
+ },
]);
expect(codec.decode(html).toDelta(), doc.toDelta());
@@ -1996,86 +2042,86 @@ final doc = [
{'insert': 'Fleather'},
{
'insert': '\n',
- 'attributes': {'heading': 1}
+ 'attributes': {'heading': 1},
},
{
'insert': 'Soft and gentle rich text editing for Flutter applications.',
- 'attributes': {'i': true}
+ 'attributes': {'i': true},
},
{'insert': '\nFleather is an '},
{
'insert': 'early preview',
- 'attributes': {'b': true, 'fg': 0xFFFF0000}
+ 'attributes': {'b': true, 'fg': 0xFFFF0000},
},
{'insert': ' open source library.\nDocumentation'},
{
'insert': '\n',
- 'attributes': {'heading': 3}
+ 'attributes': {'heading': 3},
},
{'insert': 'Quick Start'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
+ 'attributes': {'block': 'ul'},
},
{'insert': 'Data format and Document Model'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
+ 'attributes': {'block': 'ul'},
},
{'insert': 'Style attributes'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
+ 'attributes': {'block': 'ul'},
},
{'insert': 'Heuristic rules'},
{
'insert': '\n',
- 'attributes': {'block': 'ul'}
+ 'attributes': {'block': 'ul'},
},
{'insert': 'Clean and modern look'},
{
'insert': '\n',
- 'attributes': {'heading': 2}
+ 'attributes': {'heading': 2},
},
{'insert': 'Fleather’s rich text editor is built with '},
{
'insert': 'simplicity and flexibility',
- 'attributes': {'i': true}
+ 'attributes': {'i': true},
},
{
'insert':
- ' in mind. It provides clean interface for distraction-free editing. Think '
+ ' in mind. It provides clean interface for distraction-free editing. Think ',
},
{
'insert': 'Medium.com',
- 'attributes': {'c': true}
+ 'attributes': {'c': true},
},
// {'insert': '-like experience.\n'},
{'insert': '-like experience.\nimport ‘package:flutter/material.dart’;'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{'insert': 'import ‘package:parchment/parchment.dart’;'},
{
'insert': '\n\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{'insert': 'void main() {'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{'insert': ' print(“Hello world!”);'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
+ 'attributes': {'block': 'code'},
},
{'insert': '}'},
{
'insert': '\n',
- 'attributes': {'block': 'code'}
- }
+ 'attributes': {'block': 'code'},
+ },
];
final delta = Delta.fromJson(doc);
final htmlDoc = 'Fleather
'
diff --git a/packages/parchment/test/codecs/markdown_test.dart b/packages/parchment/test/codecs/markdown_test.dart
index 9af33088..9bb4b80c 100644
--- a/packages/parchment/test/codecs/markdown_test.dart
+++ b/packages/parchment/test/codecs/markdown_test.dart
@@ -75,11 +75,13 @@ void main() {
}
runFor(
- 'Okay, _this is in italics_ and _so is all of _ this_ but this is not\n\n',
- true);
+ 'Okay, _this is in italics_ and _so is all of _ this_ but this is not\n\n',
+ true,
+ );
runFor(
- 'Okay, *this is in italics* and *so is all of _ this* but this is not\n\n',
- false);
+ 'Okay, *this is in italics* and *so is all of _ this* but this is not\n\n',
+ false,
+ );
});
test('bold', () {
@@ -122,11 +124,13 @@ void main() {
}
runFor(
- 'Okay, **this is bold** and **so is all of __ this** but this is not\n\n',
- true);
+ 'Okay, **this is bold** and **so is all of __ this** but this is not\n\n',
+ true,
+ );
runFor(
- 'Okay, __this is bold__ and __so is all of __ this__ but this is not\n\n',
- false);
+ 'Okay, __this is bold__ and __so is all of __ this__ but this is not\n\n',
+ false,
+ );
});
test('strike through', () {
@@ -200,11 +204,14 @@ void main() {
}
runFor(
- '**this is bold** _this is in italics_ and **_this is both_**\n\n');
+ '**this is bold** _this is in italics_ and **_this is both_**\n\n',
+ );
runFor(
- '**this is bold** *this is in italics* and ***this is both***\n\n');
+ '**this is bold** *this is in italics* and ***this is both***\n\n',
+ );
runFor(
- '__this is bold__ _this is in italics_ and ___this is both___\n\n');
+ '__this is bold__ _this is in italics_ and ___this is both___\n\n',
+ );
});
test('link', () {
@@ -328,11 +335,14 @@ void main() {
final delta = document.toDelta();
expect(
- delta,
- Delta()
- ..insert('This is an H$level')
- ..insert(
- '\n', ParchmentAttribute.heading.withValue(level).toJson()));
+ delta,
+ Delta()
+ ..insert('This is an H$level')
+ ..insert(
+ '\n',
+ ParchmentAttribute.heading.withValue(level).toJson(),
+ ),
+ );
final andBack = parchmentMarkdown.encode(document);
expect(andBack, markdown);
@@ -479,8 +489,9 @@ void main() {
group('ParchmentMarkdownCodec.encode', () {
test('split adjacent paragraphs', () {
final delta = Delta()..insert('First line\nSecond line\n');
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
expect(result, 'First line\n\nSecond line\n\n');
});
@@ -493,15 +504,18 @@ void main() {
..insert('circus', attribute.toJson())
..insert('\n');
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
expect(result, expected);
}
runFor(ParchmentAttribute.bold, 'This **house** is a **circus**\n\n');
runFor(ParchmentAttribute.italic, 'This _house_ is a _circus_\n\n');
- runFor(ParchmentAttribute.strikethrough,
- 'This ~~house~~ is a ~~circus~~\n\n');
+ runFor(
+ ParchmentAttribute.strikethrough,
+ 'This ~~house~~ is a ~~circus~~\n\n',
+ );
});
test('intersecting inline styles', () {
@@ -517,8 +531,9 @@ void main() {
..insert('circus', b)
..insert('\n');
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
expect(result, 'This **house _is a_ circus**\n\n');
});
@@ -532,8 +547,9 @@ void main() {
..insert(' circus ', i)
..insert('\n');
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
expect(result, 'This **house** is a _circus_ \n\n');
});
@@ -547,8 +563,9 @@ void main() {
..insert(' circus ', i)
..insert('\n');
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
expect(result, 'This **_house_** is a _circus_ \n\n');
});
@@ -562,19 +579,24 @@ void main() {
..insert(' circus ', link.toJson())
..insert('\n');
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
expect(result, 'This **house** is a [circus](https://github.com) \n\n');
});
test('heading styles', () {
void runFor(
- ParchmentAttribute attribute, String source, String expected) {
+ ParchmentAttribute attribute,
+ String source,
+ String expected,
+ ) {
final delta = Delta()
..insert(source)
..insert('\n', attribute.toJson());
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
expect(result, expected);
}
@@ -587,13 +609,17 @@ void main() {
});
test('block styles', () {
- void runFor(ParchmentAttribute attribute, String source,
- String expected) {
+ void runFor(
+ ParchmentAttribute attribute,
+ String source,
+ String expected,
+ ) {
final delta = Delta()
..insert(source)
..insert('\n', attribute.toJson());
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
expect(result, expected);
}
@@ -607,16 +633,20 @@ void main() {
final delta = Delta()
..insert('Hello')
..insert('\n', ParchmentAttribute.ul.toJson());
- expect(parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta)),
- '* Hello\n\n');
expect(
- ParchmentMarkdownCodec(unorderedListToken: '-')
- .encode(ParchmentDocument.fromDelta(delta)),
- '- Hello\n\n');
+ parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta)),
+ '* Hello\n\n',
+ );
+ expect(
+ ParchmentMarkdownCodec(unorderedListToken: '-')
+ .encode(ParchmentDocument.fromDelta(delta)),
+ '- Hello\n\n',
+ );
expect(
- ParchmentMarkdownCodec(unorderedListToken: '+')
- .encode(ParchmentDocument.fromDelta(delta)),
- '+ Hello\n\n');
+ ParchmentMarkdownCodec(unorderedListToken: '+')
+ .encode(ParchmentDocument.fromDelta(delta)),
+ '+ Hello\n\n',
+ );
});
test('ol', () {
@@ -627,8 +657,9 @@ void main() {
..insert('\n', ParchmentAttribute.ol.toJson())
..insert('List')
..insert('\n', ParchmentAttribute.ol.toJson());
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
final expected = '1. Hello\n2. This is a\n3. List\n\n';
expect(result, expected);
});
@@ -641,8 +672,9 @@ void main() {
..insert('\n', {'block': 'ol', 'indent': 1})
..insert('List')
..insert('\n', {'block': 'ol'});
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
final expected = '1. Hello\n 1. This is a\n2. List\n\n';
expect(result, expected);
});
@@ -651,31 +683,34 @@ void main() {
final delta = Delta()
..insert('Hello')
..insert('\n', ParchmentAttribute.cl.toJson())
- ..insert(
- 'This is a',
- )
+ ..insert('This is a')
..insert('\n', {
...ParchmentAttribute.cl.toJson(),
...ParchmentAttribute.checked.toJson(),
})
..insert('Checklist')
..insert('\n', ParchmentAttribute.cl.toJson());
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
final expected = '- [ ] Hello\n- [X] This is a\n- [ ] Checklist\n\n';
expect(result, expected);
});
test('multiline blocks', () {
- void runFor(ParchmentAttribute attribute, String source,
- String expected) {
+ void runFor(
+ ParchmentAttribute attribute,
+ String source,
+ String expected,
+ ) {
final delta = Delta()
..insert(source)
..insert('\n', attribute.toJson())
..insert(source)
..insert('\n', attribute.toJson());
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
expect(result, expected);
}
@@ -686,8 +721,9 @@ void main() {
});
test('multiple styles', () {
- final result =
- parchmentMarkdown.encode(ParchmentDocument.fromDelta(delta));
+ final result = parchmentMarkdown.encode(
+ ParchmentDocument.fromDelta(delta),
+ );
expect(result, markdown);
});
});
diff --git a/packages/parchment/test/document/attributes_test.dart b/packages/parchment/test/document/attributes_test.dart
index b5d1df1b..5aa99445 100644
--- a/packages/parchment/test/document/attributes_test.dart
+++ b/packages/parchment/test/document/attributes_test.dart
@@ -18,30 +18,34 @@ void main() {
group('$ParchmentAttribute', () {
test('create background attribute with color', () {
- final attribute =
- ParchmentAttribute.backgroundColor.withColor(0xFFFF0000);
+ final attribute = ParchmentAttribute.backgroundColor.withColor(
+ 0xFFFF0000,
+ );
expect(attribute.key, ParchmentAttribute.backgroundColor.key);
expect(attribute.scope, ParchmentAttribute.backgroundColor.scope);
expect(attribute.value, 0xFFFF0000);
});
test('create background attribute with transparent color', () {
- final attribute =
- ParchmentAttribute.backgroundColor.withColor(0x00000000);
+ final attribute = ParchmentAttribute.backgroundColor.withColor(
+ 0x00000000,
+ );
expect(attribute, ParchmentAttribute.backgroundColor.unset);
});
test('create foreground attribute with color', () {
- final attribute =
- ParchmentAttribute.foregroundColor.withColor(0x00FF0000);
+ final attribute = ParchmentAttribute.foregroundColor.withColor(
+ 0x00FF0000,
+ );
expect(attribute.key, ParchmentAttribute.foregroundColor.key);
expect(attribute.scope, ParchmentAttribute.foregroundColor.scope);
expect(attribute.value, 0x00FF0000);
});
test('create foreground attribute with black color', () {
- final attribute =
- ParchmentAttribute.foregroundColor.withColor(0x00000000);
+ final attribute = ParchmentAttribute.foregroundColor.withColor(
+ 0x00000000,
+ );
expect(attribute, ParchmentAttribute.foregroundColor.unset);
});
});
diff --git a/packages/parchment/test/document/block_test.dart b/packages/parchment/test/document/block_test.dart
index 2428d238..e1e7a624 100644
--- a/packages/parchment/test/document/block_test.dart
+++ b/packages/parchment/test/document/block_test.dart
@@ -84,8 +84,10 @@ void main() {
expect(block.childCount, 1);
expect(block.first, const TypeMatcher());
final line = block.first as LineNode;
- expect(line.style.get(ParchmentAttribute.alignment),
- ParchmentAttribute.right);
+ expect(
+ line.style.get(ParchmentAttribute.alignment),
+ ParchmentAttribute.right,
+ );
});
test('format two sibling lines as list', () {
@@ -103,7 +105,10 @@ void main() {
test('format to split first line from block', () {
root.insert(
- 0, 'London Grammar Songs\nHey now\nStrong\nIf You Wait', null);
+ 0,
+ 'London Grammar Songs\nHey now\nStrong\nIf You Wait',
+ null,
+ );
root.retain(20, 1, h1Attrs);
root.retain(28, 1, ulAttrs);
root.retain(35, 1, ulAttrs);
@@ -125,7 +130,10 @@ void main() {
test('format to split last line from block', () {
root.insert(
- 0, 'London Grammar Songs\nHey now\nStrong\nIf You Wait', null);
+ 0,
+ 'London Grammar Songs\nHey now\nStrong\nIf You Wait',
+ null,
+ );
root.retain(20, 1, h1Attrs);
root.retain(28, 1, ulAttrs);
root.retain(35, 1, ulAttrs);
@@ -147,7 +155,10 @@ void main() {
test('format to split middle line from block', () {
root.insert(
- 0, 'London Grammar Songs\nHey now\nStrong\nIf You Wait', null);
+ 0,
+ 'London Grammar Songs\nHey now\nStrong\nIf You Wait',
+ null,
+ );
root.retain(20, 1, h1Attrs);
root.retain(28, 1, ulAttrs);
root.retain(35, 1, ulAttrs);
@@ -169,7 +180,10 @@ void main() {
test('insert line-break at the beginning of the document', () {
root.insert(
- 0, 'London Grammar Songs\nHey now\nStrong\nIf You Wait', null);
+ 0,
+ 'London Grammar Songs\nHey now\nStrong\nIf You Wait',
+ null,
+ );
root.retain(20, 1, ulAttrs);
root.retain(28, 1, ulAttrs);
root.retain(35, 1, ulAttrs);
diff --git a/packages/parchment/test/document/leaf_test.dart b/packages/parchment/test/document/leaf_test.dart
index 78406c96..37a59611 100644
--- a/packages/parchment/test/document/leaf_test.dart
+++ b/packages/parchment/test/document/leaf_test.dart
@@ -101,18 +101,9 @@ void main() {
expect(line.childCount, 4);
expect(line.children.last.offset, 9);
final b = boldStyle.toJson();
- expect(
- line.children.elementAt(0).toDelta(),
- Delta()..insert('Lon', b),
- );
- expect(
- line.children.elementAt(1).toDelta(),
- Delta()..insert('don'),
- );
- expect(
- line.children.elementAt(2).toDelta(),
- Delta()..insert('don', b),
- );
+ expect(line.children.elementAt(0).toDelta(), Delta()..insert('Lon', b));
+ expect(line.children.elementAt(1).toDelta(), Delta()..insert('don'));
+ expect(line.children.elementAt(2).toDelta(), Delta()..insert('don', b));
});
});
@@ -164,8 +155,10 @@ void main() {
});
test('toDelta', () {
- expect(node.toDelta(),
- Delta()..insert(EmbeddableObject('hr', inline: false).toJson()));
+ expect(
+ node.toDelta(),
+ Delta()..insert(EmbeddableObject('hr', inline: false).toJson()),
+ );
});
test('splitAt', () {
@@ -197,8 +190,10 @@ void main() {
final text = LeafNode('Text');
final style = ParchmentStyle().put(ParchmentAttribute.block.numberList);
- expect(() => text.applyStyle(style),
- throwsA(const TypeMatcher()));
+ expect(
+ () => text.applyStyle(style),
+ throwsA(const TypeMatcher()),
+ );
});
});
}
diff --git a/packages/parchment/test/document/line_test.dart b/packages/parchment/test/document/line_test.dart
index c098e1ba..4bc4474f 100644
--- a/packages/parchment/test/document/line_test.dart
+++ b/packages/parchment/test/document/line_test.dart
@@ -41,7 +41,10 @@ void main() {
test('nextLine', () {
root.insert(
- 0, 'Hello world\nThis is my first multiline\nItem\ndocument.', null);
+ 0,
+ 'Hello world\nThis is my first multiline\nItem\ndocument.',
+ null,
+ );
root.retain(38, 1, ulStyle);
root.retain(43, 1, bqStyle);
final line = root.first as LineNode;
@@ -240,7 +243,10 @@ void main() {
test('delete empty line', () {
root.insert(
- 0, 'Hello world\nThis is my first multiline\n\ndocument.', null);
+ 0,
+ 'Hello world\nThis is my first multiline\n\ndocument.',
+ null,
+ );
expect(root.childCount, 4);
root.delete(39, 1);
expect(root.childCount, 3);
@@ -248,7 +254,10 @@ void main() {
test('delete line-break of non-empty line', () {
root.insert(
- 0, 'Hello world\nThis is my first multiline\n\ndocument.', null);
+ 0,
+ 'Hello world\nThis is my first multiline\n\ndocument.',
+ null,
+ );
root.retain(39, 1, h2Style);
expect(root.childCount, 4);
root.delete(38, 1);
@@ -259,7 +268,10 @@ void main() {
test('insert at the beginning of a line', () {
root.insert(
- 0, 'Hello world\nThis is my first multiline\ndocument.', null);
+ 0,
+ 'Hello world\nThis is my first multiline\ndocument.',
+ null,
+ );
root.insert(12, 'Boom! ', null);
expect(root.childCount, 3);
expect(root.children.elementAt(1), hasLength(33));
@@ -267,7 +279,10 @@ void main() {
test('delete last character of a line', () {
root.insert(
- 0, 'Hello world\nThis is my first multiline\ndocument.', null);
+ 0,
+ 'Hello world\nThis is my first multiline\ndocument.',
+ null,
+ );
root.delete(37, 1);
expect(root.childCount, 3);
final line = root.children.elementAt(1) as LineNode;
@@ -277,7 +292,10 @@ void main() {
test('collectStyle', () {
// TODO: need more test cases for collectStyle
root.insert(
- 0, 'Hello world\nThis is my first multiline\n\ndocument.', null);
+ 0,
+ 'Hello world\nThis is my first multiline\n\ndocument.',
+ null,
+ );
root.retain(38, 1, h2Style);
root.retain(23, 5, boldStyle);
var result = root.lookup(20);
diff --git a/packages/parchment/test/document_test.dart b/packages/parchment/test/document_test.dart
index c2adfa60..20f9b31d 100644
--- a/packages/parchment/test/document_test.dart
+++ b/packages/parchment/test/document_test.dart
@@ -58,22 +58,26 @@ void main() {
test('load non-empty document', () {
final doc = dartconfEmbedDoc();
- expect(doc.toPlainText(),
- 'DartConf\n${EmbedNode.kObjectReplacementCharacter}\nLos Angeles\n');
+ expect(
+ doc.toPlainText(),
+ 'DartConf\n${EmbedNode.kObjectReplacementCharacter}\nLos Angeles\n',
+ );
});
test('load document with 0.x version embeds', () {
final delta = Delta()
..insert('DartConf\n')
..insert('\u200B', {
- 'embed': {'type': 'hr'}
+ 'embed': {'type': 'hr'},
})
..insert('\n')
..insert('Los Angeles\n');
final doc = ParchmentDocument.fromJson(jsonDecode(jsonEncode(delta)));
- expect(doc.toPlainText(),
- 'DartConf\n${EmbedNode.kObjectReplacementCharacter}\nLos Angeles\n');
+ expect(
+ doc.toPlainText(),
+ 'DartConf\n${EmbedNode.kObjectReplacementCharacter}\nLos Angeles\n',
+ );
final line = doc.root.children.toList()[1] as LineNode;
final node = line.children.single as LeafNode;
expect(node, isA());
@@ -239,8 +243,10 @@ void main() {
// an embed.
final doc = dartconfEmbedDoc();
doc.delete(8, 1);
- expect(doc.toPlainText(),
- 'DartConf\n${EmbedNode.kObjectReplacementCharacter}\nLos Angeles\n');
+ expect(
+ doc.toPlainText(),
+ 'DartConf\n${EmbedNode.kObjectReplacementCharacter}\nLos Angeles\n',
+ );
});
test('delete preserves last newline character', () {
@@ -253,8 +259,10 @@ void main() {
var delta = Delta()
..insert('Line 1\nLine 2\n')
..insert('\n', {'block': 'ul'});
- final document = ParchmentDocument.fromDelta(delta,
- heuristics: ParchmentHeuristics.fallback);
+ final document = ParchmentDocument.fromDelta(
+ delta,
+ heuristics: ParchmentHeuristics.fallback,
+ );
var blockLine =
(document.root.children.first.next!.next! as BlockNode).first;
// Set _offsetCache of LineNode in BlockNode to 0
@@ -325,8 +333,10 @@ void main() {
doc.insert(4, BlockEmbed.horizontalRule);
expect(doc.root.children, hasLength(4));
expect(doc.root.children.elementAt(0).toPlainText(), 'Dart\n');
- expect(doc.root.children.elementAt(1).toPlainText(),
- '${EmbedNode.kObjectReplacementCharacter}\n');
+ expect(
+ doc.root.children.elementAt(1).toPlainText(),
+ '${EmbedNode.kObjectReplacementCharacter}\n',
+ );
expect(doc.root.children.elementAt(2).toPlainText(), 'Conf\n');
expect(doc.root.children.elementAt(3).toPlainText(), 'Los Angeles\n');
final line = doc.root.children.elementAt(1) as LineNode;
@@ -358,8 +368,10 @@ void main() {
doc.insert(9, 'text');
expect(doc.root.children, hasLength(4));
expect(doc.root.children.elementAt(1).toPlainText(), 'text\n');
- expect(doc.root.children.elementAt(2).toPlainText(),
- '${EmbedNode.kObjectReplacementCharacter}\n');
+ expect(
+ doc.root.children.elementAt(2).toPlainText(),
+ '${EmbedNode.kObjectReplacementCharacter}\n',
+ );
});
test('insert text after embed', () {
@@ -368,8 +380,10 @@ void main() {
expect(doc.root.children, hasLength(3));
doc.insert(10, 'text');
expect(doc.root.children, hasLength(4));
- expect(doc.root.children.elementAt(1).toPlainText(),
- '${EmbedNode.kObjectReplacementCharacter}\n');
+ expect(
+ doc.root.children.elementAt(1).toPlainText(),
+ '${EmbedNode.kObjectReplacementCharacter}\n',
+ );
expect(doc.root.children.elementAt(2).toPlainText(), 'text\n');
});
@@ -378,8 +392,10 @@ void main() {
doc.replace(4, 4, BlockEmbed.horizontalRule);
expect(doc.root.children, hasLength(3));
expect(doc.root.children.elementAt(0).toPlainText(), 'Dart\n');
- expect(doc.root.children.elementAt(1).toPlainText(),
- '${EmbedNode.kObjectReplacementCharacter}\n');
+ expect(
+ doc.root.children.elementAt(1).toPlainText(),
+ '${EmbedNode.kObjectReplacementCharacter}\n',
+ );
expect(doc.root.children.elementAt(2).toPlainText(), 'Los Angeles\n');
});
@@ -405,8 +421,10 @@ void main() {
expect(doc.root.children, hasLength(4));
expect(doc.root.children.elementAt(0).toPlainText(), 'Dart\n');
expect(doc.root.children.elementAt(1).toPlainText(), '\n');
- expect(doc.root.children.elementAt(2).toPlainText(),
- '${EmbedNode.kObjectReplacementCharacter}\n');
+ expect(
+ doc.root.children.elementAt(2).toPlainText(),
+ '${EmbedNode.kObjectReplacementCharacter}\n',
+ );
expect(doc.root.children.elementAt(3).toPlainText(), 'Los Angeles\n');
});
});
diff --git a/packages/parchment/test/heuristics/format_rules_test.dart b/packages/parchment/test/heuristics/format_rules_test.dart
index 6fe3a4a9..53a7e96f 100644
--- a/packages/parchment/test/heuristics/format_rules_test.dart
+++ b/packages/parchment/test/heuristics/format_rules_test.dart
@@ -97,10 +97,12 @@ void main() {
final rule = FormatLinkAtCaretPositionRule();
test('apply', () {
- final link = ParchmentAttribute.link
- .fromString('https://github.com/fleather-editor/bold');
- final newLink = ParchmentAttribute.link
- .fromString('https://github.com/fleather-editor/fleather');
+ final link = ParchmentAttribute.link.fromString(
+ 'https://github.com/fleather-editor/bold',
+ );
+ final newLink = ParchmentAttribute.link.fromString(
+ 'https://github.com/fleather-editor/fleather',
+ );
final doc = Delta()
..insert('Visit our ')
..insert('website', link.toJson())
diff --git a/packages/parchment/test/heuristics/insert_rules_test.dart b/packages/parchment/test/heuristics/insert_rules_test.dart
index 100d0a4c..c1ed995d 100644
--- a/packages/parchment/test/heuristics/insert_rules_test.dart
+++ b/packages/parchment/test/heuristics/insert_rules_test.dart
@@ -123,21 +123,23 @@ void main() {
group('$AutoExitBlockRule', () {
final rule = AutoExitBlockRule();
- test('applies when newline is inserted on the last empty line in a block',
- () {
- final ul = ParchmentAttribute.ul.toJson();
- final doc = Delta()
- ..insert('Item 1')
- ..insert('\n', ul)
- ..insert('Item 2')
- ..insert('\n\n', ul);
- final actual = rule.apply(doc, 14, '\n');
- expect(actual, isNotNull);
- final expected = Delta()
- ..retain(14)
- ..retain(1, ParchmentAttribute.block.unset.toJson());
- expect(actual, expected);
- });
+ test(
+ 'applies when newline is inserted on the last empty line in a block',
+ () {
+ final ul = ParchmentAttribute.ul.toJson();
+ final doc = Delta()
+ ..insert('Item 1')
+ ..insert('\n', ul)
+ ..insert('Item 2')
+ ..insert('\n\n', ul);
+ final actual = rule.apply(doc, 14, '\n');
+ expect(actual, isNotNull);
+ final expected = Delta()
+ ..retain(14)
+ ..retain(1, ParchmentAttribute.block.unset.toJson());
+ expect(actual, expected);
+ },
+ );
test('applies only on empty line', () {
final ul = ParchmentAttribute.ul.toJson();
@@ -208,8 +210,9 @@ void main() {
test('apply preserve link formatting within link', () {
final doc = Delta()
..insert('Doc with link')
- ..insert('http://fleather-editor.github.io',
- {'a': 'http://fleather-editor.github.io'})
+ ..insert('http://fleather-editor.github.io', {
+ 'a': 'http://fleather-editor.github.io',
+ })
..insert(' link');
final actual = rule.apply(doc, 17, 's');
final expected = Delta()
@@ -221,8 +224,9 @@ void main() {
test('apply remove link formatting on link boundaries', () {
final doc = Delta()
..insert('Doc with link')
- ..insert('http://fleather-editor.github.io',
- {'a': 'http://fleather-editor.github.io'})
+ ..insert('http://fleather-editor.github.io', {
+ 'a': 'http://fleather-editor.github.io',
+ })
..insert(' link');
final actual = rule.apply(doc, 13, 'like this ');
final expected = Delta()