Skip to content

Commit 309f5e5

Browse files
[Attributed Text] - Fix: A few methods still (erroneously) using plain text length without accounting for placeholders (Resolves #2515) (#2516)
1 parent 1b4c7a2 commit 309f5e5

File tree

3 files changed

+127
-7
lines changed

3 files changed

+127
-7
lines changed

attributed_text/lib/src/attributed_text.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,14 +270,14 @@ class AttributedText {
270270
/// Returns all spans in this [AttributedText] for the given [attributions].
271271
Set<AttributionSpan> getAttributionSpans(Set<Attribution> attributions) => getAttributionSpansInRange(
272272
attributionFilter: (a) => attributions.contains(a),
273-
range: SpanRange(0, _text.length),
273+
range: SpanRange(0, length),
274274
);
275275

276276
/// Returns all spans in this [AttributedText], for attributions that are
277277
/// selected by the given [filter].
278278
Set<AttributionSpan> getAttributionSpansByFilter(AttributionFilter filter) => getAttributionSpansInRange(
279279
attributionFilter: filter,
280-
range: SpanRange(0, _text.length),
280+
range: SpanRange(0, length),
281281
);
282282

283283
/// Returns spans for each attribution that (at least partially) appear
@@ -502,7 +502,7 @@ class AttributedText {
502502

503503
return AttributedText(
504504
_text + other._text,
505-
spans.copy()..addAt(other: other.spans, index: _text.length),
505+
spans.copy()..addAt(other: other.spans, index: length),
506506
{
507507
...placeholders,
508508
...other.placeholders.map((offset, placeholder) => MapEntry(offset + length, placeholder)),
@@ -707,7 +707,7 @@ class AttributedText {
707707
///
708708
/// Attribution groups are useful when computing all style variations for [AttributedText].
709709
Iterable<MultiAttributionSpan> computeAttributionSpans() {
710-
return spans.collapseSpans(contentLength: _text.length);
710+
return spans.collapseSpans(contentLength: length);
711711
}
712712

713713
/// Returns a copy of this [AttributedText].

attributed_text/test/attributed_text_placeholders_test.dart

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,34 @@ void main() {
247247
});
248248
});
249249

250+
group("attribution queries >", () {
251+
test('finds spans that exceed plain text length', () {
252+
final attributedText = AttributedText(
253+
'Hello world',
254+
AttributedSpans(
255+
attributions: [
256+
const SpanMarker(attribution: ExpectedSpans.bold, offset: 0, markerType: SpanMarkerType.start),
257+
const SpanMarker(attribution: ExpectedSpans.bold, offset: 12, markerType: SpanMarkerType.end),
258+
],
259+
),
260+
{
261+
11: const _FakePlaceholder("trailing1"),
262+
12: const _FakePlaceholder("trailing2"),
263+
},
264+
);
265+
266+
final ranges = attributedText.getAttributionSpans({ExpectedSpans.bold});
267+
268+
expect(ranges.length, 1);
269+
expect(
270+
ranges,
271+
[
272+
const AttributionSpan(attribution: ExpectedSpans.bold, start: 0, end: 12),
273+
],
274+
);
275+
});
276+
});
277+
250278
group("full copy >", () {
251279
test("only a single placeholder", () {
252280
expect(
@@ -463,6 +491,66 @@ void main() {
463491
}),
464492
);
465493
});
494+
495+
test("at end of text (with attributions) with leading placeholder", () {
496+
// Note: We include attributions in this test because in a client app the presence
497+
// of attributions unearthed a bug where we were still using the plain text
498+
// length, when we should have been using the text + placeholders length.
499+
expect(
500+
AttributedText(
501+
"Hello",
502+
AttributedSpans(attributions: const [
503+
SpanMarker(attribution: ExpectedSpans.bold, offset: 1, markerType: SpanMarkerType.start),
504+
SpanMarker(attribution: ExpectedSpans.bold, offset: 5, markerType: SpanMarkerType.end),
505+
]),
506+
{
507+
0: const _FakePlaceholder("leading"),
508+
},
509+
).copyAndAppend(
510+
AttributedText(", world!"),
511+
),
512+
AttributedText(
513+
"Hello, world!",
514+
AttributedSpans(attributions: const [
515+
SpanMarker(attribution: ExpectedSpans.bold, offset: 1, markerType: SpanMarkerType.start),
516+
SpanMarker(attribution: ExpectedSpans.bold, offset: 5, markerType: SpanMarkerType.end),
517+
]),
518+
{
519+
0: const _FakePlaceholder("leading"),
520+
},
521+
),
522+
);
523+
});
524+
525+
test("at end of text (with attributions) with trailing placeholder", () {
526+
// Note: We include attributions in this test because in a client app the presence
527+
// of attributions unearthed a bug where we were still using the plain text
528+
// length, when we should have been using the text + placeholders length.
529+
expect(
530+
AttributedText(
531+
"Hello",
532+
AttributedSpans(attributions: const [
533+
SpanMarker(attribution: ExpectedSpans.bold, offset: 0, markerType: SpanMarkerType.start),
534+
SpanMarker(attribution: ExpectedSpans.bold, offset: 4, markerType: SpanMarkerType.end),
535+
]),
536+
{
537+
5: const _FakePlaceholder("trailing"),
538+
},
539+
).copyAndAppend(
540+
AttributedText(", world!"),
541+
),
542+
AttributedText(
543+
"Hello, world!",
544+
AttributedSpans(attributions: const [
545+
SpanMarker(attribution: ExpectedSpans.bold, offset: 0, markerType: SpanMarkerType.start),
546+
SpanMarker(attribution: ExpectedSpans.bold, offset: 4, markerType: SpanMarkerType.end),
547+
]),
548+
{
549+
5: const _FakePlaceholder("trailing"),
550+
},
551+
),
552+
);
553+
});
466554
});
467555

468556
test("insert attributed text >", () {
@@ -576,6 +664,38 @@ void main() {
576664
),
577665
);
578666
});
667+
668+
group("collapses spans >", () {
669+
test("when placeholders sit beyond plain text", () {
670+
final attributedText = AttributedText(
671+
'Hello world',
672+
AttributedSpans(
673+
attributions: [
674+
const SpanMarker(attribution: ExpectedSpans.bold, offset: 0, markerType: SpanMarkerType.start),
675+
const SpanMarker(attribution: ExpectedSpans.bold, offset: 11, markerType: SpanMarkerType.end),
676+
const SpanMarker(attribution: ExpectedSpans.underline, offset: 12, markerType: SpanMarkerType.start),
677+
const SpanMarker(attribution: ExpectedSpans.underline, offset: 12, markerType: SpanMarkerType.end),
678+
],
679+
),
680+
{
681+
11: const _FakePlaceholder("trailing1"),
682+
12: const _FakePlaceholder("trailing2"),
683+
},
684+
);
685+
686+
final spans = attributedText.computeAttributionSpans().toList();
687+
688+
expect(spans.length, 2);
689+
690+
expect(spans[0].attributions, {ExpectedSpans.bold});
691+
expect(spans[0].start, 0);
692+
expect(spans[0].end, 11);
693+
694+
expect(spans[1].attributions, {ExpectedSpans.underline});
695+
expect(spans[1].start, 12);
696+
expect(spans[1].end, 12);
697+
});
698+
});
579699
});
580700
}
581701

attributed_text/test/attributed_text_test.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ void main() {
2121
applyAttributions: {ExpectedSpans.bold},
2222
);
2323

24-
expect(newText.text, 'aabcdefghij');
24+
expect(newText.toPlainText(), 'aabcdefghij');
2525
expect(
2626
newText.hasAttributionsWithin(attributions: {ExpectedSpans.bold}, range: const SpanRange(0, 10)),
2727
true,
@@ -43,7 +43,7 @@ void main() {
4343
);
4444

4545
final slice = text.copyTextInRange(const SpanRange(5, 9));
46-
expect(slice.text, "that");
46+
expect(slice.toPlainText(), "that");
4747
expect(slice.length, 4);
4848
expect(slice.getAttributedRange({ExpectedSpans.bold}, 0), const SpanRange(0, 1));
4949
expect(slice.getAttributedRange({ExpectedSpans.italics}, 2), const SpanRange(2, 3));
@@ -63,7 +63,7 @@ void main() {
6363
);
6464

6565
final slice = text.copyText(5, 9);
66-
expect(slice.text, "that");
66+
expect(slice.toPlainText(), "that");
6767
expect(slice.length, 4);
6868
expect(slice.getAttributedRange({ExpectedSpans.bold}, 0), const SpanRange(0, 1));
6969
expect(slice.getAttributedRange({ExpectedSpans.italics}, 2), const SpanRange(2, 3));

0 commit comments

Comments
 (0)