@remotion/layout-utils 4.0.312 → 4.0.314
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/layouts/fill-text-box.js +2 -0
- package/dist/cjs/layouts/fit-text-on-n-lines.d.ts +19 -0
- package/dist/cjs/layouts/fit-text-on-n-lines.js +64 -0
- package/dist/cjs/layouts/measure-text.js +4 -1
- package/dist/esm/index.mjs +70 -1
- package/package.json +2 -2
package/dist/cjs/index.d.ts
CHANGED
package/dist/cjs/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.measureText = exports.fitText = exports.fillTextBox = void 0;
|
|
3
|
+
exports.measureText = exports.fitTextOnNLines = exports.fitText = exports.fillTextBox = void 0;
|
|
4
4
|
var fill_text_box_1 = require("./layouts/fill-text-box");
|
|
5
5
|
Object.defineProperty(exports, "fillTextBox", { enumerable: true, get: function () { return fill_text_box_1.fillTextBox; } });
|
|
6
6
|
var fit_text_1 = require("./layouts/fit-text");
|
|
7
7
|
Object.defineProperty(exports, "fitText", { enumerable: true, get: function () { return fit_text_1.fitText; } });
|
|
8
|
+
var fit_text_on_n_lines_1 = require("./layouts/fit-text-on-n-lines");
|
|
9
|
+
Object.defineProperty(exports, "fitTextOnNLines", { enumerable: true, get: function () { return fit_text_on_n_lines_1.fitTextOnNLines; } });
|
|
8
10
|
var measure_text_1 = require("./layouts/measure-text");
|
|
9
11
|
Object.defineProperty(exports, "measureText", { enumerable: true, get: function () { return measure_text_1.measureText; } });
|
|
@@ -37,6 +37,7 @@ const fillTextBox = ({ maxBoxWidth, maxLines, }) => {
|
|
|
37
37
|
fontWeight,
|
|
38
38
|
fontSize,
|
|
39
39
|
letterSpacing,
|
|
40
|
+
textTransform,
|
|
40
41
|
fontVariantNumeric,
|
|
41
42
|
});
|
|
42
43
|
return { exceedsBox: false, newLine: false };
|
|
@@ -51,6 +52,7 @@ const fillTextBox = ({ maxBoxWidth, maxLines, }) => {
|
|
|
51
52
|
fontWeight,
|
|
52
53
|
fontSize,
|
|
53
54
|
letterSpacing,
|
|
55
|
+
textTransform,
|
|
54
56
|
fontVariantNumeric,
|
|
55
57
|
},
|
|
56
58
|
];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TextTransform } from './measure-text';
|
|
2
|
+
type FitTextOnNLinesProps = {
|
|
3
|
+
text: string;
|
|
4
|
+
maxLines: number;
|
|
5
|
+
maxBoxWidth: number;
|
|
6
|
+
fontFamily: string;
|
|
7
|
+
fontWeight?: number | string;
|
|
8
|
+
letterSpacing?: string;
|
|
9
|
+
fontVariantNumeric?: string;
|
|
10
|
+
validateFontIsLoaded?: boolean;
|
|
11
|
+
textTransform?: TextTransform;
|
|
12
|
+
additionalStyles?: Record<string, string>;
|
|
13
|
+
maxFontSize?: number;
|
|
14
|
+
};
|
|
15
|
+
export declare const fitTextOnNLines: ({ text, maxLines, maxBoxWidth, fontFamily, fontWeight, letterSpacing, fontVariantNumeric, validateFontIsLoaded, textTransform, additionalStyles, maxFontSize, }: FitTextOnNLinesProps) => {
|
|
16
|
+
fontSize: number;
|
|
17
|
+
lines: string[];
|
|
18
|
+
};
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fitTextOnNLines = void 0;
|
|
4
|
+
const fill_text_box_1 = require("./fill-text-box");
|
|
5
|
+
const PRECISION = 100;
|
|
6
|
+
const fitTextOnNLines = ({ text, maxLines, maxBoxWidth, fontFamily, fontWeight, letterSpacing, fontVariantNumeric, validateFontIsLoaded, textTransform, additionalStyles, maxFontSize, }) => {
|
|
7
|
+
// Fixed max font size since we are using binary search a
|
|
8
|
+
const minFontSize = 0.1;
|
|
9
|
+
// Binary search to find the optimal font size
|
|
10
|
+
let left = Math.floor(minFontSize * PRECISION);
|
|
11
|
+
let right = Math.floor((maxFontSize !== null && maxFontSize !== void 0 ? maxFontSize : 2000) * PRECISION);
|
|
12
|
+
let optimalFontSize = minFontSize;
|
|
13
|
+
let optimalLines = [];
|
|
14
|
+
while (left <= right) {
|
|
15
|
+
const mid = Math.floor((left + right) / 2);
|
|
16
|
+
const fontSize = mid / PRECISION;
|
|
17
|
+
// Create a text box with current font size
|
|
18
|
+
const textBox = (0, fill_text_box_1.fillTextBox)({
|
|
19
|
+
maxBoxWidth,
|
|
20
|
+
maxLines,
|
|
21
|
+
});
|
|
22
|
+
// Split text into words and try to fit them
|
|
23
|
+
const words = text.split(' ');
|
|
24
|
+
let exceedsBox = false;
|
|
25
|
+
let currentLine = 0;
|
|
26
|
+
const lines = [''];
|
|
27
|
+
for (const word of words) {
|
|
28
|
+
const result = textBox.add({
|
|
29
|
+
text: word + ' ',
|
|
30
|
+
fontFamily,
|
|
31
|
+
fontWeight,
|
|
32
|
+
fontSize,
|
|
33
|
+
letterSpacing,
|
|
34
|
+
fontVariantNumeric,
|
|
35
|
+
validateFontIsLoaded,
|
|
36
|
+
textTransform,
|
|
37
|
+
additionalStyles,
|
|
38
|
+
});
|
|
39
|
+
if (result.exceedsBox) {
|
|
40
|
+
exceedsBox = true;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
if (result.newLine) {
|
|
44
|
+
lines.push('');
|
|
45
|
+
currentLine++;
|
|
46
|
+
}
|
|
47
|
+
lines[currentLine] += word + ' ';
|
|
48
|
+
}
|
|
49
|
+
// If text fits within the box and number of lines
|
|
50
|
+
if (!exceedsBox && currentLine < maxLines) {
|
|
51
|
+
optimalFontSize = fontSize;
|
|
52
|
+
optimalLines = lines;
|
|
53
|
+
left = mid + 1;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
right = mid - 1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
fontSize: optimalFontSize,
|
|
61
|
+
lines: optimalLines,
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
exports.fitTextOnNLines = fitTextOnNLines;
|
|
@@ -75,7 +75,10 @@ const measureText = ({ text, fontFamily, fontSize, fontWeight, letterSpacing, fo
|
|
|
75
75
|
});
|
|
76
76
|
const sameAsFallbackFont = boundingBox.height === boundingBoxOfFallbackFont.height &&
|
|
77
77
|
boundingBox.width === boundingBoxOfFallbackFont.width;
|
|
78
|
-
|
|
78
|
+
// Ensure there are at least 4 unique characters, with just a few, there is more likely to be a false positive
|
|
79
|
+
if (sameAsFallbackFont &&
|
|
80
|
+
computedFallback !== computedFontFamily &&
|
|
81
|
+
new Set(text).size > 4) {
|
|
79
82
|
const err = [
|
|
80
83
|
`Called measureText() with "fontFamily": ${JSON.stringify(fontFamily)} but it looks like the font is not loaded at the time of calling.`,
|
|
81
84
|
`A measurement with the fallback font ${computedFallback} was taken and had the same dimensions, indicating that the browser used the fallback font.`,
|
package/dist/esm/index.mjs
CHANGED
|
@@ -89,7 +89,7 @@ var measureText = ({
|
|
|
89
89
|
textTransform
|
|
90
90
|
});
|
|
91
91
|
const sameAsFallbackFont = boundingBox.height === boundingBoxOfFallbackFont.height && boundingBox.width === boundingBoxOfFallbackFont.width;
|
|
92
|
-
if (sameAsFallbackFont && computedFallback !== computedFontFamily) {
|
|
92
|
+
if (sameAsFallbackFont && computedFallback !== computedFontFamily && new Set(text).size > 4) {
|
|
93
93
|
const err = [
|
|
94
94
|
`Called measureText() with "fontFamily": ${JSON.stringify(fontFamily)} but it looks like the font is not loaded at the time of calling.`,
|
|
95
95
|
`A measurement with the fallback font ${computedFallback} was taken and had the same dimensions, indicating that the browser used the fallback font.`,
|
|
@@ -153,6 +153,7 @@ var fillTextBox = ({
|
|
|
153
153
|
fontWeight,
|
|
154
154
|
fontSize,
|
|
155
155
|
letterSpacing,
|
|
156
|
+
textTransform,
|
|
156
157
|
fontVariantNumeric
|
|
157
158
|
});
|
|
158
159
|
return { exceedsBox: false, newLine: false };
|
|
@@ -167,6 +168,7 @@ var fillTextBox = ({
|
|
|
167
168
|
fontWeight,
|
|
168
169
|
fontSize,
|
|
169
170
|
letterSpacing,
|
|
171
|
+
textTransform,
|
|
170
172
|
fontVariantNumeric
|
|
171
173
|
}
|
|
172
174
|
];
|
|
@@ -200,8 +202,75 @@ var fitText = ({
|
|
|
200
202
|
});
|
|
201
203
|
return { fontSize: withinWidth / estimate.width * sampleSize };
|
|
202
204
|
};
|
|
205
|
+
// src/layouts/fit-text-on-n-lines.ts
|
|
206
|
+
var PRECISION = 100;
|
|
207
|
+
var fitTextOnNLines = ({
|
|
208
|
+
text,
|
|
209
|
+
maxLines,
|
|
210
|
+
maxBoxWidth,
|
|
211
|
+
fontFamily,
|
|
212
|
+
fontWeight,
|
|
213
|
+
letterSpacing,
|
|
214
|
+
fontVariantNumeric,
|
|
215
|
+
validateFontIsLoaded,
|
|
216
|
+
textTransform,
|
|
217
|
+
additionalStyles,
|
|
218
|
+
maxFontSize
|
|
219
|
+
}) => {
|
|
220
|
+
const minFontSize = 0.1;
|
|
221
|
+
let left = Math.floor(minFontSize * PRECISION);
|
|
222
|
+
let right = Math.floor((maxFontSize ?? 2000) * PRECISION);
|
|
223
|
+
let optimalFontSize = minFontSize;
|
|
224
|
+
let optimalLines = [];
|
|
225
|
+
while (left <= right) {
|
|
226
|
+
const mid = Math.floor((left + right) / 2);
|
|
227
|
+
const fontSize = mid / PRECISION;
|
|
228
|
+
const textBox = fillTextBox({
|
|
229
|
+
maxBoxWidth,
|
|
230
|
+
maxLines
|
|
231
|
+
});
|
|
232
|
+
const words = text.split(" ");
|
|
233
|
+
let exceedsBox = false;
|
|
234
|
+
let currentLine = 0;
|
|
235
|
+
const lines = [""];
|
|
236
|
+
for (const word of words) {
|
|
237
|
+
const result = textBox.add({
|
|
238
|
+
text: word + " ",
|
|
239
|
+
fontFamily,
|
|
240
|
+
fontWeight,
|
|
241
|
+
fontSize,
|
|
242
|
+
letterSpacing,
|
|
243
|
+
fontVariantNumeric,
|
|
244
|
+
validateFontIsLoaded,
|
|
245
|
+
textTransform,
|
|
246
|
+
additionalStyles
|
|
247
|
+
});
|
|
248
|
+
if (result.exceedsBox) {
|
|
249
|
+
exceedsBox = true;
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
if (result.newLine) {
|
|
253
|
+
lines.push("");
|
|
254
|
+
currentLine++;
|
|
255
|
+
}
|
|
256
|
+
lines[currentLine] += word + " ";
|
|
257
|
+
}
|
|
258
|
+
if (!exceedsBox && currentLine < maxLines) {
|
|
259
|
+
optimalFontSize = fontSize;
|
|
260
|
+
optimalLines = lines;
|
|
261
|
+
left = mid + 1;
|
|
262
|
+
} else {
|
|
263
|
+
right = mid - 1;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
fontSize: optimalFontSize,
|
|
268
|
+
lines: optimalLines
|
|
269
|
+
};
|
|
270
|
+
};
|
|
203
271
|
export {
|
|
204
272
|
measureText,
|
|
273
|
+
fitTextOnNLines,
|
|
205
274
|
fitText,
|
|
206
275
|
fillTextBox
|
|
207
276
|
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/layout-utils"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/layout-utils",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.314",
|
|
7
7
|
"description": "Utilities for working with layouts",
|
|
8
8
|
"main": "dist/cjs/index.js",
|
|
9
9
|
"types": "dist/cjs/index.d.ts",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"eslint": "9.19.0",
|
|
23
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
23
|
+
"@remotion/eslint-config-internal": "4.0.314"
|
|
24
24
|
},
|
|
25
25
|
"author": "Yehor Misiats (https://github.com/satelllte)",
|
|
26
26
|
"maintainers": [
|