@lumiastream/ui 0.5.0 → 0.5.3
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 +73 -18
- package/dist/se-import.js +73 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3154,7 +3154,40 @@ var SE_TO_LUMIA_PLACEHOLDER = {
|
|
|
3154
3154
|
// tied to an alert payload), so we route it at the *global* template
|
|
3155
3155
|
// variable `{{streamer}}` populated by VariablesManager.refreshStreamerVariable
|
|
3156
3156
|
// (Twitch → Kick → YouTube → Facebook → TikTok fallback chain).
|
|
3157
|
-
streamer: "streamer"
|
|
3157
|
+
streamer: "streamer",
|
|
3158
|
+
// Sub / resub months — SL and SE both expose `{months}` inside sub-event
|
|
3159
|
+
// variation templates ("{name} just resubbed for {months} months!"). Lumia
|
|
3160
|
+
// surfaces this on the subscriber alert payload as `subMonths` (see
|
|
3161
|
+
// lumia-types/src/variables.types.ts). Mapping is global because `{months}`
|
|
3162
|
+
// only ever appears in subscriber-context templates in the wild — neither
|
|
3163
|
+
// SE nor SL emit it for follower / cheer / tip alerts.
|
|
3164
|
+
months: "subMonths",
|
|
3165
|
+
// Merch / loyalty redemption product name — SL emits `{product}` in
|
|
3166
|
+
// merch_message_template and loyalty_store_redemption_message_template,
|
|
3167
|
+
// SE emits it the same way. Lumia's shopOrder alert exposes the first
|
|
3168
|
+
// item's name as `firstItem.name`; alias to `item` (which already maps
|
|
3169
|
+
// there) so both tokens resolve identically.
|
|
3170
|
+
product: "firstItem.name",
|
|
3171
|
+
// Treatstream title — SL `treat_message_template`
|
|
3172
|
+
// ("{name} bought you a {title} treat"). Lumia's treat alert exposes the
|
|
3173
|
+
// gift name as `treat` (see treatstream entry in variables.types.ts).
|
|
3174
|
+
title: "treat",
|
|
3175
|
+
// SL custom-HTML alias for the chat message — `{userMessage}` and
|
|
3176
|
+
// `{message}` mean the same thing. Both should resolve to Lumia's
|
|
3177
|
+
// `{{message}}`.
|
|
3178
|
+
userMessage: "message",
|
|
3179
|
+
// Prime-gaming gift tier — SL `prime_sub_gift_message_template`
|
|
3180
|
+
// ("{name} gifted {giftType} Ultra subscription to {streamer}"). The gift
|
|
3181
|
+
// type carries the subscription tier ("1000" / "2000" / "3000" / "prime")
|
|
3182
|
+
// which Lumia exposes as `tier` on every sub-related alert payload.
|
|
3183
|
+
giftType: "tier",
|
|
3184
|
+
// TikTok-style jewel gift quantity — SL `jewel_gift_message_template`
|
|
3185
|
+
// ("{name} gifted {giftName} x{jewelsAmount} jewels!"). Lumia's tiktok-gift
|
|
3186
|
+
// alert exposes the quantity as `amount`. `{giftName}` (the gift's display
|
|
3187
|
+
// name) doesn't have a 1:1 Lumia variable — TikTok's gift catalog isn't
|
|
3188
|
+
// directly imported — so we leave it unmapped and the streamer can adjust
|
|
3189
|
+
// the template in the Lumia editor.
|
|
3190
|
+
jewelsAmount: "amount"
|
|
3158
3191
|
};
|
|
3159
3192
|
var TWITCH_CONTEXTS = {
|
|
3160
3193
|
"follower-latest": {
|
|
@@ -6886,9 +6919,9 @@ async function fetchWithProxyFallback(url, options = {}) {
|
|
|
6886
6919
|
}
|
|
6887
6920
|
|
|
6888
6921
|
// src/se-import/assets.ts
|
|
6889
|
-
var IMPORTABLE_CDN_REGEX = /https?:\/\/(?:(?:cdn|static)\.streamelements\.com|streamelements-cdn\.com|cdn\.streamlabs\.com|(?:cdn|uploads)\.twitchalerts\.com)\/[^\s"'\\)]+/g;
|
|
6922
|
+
var IMPORTABLE_CDN_REGEX = /https?:\/\/(?:(?:cdn|static)\.streamelements\.com|streamelements-cdn\.com|streamlabs\.com|cdn\.streamlabs\.com|(?:cdn|uploads)\.twitchalerts\.com)\/[^\s"'\\)]+/g;
|
|
6890
6923
|
var CSS_URL_REGEX = /url\(\s*['"]?([^'")]+)['"]?\s*\)/g;
|
|
6891
|
-
var IMPORTABLE_CDN_HOST_REGEX = /^https?:\/\/(?:(?:cdn|static)\.streamelements\.com|streamelements-cdn\.com|cdn\.streamlabs\.com|(?:cdn|uploads)\.twitchalerts\.com)\//;
|
|
6924
|
+
var IMPORTABLE_CDN_HOST_REGEX = /^https?:\/\/(?:(?:cdn|static)\.streamelements\.com|streamelements-cdn\.com|streamlabs\.com|cdn\.streamlabs\.com|(?:cdn|uploads)\.twitchalerts\.com)\//;
|
|
6892
6925
|
function isImportableAssetUrl(url) {
|
|
6893
6926
|
return IMPORTABLE_CDN_HOST_REGEX.test(url);
|
|
6894
6927
|
}
|
|
@@ -7631,7 +7664,7 @@ function absolutizeSLUrl(raw) {
|
|
|
7631
7664
|
if (typeof raw !== "string" || raw.length === 0) return "";
|
|
7632
7665
|
if (raw.startsWith("http://") || raw.startsWith("https://")) return raw;
|
|
7633
7666
|
if (raw.startsWith("//")) return `https:${raw}`;
|
|
7634
|
-
if (raw.startsWith("/")) return `https://
|
|
7667
|
+
if (raw.startsWith("/")) return `https://streamlabs.com${raw}`;
|
|
7635
7668
|
return raw;
|
|
7636
7669
|
}
|
|
7637
7670
|
function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
@@ -7642,13 +7675,7 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
7642
7675
|
const fontWeight = getField(settings, prefix, "font_weight") ?? 600;
|
|
7643
7676
|
const fontColor = getField(settings, prefix, "font_color") ?? "#FFFFFF";
|
|
7644
7677
|
const highlightColor = getField(settings, prefix, "font_color2") ?? "#32C3A6";
|
|
7645
|
-
const
|
|
7646
|
-
getField(settings, prefix, "message_font_size"),
|
|
7647
|
-
20
|
|
7648
|
-
);
|
|
7649
|
-
const messageFontFamily = getField(settings, prefix, "message_font") ?? fontFamily;
|
|
7650
|
-
const messageFontWeight = getField(settings, prefix, "message_font_weight") ?? 400;
|
|
7651
|
-
const messageFontColor = getField(settings, prefix, "message_font_color") ?? "#FFFFFF";
|
|
7678
|
+
const secondaryMessage = readSecondaryMessageConfig(settings, prefix, fontFamily);
|
|
7652
7679
|
const imageHref = absolutizeSLUrl(getField(settings, prefix, "image_href"));
|
|
7653
7680
|
const soundHref = absolutizeSLUrl(getField(settings, prefix, "sound_href"));
|
|
7654
7681
|
const soundVolume = getField(settings, prefix, "sound_volume") ?? 50;
|
|
@@ -7667,7 +7694,7 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
7667
7694
|
accentColor: null,
|
|
7668
7695
|
highlightColor,
|
|
7669
7696
|
firstMessageTemplate: translateSeText(messageTemplate),
|
|
7670
|
-
secondMessageTemplate: "",
|
|
7697
|
+
secondMessageTemplate: secondaryMessage?.template ?? "",
|
|
7671
7698
|
thirdMessageTemplate: "",
|
|
7672
7699
|
showAvatar: false,
|
|
7673
7700
|
showAmount: true,
|
|
@@ -7690,12 +7717,10 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
7690
7717
|
textShadow: "rgba(0, 0, 0, 0.8) 1px 1px 1px",
|
|
7691
7718
|
textAlign: "center"
|
|
7692
7719
|
},
|
|
7693
|
-
messageCss
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
fontWeight: messageFontWeight
|
|
7698
|
-
},
|
|
7720
|
+
// `messageCss` only matters when secondMessageTemplate is set;
|
|
7721
|
+
// leave it empty when SL didn't ship a secondary-message block
|
|
7722
|
+
// so Lumia's renderer falls back to its own default styling.
|
|
7723
|
+
messageCss: secondaryMessage?.css ?? {},
|
|
7699
7724
|
content: { value: translateSeText(messageTemplate) }
|
|
7700
7725
|
},
|
|
7701
7726
|
media: {
|
|
@@ -7738,6 +7763,36 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
7738
7763
|
variations: []
|
|
7739
7764
|
};
|
|
7740
7765
|
}
|
|
7766
|
+
var SECONDARY_MESSAGE_PREFIX_OVERRIDE = {
|
|
7767
|
+
sub: "resub"
|
|
7768
|
+
};
|
|
7769
|
+
function readSecondaryMessageConfig(settings, prefix, primaryFontFamily) {
|
|
7770
|
+
const secondaryPrefix = SECONDARY_MESSAGE_PREFIX_OVERRIDE[prefix] ?? prefix;
|
|
7771
|
+
const showKey = `show_${secondaryPrefix}_message`;
|
|
7772
|
+
const enabled = settings[showKey];
|
|
7773
|
+
if (enabled !== true) return null;
|
|
7774
|
+
const fontFamily = getField(settings, secondaryPrefix, "message_font") ?? primaryFontFamily;
|
|
7775
|
+
const fontSize = pxToNumber(
|
|
7776
|
+
getField(settings, secondaryPrefix, "message_font_size"),
|
|
7777
|
+
20
|
|
7778
|
+
);
|
|
7779
|
+
const fontWeight = getField(settings, secondaryPrefix, "message_font_weight") ?? 400;
|
|
7780
|
+
const fontColor = getField(settings, secondaryPrefix, "message_font_color") ?? "#FFFFFF";
|
|
7781
|
+
return {
|
|
7782
|
+
// `{message}` is the SE/SL chat-message token (mapped to Lumia's
|
|
7783
|
+
// `{{message}}` in translate.ts). It resolves at render time from
|
|
7784
|
+
// the alert payload's `message` field — populated for every event
|
|
7785
|
+
// where SL ships a secondary-message line (donations, resubs,
|
|
7786
|
+
// cheers, charity, merch, etc.).
|
|
7787
|
+
template: translateSeText("{message}"),
|
|
7788
|
+
css: {
|
|
7789
|
+
fontFamily,
|
|
7790
|
+
fontSize,
|
|
7791
|
+
color: fontColor,
|
|
7792
|
+
fontWeight
|
|
7793
|
+
}
|
|
7794
|
+
};
|
|
7795
|
+
}
|
|
7741
7796
|
function clampVolume(slVolume) {
|
|
7742
7797
|
if (typeof slVolume !== "number" || !Number.isFinite(slVolume)) return 0.5;
|
|
7743
7798
|
return Math.max(0, Math.min(1, slVolume / 100));
|
package/dist/se-import.js
CHANGED
|
@@ -20,7 +20,40 @@ var SE_TO_LUMIA_PLACEHOLDER = {
|
|
|
20
20
|
// tied to an alert payload), so we route it at the *global* template
|
|
21
21
|
// variable `{{streamer}}` populated by VariablesManager.refreshStreamerVariable
|
|
22
22
|
// (Twitch → Kick → YouTube → Facebook → TikTok fallback chain).
|
|
23
|
-
streamer: "streamer"
|
|
23
|
+
streamer: "streamer",
|
|
24
|
+
// Sub / resub months — SL and SE both expose `{months}` inside sub-event
|
|
25
|
+
// variation templates ("{name} just resubbed for {months} months!"). Lumia
|
|
26
|
+
// surfaces this on the subscriber alert payload as `subMonths` (see
|
|
27
|
+
// lumia-types/src/variables.types.ts). Mapping is global because `{months}`
|
|
28
|
+
// only ever appears in subscriber-context templates in the wild — neither
|
|
29
|
+
// SE nor SL emit it for follower / cheer / tip alerts.
|
|
30
|
+
months: "subMonths",
|
|
31
|
+
// Merch / loyalty redemption product name — SL emits `{product}` in
|
|
32
|
+
// merch_message_template and loyalty_store_redemption_message_template,
|
|
33
|
+
// SE emits it the same way. Lumia's shopOrder alert exposes the first
|
|
34
|
+
// item's name as `firstItem.name`; alias to `item` (which already maps
|
|
35
|
+
// there) so both tokens resolve identically.
|
|
36
|
+
product: "firstItem.name",
|
|
37
|
+
// Treatstream title — SL `treat_message_template`
|
|
38
|
+
// ("{name} bought you a {title} treat"). Lumia's treat alert exposes the
|
|
39
|
+
// gift name as `treat` (see treatstream entry in variables.types.ts).
|
|
40
|
+
title: "treat",
|
|
41
|
+
// SL custom-HTML alias for the chat message — `{userMessage}` and
|
|
42
|
+
// `{message}` mean the same thing. Both should resolve to Lumia's
|
|
43
|
+
// `{{message}}`.
|
|
44
|
+
userMessage: "message",
|
|
45
|
+
// Prime-gaming gift tier — SL `prime_sub_gift_message_template`
|
|
46
|
+
// ("{name} gifted {giftType} Ultra subscription to {streamer}"). The gift
|
|
47
|
+
// type carries the subscription tier ("1000" / "2000" / "3000" / "prime")
|
|
48
|
+
// which Lumia exposes as `tier` on every sub-related alert payload.
|
|
49
|
+
giftType: "tier",
|
|
50
|
+
// TikTok-style jewel gift quantity — SL `jewel_gift_message_template`
|
|
51
|
+
// ("{name} gifted {giftName} x{jewelsAmount} jewels!"). Lumia's tiktok-gift
|
|
52
|
+
// alert exposes the quantity as `amount`. `{giftName}` (the gift's display
|
|
53
|
+
// name) doesn't have a 1:1 Lumia variable — TikTok's gift catalog isn't
|
|
54
|
+
// directly imported — so we leave it unmapped and the streamer can adjust
|
|
55
|
+
// the template in the Lumia editor.
|
|
56
|
+
jewelsAmount: "amount"
|
|
24
57
|
};
|
|
25
58
|
var TWITCH_CONTEXTS = {
|
|
26
59
|
"follower-latest": {
|
|
@@ -3752,9 +3785,9 @@ async function fetchWithProxyFallback(url, options = {}) {
|
|
|
3752
3785
|
}
|
|
3753
3786
|
|
|
3754
3787
|
// src/se-import/assets.ts
|
|
3755
|
-
var IMPORTABLE_CDN_REGEX = /https?:\/\/(?:(?:cdn|static)\.streamelements\.com|streamelements-cdn\.com|cdn\.streamlabs\.com|(?:cdn|uploads)\.twitchalerts\.com)\/[^\s"'\\)]+/g;
|
|
3788
|
+
var IMPORTABLE_CDN_REGEX = /https?:\/\/(?:(?:cdn|static)\.streamelements\.com|streamelements-cdn\.com|streamlabs\.com|cdn\.streamlabs\.com|(?:cdn|uploads)\.twitchalerts\.com)\/[^\s"'\\)]+/g;
|
|
3756
3789
|
var CSS_URL_REGEX = /url\(\s*['"]?([^'")]+)['"]?\s*\)/g;
|
|
3757
|
-
var IMPORTABLE_CDN_HOST_REGEX = /^https?:\/\/(?:(?:cdn|static)\.streamelements\.com|streamelements-cdn\.com|cdn\.streamlabs\.com|(?:cdn|uploads)\.twitchalerts\.com)\//;
|
|
3790
|
+
var IMPORTABLE_CDN_HOST_REGEX = /^https?:\/\/(?:(?:cdn|static)\.streamelements\.com|streamelements-cdn\.com|streamlabs\.com|cdn\.streamlabs\.com|(?:cdn|uploads)\.twitchalerts\.com)\//;
|
|
3758
3791
|
function isImportableAssetUrl(url) {
|
|
3759
3792
|
return IMPORTABLE_CDN_HOST_REGEX.test(url);
|
|
3760
3793
|
}
|
|
@@ -6479,7 +6512,7 @@ function absolutizeSLUrl(raw) {
|
|
|
6479
6512
|
if (typeof raw !== "string" || raw.length === 0) return "";
|
|
6480
6513
|
if (raw.startsWith("http://") || raw.startsWith("https://")) return raw;
|
|
6481
6514
|
if (raw.startsWith("//")) return `https:${raw}`;
|
|
6482
|
-
if (raw.startsWith("/")) return `https://
|
|
6515
|
+
if (raw.startsWith("/")) return `https://streamlabs.com${raw}`;
|
|
6483
6516
|
return raw;
|
|
6484
6517
|
}
|
|
6485
6518
|
function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
@@ -6490,13 +6523,7 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
6490
6523
|
const fontWeight = getField(settings, prefix, "font_weight") ?? 600;
|
|
6491
6524
|
const fontColor = getField(settings, prefix, "font_color") ?? "#FFFFFF";
|
|
6492
6525
|
const highlightColor = getField(settings, prefix, "font_color2") ?? "#32C3A6";
|
|
6493
|
-
const
|
|
6494
|
-
getField(settings, prefix, "message_font_size"),
|
|
6495
|
-
20
|
|
6496
|
-
);
|
|
6497
|
-
const messageFontFamily = getField(settings, prefix, "message_font") ?? fontFamily;
|
|
6498
|
-
const messageFontWeight = getField(settings, prefix, "message_font_weight") ?? 400;
|
|
6499
|
-
const messageFontColor = getField(settings, prefix, "message_font_color") ?? "#FFFFFF";
|
|
6526
|
+
const secondaryMessage = readSecondaryMessageConfig(settings, prefix, fontFamily);
|
|
6500
6527
|
const imageHref = absolutizeSLUrl(getField(settings, prefix, "image_href"));
|
|
6501
6528
|
const soundHref = absolutizeSLUrl(getField(settings, prefix, "sound_href"));
|
|
6502
6529
|
const soundVolume = getField(settings, prefix, "sound_volume") ?? 50;
|
|
@@ -6515,7 +6542,7 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
6515
6542
|
accentColor: null,
|
|
6516
6543
|
highlightColor,
|
|
6517
6544
|
firstMessageTemplate: translateSeText(messageTemplate),
|
|
6518
|
-
secondMessageTemplate: "",
|
|
6545
|
+
secondMessageTemplate: secondaryMessage?.template ?? "",
|
|
6519
6546
|
thirdMessageTemplate: "",
|
|
6520
6547
|
showAvatar: false,
|
|
6521
6548
|
showAmount: true,
|
|
@@ -6538,12 +6565,10 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
6538
6565
|
textShadow: "rgba(0, 0, 0, 0.8) 1px 1px 1px",
|
|
6539
6566
|
textAlign: "center"
|
|
6540
6567
|
},
|
|
6541
|
-
messageCss
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
fontWeight: messageFontWeight
|
|
6546
|
-
},
|
|
6568
|
+
// `messageCss` only matters when secondMessageTemplate is set;
|
|
6569
|
+
// leave it empty when SL didn't ship a secondary-message block
|
|
6570
|
+
// so Lumia's renderer falls back to its own default styling.
|
|
6571
|
+
messageCss: secondaryMessage?.css ?? {},
|
|
6547
6572
|
content: { value: translateSeText(messageTemplate) }
|
|
6548
6573
|
},
|
|
6549
6574
|
media: {
|
|
@@ -6586,6 +6611,36 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
6586
6611
|
variations: []
|
|
6587
6612
|
};
|
|
6588
6613
|
}
|
|
6614
|
+
var SECONDARY_MESSAGE_PREFIX_OVERRIDE = {
|
|
6615
|
+
sub: "resub"
|
|
6616
|
+
};
|
|
6617
|
+
function readSecondaryMessageConfig(settings, prefix, primaryFontFamily) {
|
|
6618
|
+
const secondaryPrefix = SECONDARY_MESSAGE_PREFIX_OVERRIDE[prefix] ?? prefix;
|
|
6619
|
+
const showKey = `show_${secondaryPrefix}_message`;
|
|
6620
|
+
const enabled = settings[showKey];
|
|
6621
|
+
if (enabled !== true) return null;
|
|
6622
|
+
const fontFamily = getField(settings, secondaryPrefix, "message_font") ?? primaryFontFamily;
|
|
6623
|
+
const fontSize = pxToNumber(
|
|
6624
|
+
getField(settings, secondaryPrefix, "message_font_size"),
|
|
6625
|
+
20
|
|
6626
|
+
);
|
|
6627
|
+
const fontWeight = getField(settings, secondaryPrefix, "message_font_weight") ?? 400;
|
|
6628
|
+
const fontColor = getField(settings, secondaryPrefix, "message_font_color") ?? "#FFFFFF";
|
|
6629
|
+
return {
|
|
6630
|
+
// `{message}` is the SE/SL chat-message token (mapped to Lumia's
|
|
6631
|
+
// `{{message}}` in translate.ts). It resolves at render time from
|
|
6632
|
+
// the alert payload's `message` field — populated for every event
|
|
6633
|
+
// where SL ships a secondary-message line (donations, resubs,
|
|
6634
|
+
// cheers, charity, merch, etc.).
|
|
6635
|
+
template: translateSeText("{message}"),
|
|
6636
|
+
css: {
|
|
6637
|
+
fontFamily,
|
|
6638
|
+
fontSize,
|
|
6639
|
+
color: fontColor,
|
|
6640
|
+
fontWeight
|
|
6641
|
+
}
|
|
6642
|
+
};
|
|
6643
|
+
}
|
|
6589
6644
|
function clampVolume(slVolume) {
|
|
6590
6645
|
if (typeof slVolume !== "number" || !Number.isFinite(slVolume)) return 0.5;
|
|
6591
6646
|
return Math.max(0, Math.min(1, slVolume / 100));
|