@@ -44,20 +44,42 @@ export function truncateText(
44
44
ellipsis ?: string ,
45
45
options ?: InnerTruncateOption
46
46
) : string {
47
+ const out = { } as Parameters < typeof truncateText2 > [ 0 ] ;
48
+ truncateText2 ( out , text , containerWidth , font , ellipsis , options ) ;
49
+ return out . text ;
50
+ }
51
+
52
+ // PENDING: not sure whether `truncateText` is used outside zrender, since it has an `export`
53
+ // specifier. So keep it and perform the interface modification in `truncateText2`.
54
+ function truncateText2 (
55
+ out : { text : string , isTruncated : boolean } ,
56
+ text : string ,
57
+ containerWidth : number ,
58
+ font : string ,
59
+ ellipsis ?: string ,
60
+ options ?: InnerTruncateOption
61
+ ) : void {
47
62
if ( ! containerWidth ) {
48
- return '' ;
63
+ out . text = '' ;
64
+ out . isTruncated = false ;
65
+ return ;
49
66
}
50
67
51
68
const textLines = ( text + '' ) . split ( '\n' ) ;
52
69
options = prepareTruncateOptions ( containerWidth , font , ellipsis , options ) ;
53
70
54
71
// FIXME
55
72
// It is not appropriate that every line has '...' when truncate multiple lines.
73
+ let isTruncated = false ;
74
+ const truncateOut = { } as Parameters < typeof truncateSingleLine > [ 0 ] ;
56
75
for ( let i = 0 , len = textLines . length ; i < len ; i ++ ) {
57
- textLines [ i ] = truncateSingleLine ( textLines [ i ] , options as InnerPreparedTruncateOption ) ;
76
+ truncateSingleLine ( truncateOut , textLines [ i ] , options as InnerPreparedTruncateOption ) ;
77
+ textLines [ i ] = truncateOut . textLine ;
78
+ isTruncated = isTruncated || truncateOut . isTruncated ;
58
79
}
59
80
60
- return textLines . join ( '\n' ) ;
81
+ out . text = textLines . join ( '\n' ) ;
82
+ out . isTruncated = isTruncated ;
61
83
}
62
84
63
85
function prepareTruncateOptions (
@@ -104,19 +126,27 @@ function prepareTruncateOptions(
104
126
return preparedOpts ;
105
127
}
106
128
107
- function truncateSingleLine ( textLine : string , options : InnerPreparedTruncateOption ) : string {
129
+ function truncateSingleLine (
130
+ out : { textLine : string , isTruncated : boolean } ,
131
+ textLine : string ,
132
+ options : InnerPreparedTruncateOption
133
+ ) : void {
108
134
const containerWidth = options . containerWidth ;
109
135
const font = options . font ;
110
136
const contentWidth = options . contentWidth ;
111
137
112
138
if ( ! containerWidth ) {
113
- return '' ;
139
+ out . textLine = '' ;
140
+ out . isTruncated = false ;
141
+ return ;
114
142
}
115
143
116
144
let lineWidth = getWidth ( textLine , font ) ;
117
145
118
146
if ( lineWidth <= containerWidth ) {
119
- return textLine ;
147
+ out . textLine = textLine ;
148
+ out . isTruncated = false ;
149
+ return ;
120
150
}
121
151
122
152
for ( let j = 0 ; ; j ++ ) {
@@ -139,7 +169,8 @@ function truncateSingleLine(textLine: string, options: InnerPreparedTruncateOpti
139
169
textLine = options . placeholder ;
140
170
}
141
171
142
- return textLine ;
172
+ out . textLine = textLine ;
173
+ out . isTruncated = true ;
143
174
}
144
175
145
176
function estimateLength (
@@ -174,6 +205,10 @@ export interface PlainTextContentBlock {
174
205
outerHeight : number
175
206
176
207
lines : string [ ]
208
+
209
+ // Be `true` if and only if the result text is modified due to overflow, due to
210
+ // settings on either `overflow` or `lineOverflow`
211
+ isTruncated : boolean
177
212
}
178
213
179
214
export function parsePlainText (
@@ -192,6 +227,7 @@ export function parsePlainText(
192
227
const bgColorDrawn = ! ! ( style . backgroundColor ) ;
193
228
194
229
const truncateLineOverflow = style . lineOverflow === 'truncate' ;
230
+ let isTruncated = false ;
195
231
196
232
let width = style . width ;
197
233
let lines : string [ ] ;
@@ -210,6 +246,7 @@ export function parsePlainText(
210
246
if ( contentHeight > height && truncateLineOverflow ) {
211
247
const lineCount = Math . floor ( height / lineHeight ) ;
212
248
249
+ isTruncated = isTruncated || ( lines . length > lineCount ) ;
213
250
lines = lines . slice ( 0 , lineCount ) ;
214
251
215
252
// TODO If show ellipse for line truncate
@@ -228,8 +265,11 @@ export function parsePlainText(
228
265
placeholder : style . placeholder
229
266
} ) ;
230
267
// Having every line has '...' when truncate multiple lines.
268
+ const singleOut = { } as Parameters < typeof truncateSingleLine > [ 0 ] ;
231
269
for ( let i = 0 ; i < lines . length ; i ++ ) {
232
- lines [ i ] = truncateSingleLine ( lines [ i ] , options ) ;
270
+ truncateSingleLine ( singleOut , lines [ i ] , options ) ;
271
+ lines [ i ] = singleOut . textLine ;
272
+ isTruncated = isTruncated || singleOut . isTruncated ;
233
273
}
234
274
}
235
275
@@ -265,7 +305,8 @@ export function parsePlainText(
265
305
calculatedLineHeight : calculatedLineHeight ,
266
306
contentWidth : contentWidth ,
267
307
contentHeight : contentHeight ,
268
- width : width
308
+ width : width ,
309
+ isTruncated : isTruncated
269
310
} ;
270
311
}
271
312
@@ -314,6 +355,9 @@ export class RichTextContentBlock {
314
355
outerWidth : number = 0
315
356
outerHeight : number = 0
316
357
lines : RichTextLine [ ] = [ ]
358
+ // Be `true` if and only if the result text is modified due to overflow, due to
359
+ // settings on either `overflow` or `lineOverflow`
360
+ isTruncated : boolean = false
317
361
}
318
362
319
363
type WrapInfo = {
@@ -326,7 +370,7 @@ type WrapInfo = {
326
370
* Also consider 'bbbb{a|xxx\nzzz}xxxx\naaaa'.
327
371
* If styleName is undefined, it is plain text.
328
372
*/
329
- export function parseRichText ( text : string , style : TextStyleProps ) {
373
+ export function parseRichText ( text : string , style : TextStyleProps ) : RichTextContentBlock {
330
374
const contentBlock = new RichTextContentBlock ( ) ;
331
375
332
376
text != null && ( text += '' ) ;
@@ -366,6 +410,7 @@ export function parseRichText(text: string, style: TextStyleProps) {
366
410
367
411
const truncate = overflow === 'truncate' ;
368
412
const truncateLine = style . lineOverflow === 'truncate' ;
413
+ const tmpTruncateOut = { } as Parameters < typeof truncateText2 > [ 0 ] ;
369
414
370
415
// let prevToken: RichTextToken;
371
416
@@ -412,6 +457,7 @@ export function parseRichText(text: string, style: TextStyleProps) {
412
457
if ( truncateLine && topHeight != null && calculatedHeight + token . lineHeight > topHeight ) {
413
458
// TODO Add ellipsis on the previous token.
414
459
// prevToken.text =
460
+ const originalLength = contentBlock . lines . length ;
415
461
if ( j > 0 ) {
416
462
line . tokens = line . tokens . slice ( 0 , j ) ;
417
463
finishLine ( line , lineWidth , lineHeight ) ;
@@ -420,6 +466,7 @@ export function parseRichText(text: string, style: TextStyleProps) {
420
466
else {
421
467
contentBlock . lines = contentBlock . lines . slice ( 0 , i ) ;
422
468
}
469
+ contentBlock . isTruncated = contentBlock . isTruncated || ( contentBlock . lines . length < originalLength ) ;
423
470
break outer;
424
471
}
425
472
@@ -461,10 +508,13 @@ export function parseRichText(text: string, style: TextStyleProps) {
461
508
token . width = token . contentWidth = 0 ;
462
509
}
463
510
else {
464
- token . text = truncateText (
511
+ truncateText2 (
512
+ tmpTruncateOut ,
465
513
token . text , remainTruncWidth - paddingH , font , style . ellipsis ,
466
514
{ minChar : style . truncateMinChar }
467
515
) ;
516
+ token . text = tmpTruncateOut . text ;
517
+ contentBlock . isTruncated = contentBlock . isTruncated || tmpTruncateOut . isTruncated ;
468
518
token . width = token . contentWidth = getWidth ( token . text , font ) ;
469
519
}
470
520
}
0 commit comments