Skip to content

Commit 3f598c2

Browse files
authoredAug 11, 2023
fix: text-align (#527)
### Description Closes: #525
1 parent efbb5ec commit 3f598c2

8 files changed

+158
-4
lines changed
 

‎src/text.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,12 @@ export default async function* buildTextNodes(
228228
// @TODO: Support different writing modes.
229229
// @TODO: Support RTL languages.
230230
let i = 0
231+
let prevLineEndingSpacesWidth = 0
231232
while (i < words.length && lines < lineLimit) {
232233
let word = words[i]
233234
const forceBreak = requiredBreaks[i]
234235

235236
let w = 0
236-
let lineEndingSpacesWidth = 0
237237

238238
const {
239239
originWidth,
@@ -243,7 +243,7 @@ export default async function* buildTextNodes(
243243
word = _word
244244

245245
w = originWidth
246-
lineEndingSpacesWidth = endingSpacesWidth
246+
const lineEndingSpacesWidth = endingSpacesWidth
247247

248248
// When starting a new line from an empty line, we should push one extra
249249
// line height.
@@ -281,7 +281,7 @@ export default async function* buildTextNodes(
281281
words.splice(i, 1, ...chars)
282282
if (currentWidth > 0) {
283283
// Start a new line, spaces can be ignored.
284-
lineWidths.push(currentWidth)
284+
lineWidths.push(currentWidth - prevLineEndingSpacesWidth)
285285
baselines.push(currentBaselineOffset)
286286
lines++
287287
height += currentLineHeight
@@ -291,6 +291,7 @@ export default async function* buildTextNodes(
291291
lineSegmentNumber.push(1)
292292
lineIndex = -1
293293
}
294+
prevLineEndingSpacesWidth = lineEndingSpacesWidth
294295
continue
295296
}
296297
if (forceBreak || willWrap) {
@@ -299,7 +300,8 @@ export default async function* buildTextNodes(
299300
if (shouldCollapseTabsAndSpaces && word === ' ') {
300301
w = 0
301302
}
302-
lineWidths.push(currentWidth)
303+
304+
lineWidths.push(currentWidth - prevLineEndingSpacesWidth)
303305
baselines.push(currentBaselineOffset)
304306
lines++
305307
height += currentLineHeight
@@ -376,6 +378,7 @@ export default async function* buildTextNodes(
376378
}
377379

378380
i++
381+
prevLineEndingSpacesWidth = lineEndingSpacesWidth
379382
}
380383

381384
if (currentWidth) {

‎test/line-clamp.test.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ describe('Line Clamp', () => {
155155
fontSize: 32,
156156
textAlign: 'center',
157157
lineClamp: 2,
158+
backgroundColor: '#ff6c2f',
159+
color: 'white',
158160
}}
159161
>
160162
Making the Web. Superfast

‎test/text-align.test.tsx

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import { it, describe, expect } from 'vitest'
2+
3+
import { initFonts, toImage } from './utils.js'
4+
import satori from '../src/index.js'
5+
6+
describe('Text Align', () => {
7+
let fonts
8+
initFonts((f) => (fonts = f))
9+
10+
it('Should work correctly when `text-align: left`', async () => {
11+
const svg = await satori(
12+
<div
13+
style={{
14+
height: '100%',
15+
width: '100%',
16+
display: 'flex',
17+
flexDirection: 'column',
18+
alignItems: 'center',
19+
justifyContent: 'center',
20+
backgroundColor: '#fff',
21+
fontSize: 20,
22+
fontWeight: 600,
23+
}}
24+
>
25+
<div
26+
style={{
27+
display: 'flex',
28+
maxWidth: '190px',
29+
textAlign: 'left',
30+
alignItems: 'center',
31+
justifyContent: 'center',
32+
backgroundColor: '#ff6c2f',
33+
color: 'white',
34+
letterSpacing: '1px',
35+
}}
36+
>
37+
God kisses the finite in his love and man the infinite
38+
</div>
39+
</div>,
40+
{ width: 200, height: 200, fonts, embedFont: true }
41+
)
42+
expect(toImage(svg, 200)).toMatchImageSnapshot()
43+
})
44+
45+
it('Should work correctly when `text-align: center`', async () => {
46+
const svg = await satori(
47+
<div
48+
style={{
49+
height: '100%',
50+
width: '100%',
51+
display: 'flex',
52+
flexDirection: 'column',
53+
alignItems: 'center',
54+
justifyContent: 'center',
55+
backgroundColor: '#fff',
56+
fontSize: 20,
57+
fontWeight: 600,
58+
}}
59+
>
60+
<div
61+
style={{
62+
display: 'flex',
63+
maxWidth: '190px',
64+
textAlign: 'center',
65+
alignItems: 'center',
66+
justifyContent: 'center',
67+
backgroundColor: '#ff6c2f',
68+
color: 'white',
69+
letterSpacing: '1px',
70+
}}
71+
>
72+
God kisses the finite in his love and man the infinite
73+
</div>
74+
</div>,
75+
{ width: 200, height: 200, fonts, embedFont: true }
76+
)
77+
expect(toImage(svg, 200)).toMatchImageSnapshot()
78+
})
79+
80+
it('Should work correctly when `text-align: right`', async () => {
81+
const svg = await satori(
82+
<div
83+
style={{
84+
height: '100%',
85+
width: '100%',
86+
display: 'flex',
87+
flexDirection: 'column',
88+
alignItems: 'center',
89+
justifyContent: 'center',
90+
backgroundColor: '#fff',
91+
fontSize: 20,
92+
fontWeight: 600,
93+
}}
94+
>
95+
<div
96+
style={{
97+
display: 'flex',
98+
maxWidth: '190px',
99+
textAlign: 'right',
100+
alignItems: 'center',
101+
justifyContent: 'center',
102+
backgroundColor: '#ff6c2f',
103+
color: 'white',
104+
letterSpacing: '1px',
105+
}}
106+
>
107+
God kisses the finite in his love and man the infinite
108+
</div>
109+
</div>,
110+
{ width: 200, height: 200, fonts, embedFont: true }
111+
)
112+
expect(toImage(svg, 200)).toMatchImageSnapshot()
113+
})
114+
115+
it('Should work correctly when `text-align: end`', async () => {
116+
const svg = await satori(
117+
<div
118+
style={{
119+
height: '100%',
120+
width: '100%',
121+
display: 'flex',
122+
flexDirection: 'column',
123+
alignItems: 'center',
124+
justifyContent: 'center',
125+
backgroundColor: '#fff',
126+
fontSize: 20,
127+
fontWeight: 600,
128+
}}
129+
>
130+
<div
131+
style={{
132+
display: 'flex',
133+
maxWidth: '190px',
134+
textAlign: 'end',
135+
alignItems: 'center',
136+
justifyContent: 'center',
137+
backgroundColor: '#ff6c2f',
138+
color: 'white',
139+
letterSpacing: '1px',
140+
}}
141+
>
142+
God kisses the finite in his love and man the infinite
143+
</div>
144+
</div>,
145+
{ width: 200, height: 200, fonts, embedFont: true }
146+
)
147+
expect(toImage(svg, 200)).toMatchImageSnapshot()
148+
})
149+
})

1 commit comments

Comments
 (1)

vercel[bot] commented on Aug 11, 2023

@vercel[bot]
Please sign in to comment.