ugcinc-render 1.5.28 → 1.5.30
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/index.js +76 -3
- package/dist/index.mjs +76 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -388,6 +388,51 @@ function hexToRgba(hex, opacity = 100) {
|
|
|
388
388
|
return `rgba(${r}, ${g}, ${b}, ${opacity / 100})`;
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
+
// src/utils/emoji.ts
|
|
392
|
+
var APPLE_EMOJI_CDN_BASE = "https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/";
|
|
393
|
+
function emojiToUnified(emoji) {
|
|
394
|
+
const codePoints = [];
|
|
395
|
+
for (const codePoint of emoji) {
|
|
396
|
+
const hex = codePoint.codePointAt(0)?.toString(16);
|
|
397
|
+
if (hex) {
|
|
398
|
+
codePoints.push(hex);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return codePoints.join("-");
|
|
402
|
+
}
|
|
403
|
+
function getAppleEmojiUrl(emoji) {
|
|
404
|
+
const unified = emojiToUnified(emoji);
|
|
405
|
+
return `${APPLE_EMOJI_CDN_BASE}${unified}.png`;
|
|
406
|
+
}
|
|
407
|
+
var EMOJI_REGEX = /(?:\p{Emoji_Presentation}|\p{Emoji}\uFE0F)(?:\p{Emoji_Modifier}|\uFE0F|\u200D(?:\p{Emoji_Presentation}|\p{Emoji}\uFE0F)(?:\p{Emoji_Modifier})?)*|\p{Regional_Indicator}{2}/gu;
|
|
408
|
+
function splitTextAndEmojis(text) {
|
|
409
|
+
const segments = [];
|
|
410
|
+
let lastIndex = 0;
|
|
411
|
+
EMOJI_REGEX.lastIndex = 0;
|
|
412
|
+
let match;
|
|
413
|
+
while ((match = EMOJI_REGEX.exec(text)) !== null) {
|
|
414
|
+
if (match.index > lastIndex) {
|
|
415
|
+
segments.push({
|
|
416
|
+
type: "text",
|
|
417
|
+
content: text.slice(lastIndex, match.index)
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
segments.push({
|
|
421
|
+
type: "emoji",
|
|
422
|
+
content: match[0],
|
|
423
|
+
imageUrl: getAppleEmojiUrl(match[0])
|
|
424
|
+
});
|
|
425
|
+
lastIndex = match.index + match[0].length;
|
|
426
|
+
}
|
|
427
|
+
if (lastIndex < text.length) {
|
|
428
|
+
segments.push({
|
|
429
|
+
type: "text",
|
|
430
|
+
content: text.slice(lastIndex)
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
return segments;
|
|
434
|
+
}
|
|
435
|
+
|
|
391
436
|
// src/components/TextElement.tsx
|
|
392
437
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
393
438
|
function calculateAutoWidthAndLines({
|
|
@@ -686,9 +731,37 @@ function TextElement({ segment, scale = 1 }) {
|
|
|
686
731
|
autoWidth,
|
|
687
732
|
verticalAlign
|
|
688
733
|
]);
|
|
734
|
+
const hasStroke = strokeWidth > 0 && strokeColor;
|
|
735
|
+
const renderTextWithEmojis = (text) => {
|
|
736
|
+
if (!hasStroke) {
|
|
737
|
+
return text;
|
|
738
|
+
}
|
|
739
|
+
const segments = splitTextAndEmojis(text);
|
|
740
|
+
if (segments.every((s) => s.type === "text")) {
|
|
741
|
+
return text;
|
|
742
|
+
}
|
|
743
|
+
return segments.map((segment2, i) => {
|
|
744
|
+
if (segment2.type === "text") {
|
|
745
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.default.Fragment, { children: segment2.content }, i);
|
|
746
|
+
}
|
|
747
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
748
|
+
"span",
|
|
749
|
+
{
|
|
750
|
+
style: {
|
|
751
|
+
textShadow: "none",
|
|
752
|
+
WebkitTextStroke: "initial",
|
|
753
|
+
// Ensure emoji renders properly
|
|
754
|
+
display: "inline"
|
|
755
|
+
},
|
|
756
|
+
children: segment2.content
|
|
757
|
+
},
|
|
758
|
+
i
|
|
759
|
+
);
|
|
760
|
+
});
|
|
761
|
+
};
|
|
689
762
|
if (autoWidth) {
|
|
690
763
|
const textContent = calculatedLines.map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [
|
|
691
|
-
line,
|
|
764
|
+
renderTextWithEmojis(line),
|
|
692
765
|
index < calculatedLines.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {})
|
|
693
766
|
] }, index));
|
|
694
767
|
if (backgroundColor) {
|
|
@@ -707,7 +780,7 @@ function TextElement({ segment, scale = 1 }) {
|
|
|
707
780
|
}
|
|
708
781
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: positioningContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { width: calculatedWidth, maxWidth: width }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: textStyle, children: textContent }) }) });
|
|
709
782
|
}
|
|
710
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: positioningContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: backgroundBoxStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: textStyle, children: segment.text }) }) });
|
|
783
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: positioningContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: backgroundBoxStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: textStyle, children: renderTextWithEmojis(segment.text) }) }) });
|
|
711
784
|
}
|
|
712
785
|
|
|
713
786
|
// src/components/ImageElement.tsx
|
|
@@ -1675,7 +1748,7 @@ function VideoElement({
|
|
|
1675
1748
|
{
|
|
1676
1749
|
src,
|
|
1677
1750
|
style: videoStyle,
|
|
1678
|
-
|
|
1751
|
+
trimBefore: startFromFrames,
|
|
1679
1752
|
playbackRate: speed,
|
|
1680
1753
|
volume
|
|
1681
1754
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -302,6 +302,51 @@ function hexToRgba(hex, opacity = 100) {
|
|
|
302
302
|
return `rgba(${r}, ${g}, ${b}, ${opacity / 100})`;
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
+
// src/utils/emoji.ts
|
|
306
|
+
var APPLE_EMOJI_CDN_BASE = "https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/apple/64/";
|
|
307
|
+
function emojiToUnified(emoji) {
|
|
308
|
+
const codePoints = [];
|
|
309
|
+
for (const codePoint of emoji) {
|
|
310
|
+
const hex = codePoint.codePointAt(0)?.toString(16);
|
|
311
|
+
if (hex) {
|
|
312
|
+
codePoints.push(hex);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return codePoints.join("-");
|
|
316
|
+
}
|
|
317
|
+
function getAppleEmojiUrl(emoji) {
|
|
318
|
+
const unified = emojiToUnified(emoji);
|
|
319
|
+
return `${APPLE_EMOJI_CDN_BASE}${unified}.png`;
|
|
320
|
+
}
|
|
321
|
+
var EMOJI_REGEX = /(?:\p{Emoji_Presentation}|\p{Emoji}\uFE0F)(?:\p{Emoji_Modifier}|\uFE0F|\u200D(?:\p{Emoji_Presentation}|\p{Emoji}\uFE0F)(?:\p{Emoji_Modifier})?)*|\p{Regional_Indicator}{2}/gu;
|
|
322
|
+
function splitTextAndEmojis(text) {
|
|
323
|
+
const segments = [];
|
|
324
|
+
let lastIndex = 0;
|
|
325
|
+
EMOJI_REGEX.lastIndex = 0;
|
|
326
|
+
let match;
|
|
327
|
+
while ((match = EMOJI_REGEX.exec(text)) !== null) {
|
|
328
|
+
if (match.index > lastIndex) {
|
|
329
|
+
segments.push({
|
|
330
|
+
type: "text",
|
|
331
|
+
content: text.slice(lastIndex, match.index)
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
segments.push({
|
|
335
|
+
type: "emoji",
|
|
336
|
+
content: match[0],
|
|
337
|
+
imageUrl: getAppleEmojiUrl(match[0])
|
|
338
|
+
});
|
|
339
|
+
lastIndex = match.index + match[0].length;
|
|
340
|
+
}
|
|
341
|
+
if (lastIndex < text.length) {
|
|
342
|
+
segments.push({
|
|
343
|
+
type: "text",
|
|
344
|
+
content: text.slice(lastIndex)
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
return segments;
|
|
348
|
+
}
|
|
349
|
+
|
|
305
350
|
// src/components/TextElement.tsx
|
|
306
351
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
307
352
|
function calculateAutoWidthAndLines({
|
|
@@ -600,9 +645,37 @@ function TextElement({ segment, scale = 1 }) {
|
|
|
600
645
|
autoWidth,
|
|
601
646
|
verticalAlign
|
|
602
647
|
]);
|
|
648
|
+
const hasStroke = strokeWidth > 0 && strokeColor;
|
|
649
|
+
const renderTextWithEmojis = (text) => {
|
|
650
|
+
if (!hasStroke) {
|
|
651
|
+
return text;
|
|
652
|
+
}
|
|
653
|
+
const segments = splitTextAndEmojis(text);
|
|
654
|
+
if (segments.every((s) => s.type === "text")) {
|
|
655
|
+
return text;
|
|
656
|
+
}
|
|
657
|
+
return segments.map((segment2, i) => {
|
|
658
|
+
if (segment2.type === "text") {
|
|
659
|
+
return /* @__PURE__ */ jsx(React.Fragment, { children: segment2.content }, i);
|
|
660
|
+
}
|
|
661
|
+
return /* @__PURE__ */ jsx(
|
|
662
|
+
"span",
|
|
663
|
+
{
|
|
664
|
+
style: {
|
|
665
|
+
textShadow: "none",
|
|
666
|
+
WebkitTextStroke: "initial",
|
|
667
|
+
// Ensure emoji renders properly
|
|
668
|
+
display: "inline"
|
|
669
|
+
},
|
|
670
|
+
children: segment2.content
|
|
671
|
+
},
|
|
672
|
+
i
|
|
673
|
+
);
|
|
674
|
+
});
|
|
675
|
+
};
|
|
603
676
|
if (autoWidth) {
|
|
604
677
|
const textContent = calculatedLines.map((line, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
605
|
-
line,
|
|
678
|
+
renderTextWithEmojis(line),
|
|
606
679
|
index < calculatedLines.length - 1 && /* @__PURE__ */ jsx("br", {})
|
|
607
680
|
] }, index));
|
|
608
681
|
if (backgroundColor) {
|
|
@@ -621,7 +694,7 @@ function TextElement({ segment, scale = 1 }) {
|
|
|
621
694
|
}
|
|
622
695
|
return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsx("div", { style: { width: calculatedWidth, maxWidth: width }, children: /* @__PURE__ */ jsx("div", { style: textStyle, children: textContent }) }) });
|
|
623
696
|
}
|
|
624
|
-
return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsx("div", { style: backgroundBoxStyle, children: /* @__PURE__ */ jsx("div", { style: textStyle, children: segment.text }) }) });
|
|
697
|
+
return /* @__PURE__ */ jsx("div", { style: positioningContainerStyle, children: /* @__PURE__ */ jsx("div", { style: backgroundBoxStyle, children: /* @__PURE__ */ jsx("div", { style: textStyle, children: renderTextWithEmojis(segment.text) }) }) });
|
|
625
698
|
}
|
|
626
699
|
|
|
627
700
|
// src/components/ImageElement.tsx
|
|
@@ -1589,7 +1662,7 @@ function VideoElement({
|
|
|
1589
1662
|
{
|
|
1590
1663
|
src,
|
|
1591
1664
|
style: videoStyle,
|
|
1592
|
-
|
|
1665
|
+
trimBefore: startFromFrames,
|
|
1593
1666
|
playbackRate: speed,
|
|
1594
1667
|
volume
|
|
1595
1668
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ugcinc-render",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.30",
|
|
4
4
|
"description": "Unified rendering package for UGC Inc - shared types, components, and compositions for pixel-perfect client/server rendering",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|