diff --git a/attributed_text/lib/src/attributed_spans.dart b/attributed_text/lib/src/attributed_spans.dart index 3a711d840..650ccf5b3 100644 --- a/attributed_text/lib/src/attributed_spans.dart +++ b/attributed_text/lib/src/attributed_spans.dart @@ -897,7 +897,7 @@ class AttributedSpans { } } - if (collapsedSpans.last.end < contentLength) { + if (collapsedSpans.isEmpty || collapsedSpans.last.end < contentLength) { // The last span committed during the loop does not reach the end of the requested content range. We either ran // out of markers or the remaining markers are outside the content range. In both cases the value in currentSpan // should already have the correct start, end, and attributions values to cover the remaining content. diff --git a/attributed_text/test/attributed_spans_test.dart b/attributed_text/test/attributed_spans_test.dart index f7baf73a1..90bd8bfb1 100644 --- a/attributed_text/test/attributed_spans_test.dart +++ b/attributed_text/test/attributed_spans_test.dart @@ -486,19 +486,46 @@ void main() { expect(collapsedSpans.first.attributions, isEmpty); }); - test('single continuous attribution', () { - final collapsedSpans = AttributedSpans( + group('single continuous attribution', () { + final spans = AttributedSpans( attributions: [ const SpanMarker(attribution: ExpectedSpans.bold, offset: 0, markerType: SpanMarkerType.start), const SpanMarker(attribution: ExpectedSpans.bold, offset: 16, markerType: SpanMarkerType.end), ], - ).collapseSpans(contentLength: 16); + ); - expect(collapsedSpans.length, 1); - expect(collapsedSpans.first.start, 0); - expect(collapsedSpans.first.end, 16); - expect(collapsedSpans.first.attributions.length, 1); - expect(collapsedSpans.first.attributions.first, ExpectedSpans.bold); + test('collapse at span end', () { + final collapsedSpans = spans.collapseSpans(contentLength: 16); + + expect(collapsedSpans.length, 1); + expect(collapsedSpans.first.start, 0); + expect(collapsedSpans.first.end, 16); + expect(collapsedSpans.first.attributions.length, 1); + expect(collapsedSpans.first.attributions.first, ExpectedSpans.bold); + }); + + test('collapse before span end', () { + final collapsedSpans = spans.collapseSpans(contentLength: 10); + + expect(collapsedSpans.length, 1); + expect(collapsedSpans.first.start, 0); + expect(collapsedSpans.first.end, 10); + expect(collapsedSpans.first.attributions.length, 1); + expect(collapsedSpans.first.attributions.first, ExpectedSpans.bold); + }); + + test('collapse after span end', () { + final collapsedSpans = spans.collapseSpans(contentLength: 20); + + expect(collapsedSpans.length, 2); + expect(collapsedSpans[0].start, 0); + expect(collapsedSpans[0].end, 16); + expect(collapsedSpans[0].attributions.length, 1); + expect(collapsedSpans[0].attributions.first, ExpectedSpans.bold); + expect(collapsedSpans[1].start, 16); + expect(collapsedSpans[1].end, 20); + expect(collapsedSpans[1].attributions, isEmpty); + }); }); test('single fractured attribution', () {