@remotion/web-renderer 4.0.406 → 4.0.407

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.
@@ -1,6 +1,7 @@
1
1
  import type { DrawFn } from '../drawn-fn';
2
- export declare const drawText: ({ span, logLevel, onlyBackgroundClipText, }: {
2
+ export declare const drawText: ({ span, logLevel, onlyBackgroundClipText, parentRect, }: {
3
3
  span: HTMLSpanElement;
4
4
  logLevel: "error" | "info" | "trace" | "verbose" | "warn";
5
+ parentRect: DOMRect;
5
6
  onlyBackgroundClipText: boolean;
6
7
  }) => DrawFn;
@@ -1,5 +1,6 @@
1
- export declare function findLineBreaks(span: HTMLSpanElement, rtl: boolean): Array<{
1
+ type Token = {
2
2
  text: string;
3
- height: number;
4
- offsetHorizontal: number;
5
- }>;
3
+ rect: DOMRect;
4
+ };
5
+ export declare const findWords: (span: HTMLSpanElement) => Token[];
6
+ export {};
@@ -1 +1,8 @@
1
- export declare const getCollapsedText: (span: HTMLSpanElement) => string;
1
+ export declare const getCollapsedText: ({ span, previousText, wordsToAdd, canCollapseStart, }: {
2
+ wordsToAdd: string;
3
+ span: HTMLSpanElement;
4
+ previousText: string;
5
+ canCollapseStart: boolean;
6
+ }) => {
7
+ collapsedText: string;
8
+ };
@@ -3244,151 +3244,42 @@ var applyTextTransform = (text, transform) => {
3244
3244
  return text;
3245
3245
  };
3246
3246
 
3247
- // src/drawing/text/get-collapsed-text.ts
3248
- var getCollapsedText = (span) => {
3249
- const textNode = span.firstChild;
3250
- if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
3251
- throw new Error("Span must contain a single text node");
3252
- }
3253
- const originalText = textNode.textContent || "";
3254
- let collapsedText = originalText;
3255
- const measureWidth = (text) => {
3256
- textNode.textContent = text;
3257
- return span.getBoundingClientRect().width;
3258
- };
3259
- const originalWidth = measureWidth(originalText);
3260
- if (/^\s/.test(collapsedText)) {
3261
- const trimmedLeading = collapsedText.replace(/^\s+/, "");
3262
- const newWidth = measureWidth(trimmedLeading);
3263
- if (newWidth === originalWidth) {
3264
- collapsedText = trimmedLeading;
3265
- }
3266
- }
3267
- if (/\s$/.test(collapsedText)) {
3268
- const currentWidth = measureWidth(collapsedText);
3269
- const trimmedTrailing = collapsedText.replace(/\s+$/, "");
3270
- const newWidth = measureWidth(trimmedTrailing);
3271
- if (newWidth === currentWidth) {
3272
- collapsedText = trimmedTrailing;
3273
- }
3274
- }
3275
- if (/\s\s/.test(collapsedText)) {
3276
- const currentWidth = measureWidth(collapsedText);
3277
- const collapsedInternal = collapsedText.replace(/\s\s+/g, " ");
3278
- const newWidth = measureWidth(collapsedInternal);
3279
- if (newWidth === currentWidth) {
3280
- collapsedText = collapsedInternal;
3281
- }
3282
- }
3283
- textNode.textContent = originalText;
3284
- return collapsedText;
3285
- };
3286
-
3287
3247
  // src/drawing/text/find-line-breaks.text.ts
3288
- var cannotStartLine = (segment) => {
3289
- if (segment.length === 0)
3290
- return false;
3291
- const firstChar = segment[0];
3292
- const forbiddenLineStarts = [
3293
- ".",
3294
- ",",
3295
- ";",
3296
- ":",
3297
- "!",
3298
- "?",
3299
- ")",
3300
- "]",
3301
- "}",
3302
- '"',
3303
- "'",
3304
- '"',
3305
- `'`,
3306
- "»",
3307
- "…",
3308
- "‥",
3309
- "·",
3310
- "%",
3311
- "‰"
3312
- ];
3313
- return forbiddenLineStarts.includes(firstChar);
3314
- };
3315
- function findLineBreaks(span, rtl) {
3316
- const textNode = span.childNodes[0];
3317
- const originalText = textNode.textContent;
3318
- const originalRect = span.getBoundingClientRect();
3319
- const computedStyle = getComputedStyle(span);
3248
+ var findWords = (span) => {
3249
+ const originalText = span.textContent;
3320
3250
  const segmenter = new Intl.Segmenter("en", { granularity: "word" });
3321
- const segments = segmenter.segment(originalText);
3251
+ const segments = segmenter.segment(span.textContent);
3322
3252
  const words = Array.from(segments).map((s) => s.segment);
3323
- const lines = [];
3324
- let currentLine = "";
3325
- let testText = "";
3326
- let previousRect = originalRect;
3327
- textNode.textContent = "";
3328
- for (let i = 0;i < words.length; i += 1) {
3253
+ const tokens = [];
3254
+ for (let i = 0;i < words.length; i++) {
3255
+ const wordsBefore = words.slice(0, i);
3256
+ const wordsAfter = words.slice(i + 1);
3329
3257
  const word = words[i];
3330
- testText += word;
3331
- let wordsToAdd = word;
3332
- while (typeof words[i + 1] !== "undefined" && words[i + 1].trim() === "") {
3333
- testText += words[i + 1];
3334
- wordsToAdd += words[i + 1];
3335
- i++;
3336
- }
3337
- previousRect = span.getBoundingClientRect();
3338
- textNode.textContent = testText;
3339
- const collapsedText = getCollapsedText(span);
3340
- textNode.textContent = collapsedText;
3341
- const rect = span.getBoundingClientRect();
3342
- const currentHeight = rect.height;
3343
- if (previousRect && previousRect.height !== 0 && Math.abs(currentHeight - previousRect.height) > 2) {
3344
- const offsetHorizontal = rtl ? previousRect.right - originalRect.right : previousRect.left - originalRect.left;
3345
- const shouldCollapse = !computedStyle.whiteSpaceCollapse.includes("preserve");
3346
- let textForPreviousLine = currentLine;
3347
- let textForNewLine = wordsToAdd;
3348
- if (cannotStartLine(word)) {
3349
- const currentLineSegments = Array.from(segmenter.segment(currentLine)).map((s) => s.segment);
3350
- let lastWordIndex = currentLineSegments.length - 1;
3351
- while (lastWordIndex >= 0 && currentLineSegments[lastWordIndex].trim() === "") {
3352
- lastWordIndex--;
3353
- }
3354
- if (lastWordIndex >= 0) {
3355
- textForPreviousLine = currentLineSegments.slice(0, lastWordIndex).join("");
3356
- textForNewLine = currentLineSegments.slice(lastWordIndex).join("") + wordsToAdd;
3357
- }
3358
- }
3359
- lines.push({
3360
- text: shouldCollapse ? textForPreviousLine.trim() : textForPreviousLine,
3361
- height: currentHeight - previousRect.height,
3362
- offsetHorizontal
3363
- });
3364
- currentLine = textForNewLine;
3365
- } else {
3366
- currentLine += wordsToAdd;
3367
- }
3368
- }
3369
- if (currentLine) {
3370
- textNode.textContent = testText;
3371
- const rects = span.getClientRects();
3372
- const rect = span.getBoundingClientRect();
3373
- const lastRect = rects[rects.length - 1];
3374
- const offsetHorizontal = rtl ? lastRect.right - originalRect.right : lastRect.left - originalRect.left;
3375
- lines.push({
3376
- text: currentLine,
3377
- height: rect.height - lines.reduce((acc, curr) => acc + curr.height, 0),
3378
- offsetHorizontal
3379
- });
3258
+ const wordsBeforeText = wordsBefore.join("");
3259
+ const wordsAfterText = wordsAfter.join("");
3260
+ const beforeNode = document.createTextNode(wordsBeforeText);
3261
+ const afterNode = document.createTextNode(wordsAfterText);
3262
+ const interstitialNode = document.createElement("span");
3263
+ interstitialNode.textContent = word;
3264
+ span.textContent = "";
3265
+ span.appendChild(beforeNode);
3266
+ span.appendChild(interstitialNode);
3267
+ span.appendChild(afterNode);
3268
+ const rect = interstitialNode.getBoundingClientRect();
3269
+ span.textContent = originalText;
3270
+ tokens.push({ text: word, rect });
3380
3271
  }
3381
- textNode.textContent = originalText;
3382
- return lines;
3383
- }
3272
+ return tokens;
3273
+ };
3384
3274
 
3385
3275
  // src/drawing/text/draw-text.ts
3386
3276
  var drawText = ({
3387
3277
  span,
3388
3278
  logLevel,
3389
- onlyBackgroundClipText
3279
+ onlyBackgroundClipText,
3280
+ parentRect
3390
3281
  }) => {
3391
- const drawFn = ({ dimensions: rect, computedStyle, contextToDraw }) => {
3282
+ const drawFn = ({ computedStyle, contextToDraw }) => {
3392
3283
  const {
3393
3284
  fontFamily,
3394
3285
  fontSize,
@@ -3416,20 +3307,16 @@ var drawText = ({
3416
3307
  contextToDraw.textAlign = isRTL ? "right" : "left";
3417
3308
  contextToDraw.textBaseline = "alphabetic";
3418
3309
  const originalText = span.textContent;
3419
- const collapsedText = getCollapsedText(span);
3420
- const transformedText = applyTextTransform(collapsedText, textTransform);
3310
+ const transformedText = applyTextTransform(originalText, textTransform);
3421
3311
  span.textContent = transformedText;
3422
- const xPosition = isRTL ? rect.right : rect.left;
3423
- const lines = findLineBreaks(span, isRTL);
3424
- let offsetTop = 0;
3425
- const measurements = contextToDraw.measureText(lines[0].text);
3426
- const { fontBoundingBoxDescent, fontBoundingBoxAscent } = measurements;
3427
- const fontHeight = fontBoundingBoxAscent + fontBoundingBoxDescent;
3428
- for (const line of lines) {
3429
- const leading = line.height - fontHeight;
3312
+ const tokens = findWords(span);
3313
+ for (const token of tokens) {
3314
+ const measurements = contextToDraw.measureText(originalText);
3315
+ const { fontBoundingBoxDescent, fontBoundingBoxAscent } = measurements;
3316
+ const fontHeight = fontBoundingBoxAscent + fontBoundingBoxDescent;
3317
+ const leading = token.rect.height - fontHeight;
3430
3318
  const halfLeading = leading / 2;
3431
- contextToDraw.fillText(line.text, xPosition + line.offsetHorizontal, rect.top + halfLeading + fontBoundingBoxAscent + offsetTop);
3432
- offsetTop += line.height;
3319
+ contextToDraw.fillText(token.text, (isRTL ? token.rect.right : token.rect.left) - parentRect.x, token.rect.top + fontBoundingBoxAscent + halfLeading - parentRect.y);
3433
3320
  }
3434
3321
  span.textContent = originalText;
3435
3322
  contextToDraw.restore();
@@ -3458,7 +3345,7 @@ var handleTextNode = async ({
3458
3345
  const value = await processNode({
3459
3346
  context,
3460
3347
  element: span,
3461
- draw: drawText({ span, logLevel, onlyBackgroundClipText }),
3348
+ draw: drawText({ span, logLevel, onlyBackgroundClipText, parentRect }),
3462
3349
  logLevel,
3463
3350
  parentRect,
3464
3351
  internalState,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/web-renderer"
4
4
  },
5
5
  "name": "@remotion/web-renderer",
6
- "version": "4.0.406",
6
+ "version": "4.0.407",
7
7
  "main": "dist/index.js",
8
8
  "type": "module",
9
9
  "sideEffects": false,
@@ -19,14 +19,14 @@
19
19
  "author": "Remotion <jonny@remotion.dev>",
20
20
  "license": "UNLICENSED",
21
21
  "dependencies": {
22
- "@remotion/licensing": "4.0.406",
23
- "remotion": "4.0.406",
22
+ "@remotion/licensing": "4.0.407",
23
+ "remotion": "4.0.407",
24
24
  "mediabunny": "1.27.3"
25
25
  },
26
26
  "devDependencies": {
27
- "@remotion/eslint-config-internal": "4.0.406",
28
- "@remotion/player": "4.0.406",
29
- "@remotion/media": "4.0.406",
27
+ "@remotion/eslint-config-internal": "4.0.407",
28
+ "@remotion/player": "4.0.407",
29
+ "@remotion/media": "4.0.407",
30
30
  "@typescript/native-preview": "7.0.0-dev.20260105.1",
31
31
  "@vitejs/plugin-react": "4.1.0",
32
32
  "@vitest/browser-playwright": "4.0.9",