Release v2.2.0

This commit is contained in:
2026-08-01 21:41:44 +01:00
parent c643d2fb07
commit d6417b667c
673 changed files with 146752 additions and 7389 deletions
+109 -13
View File
@@ -1,5 +1,6 @@
const fs = require('fs');
const path = require('path');
const announcementIcons = require('#src/data/announcement-icons');
function mediaKind(mediaPath) {
const ext = path.extname(mediaPath || '').toLowerCase();
@@ -235,6 +236,17 @@ function renderEditorJsTable(data) {
return '<table class="ck-content-table">' + tableRows + '</table>';
}
function wrapRichTextParagraph(html) {
const raw = String(html || '').trim();
if (!raw) {
return '';
}
if (/^<\s*(?:p|div|h[1-6]|ul|ol|pre|table|blockquote|figure|hr|li)\b/i.test(raw)) {
return raw;
}
return '<p>' + raw + '</p>';
}
function renderEditorJsContent(value) {
if (value && typeof value === 'object') {
if (Array.isArray(value.blocks)) {
@@ -253,7 +265,7 @@ function renderEditorJsContent(value) {
} catch (_error) {
// fall through to legacy HTML rendering
}
return sanitizeRichText(raw);
return wrapRichTextParagraph(sanitizeRichText(raw));
}
function renderHtmlRegionContent(value) {
@@ -283,17 +295,13 @@ const playerPagePlaylistScriptPath = path.join(__dirname, 'public', 'js', 'playe
const playerPageCommandsScriptPath = path.join(__dirname, 'public', 'js', 'player-page-commands.js');
const playerPageRenderingScriptPath = path.join(__dirname, 'public', 'js', 'player-page-rendering.js');
const playerPagePlaybackScriptPath = path.join(__dirname, 'public', 'js', 'player-page-playback.js');
const playerAnnouncementTemplatesScriptPath = path.join(__dirname, 'public', 'js', 'player-announcement-templates.js');
const playerAnnouncementLowerThirdTemplatePath = path.join(__dirname, 'announcement-templates', 'lower-third.template.html');
const playerAnnouncementTopBannerTemplatePath = path.join(__dirname, 'announcement-templates', 'top-banner.template.html');
const playerAnnouncementFullscreenTemplatePath = path.join(__dirname, 'announcement-templates', 'fullscreen.template.html');
const playerPageAnnouncementsScriptPath = path.join(__dirname, 'player-page-announcements.js');
const playerPageScriptPath = path.join(__dirname, 'player-page.script.html');
const playerRegionScriptPaths = [
path.join(__dirname, 'regions', 'image.js'),
path.join(__dirname, 'regions', 'video.js'),
path.join(__dirname, 'regions', 'webpage.js'),
path.join(__dirname, 'regions', 'html.js'),
path.join(__dirname, 'regions', 'rtmp.js'),
path.join(__dirname, 'regions', 'rss.js'),
path.join(__dirname, 'regions', 'api.js'),
path.join(__dirname, 'regions', 'text.js')
];
const playerRegionScriptDir = path.join(__dirname, 'regions');
const playerOnboardingLandingScriptPath = path.join(__dirname, 'onboarding', 'player-onboarding-landing.script.html');
const playerOnboardingFormScriptPath = path.join(__dirname, 'onboarding', 'player-onboarding-form.script.html');
let playerPageTemplateCache = null;
@@ -303,6 +311,9 @@ let playerPagePlaylistScriptCache = null;
let playerPageCommandsScriptCache = null;
let playerPageRenderingScriptCache = null;
let playerPagePlaybackScriptCache = null;
let playerAnnouncementTemplatesScriptCache = null;
let playerAnnouncementTemplatesDataScriptCache = null;
let playerPageAnnouncementsScriptCache = null;
let playerPageScriptCache = null;
let playerRegionScriptsCache = null;
let playerOnboardingLandingScriptCache = null;
@@ -347,19 +358,100 @@ function getPlayerPagePlaybackScript() {
return loadTemplate(playerPagePlaybackScriptPath, playerPagePlaybackScriptCache || (playerPagePlaybackScriptCache = {}));
}
function getPlayerAnnouncementTemplatesScript() {
if (playerAnnouncementTemplatesScriptCache && playerAnnouncementTemplatesScriptCache.path === playerAnnouncementTemplatesScriptPath) {
return playerAnnouncementTemplatesScriptCache.value;
}
const value = fs.readFileSync(playerAnnouncementTemplatesScriptPath, 'utf8').trim();
playerAnnouncementTemplatesScriptCache = {
path: playerAnnouncementTemplatesScriptPath,
value: value
};
return value;
}
function getAnnouncementIconsDataScript() {
return [
'(function () {',
' window.pulseAnnouncementIconKeys = ' + safeJsonForScript(announcementIcons.ANNOUNCEMENT_ICON_KEYS) + ';',
' window.pulseAnnouncementDefaultIconKey = ' + safeJsonForScript(announcementIcons.DEFAULT_ANNOUNCEMENT_ICON) + ';',
'}());'
].join('\n');
}
function loadAnnouncementTemplate(filePath) {
return fs.readFileSync(filePath, 'utf8').trim();
}
function getPlayerAnnouncementTemplatesDataScript() {
const templatePaths = [
playerAnnouncementLowerThirdTemplatePath,
playerAnnouncementTopBannerTemplatePath,
playerAnnouncementFullscreenTemplatePath
];
const signature = templatePaths.map(function (filePath) {
return fs.statSync(filePath).mtimeMs;
}).join('|');
if (playerAnnouncementTemplatesDataScriptCache && playerAnnouncementTemplatesDataScriptCache.signature === signature) {
return playerAnnouncementTemplatesDataScriptCache.value;
}
const value = [
'(function () {',
' window.playerAnnouncementTemplates = {',
' lowerThird: ' + safeJsonForScript(loadAnnouncementTemplate(playerAnnouncementLowerThirdTemplatePath)) + ',',
' topBanner: ' + safeJsonForScript(loadAnnouncementTemplate(playerAnnouncementTopBannerTemplatePath)) + ',',
' fullscreen: ' + safeJsonForScript(loadAnnouncementTemplate(playerAnnouncementFullscreenTemplatePath)),
' };',
'}());'
].join('\n');
playerAnnouncementTemplatesDataScriptCache = {
signature: signature,
value: value
};
return value;
}
function getPlayerPageAnnouncementsScript() {
return loadTemplate(playerPageAnnouncementsScriptPath, playerPageAnnouncementsScriptCache || (playerPageAnnouncementsScriptCache = {}));
}
function getPlayerPageScript() {
return loadTemplate(playerPageScriptPath, playerPageScriptCache || (playerPageScriptCache = {}));
}
function getPlayerRegionScriptPaths() {
if (!fs.existsSync(playerRegionScriptDir)) {
return [];
}
return fs.readdirSync(playerRegionScriptDir, { withFileTypes: true })
.filter(function (entry) {
return entry.isFile() && entry.name.toLowerCase().endsWith('.js');
})
.map(function (entry) {
return path.join(playerRegionScriptDir, entry.name);
})
.sort(function (left, right) {
return left.localeCompare(right);
});
}
function getPlayerRegionScripts() {
const statSignature = playerRegionScriptPaths.map(function (filePath) {
const sharedPlaceholderUtilsPath = path.join(__dirname, '..', 'web', 'public', 'js', 'shared', 'placeholder-utils.js');
const playerRegionScriptPaths = getPlayerRegionScriptPaths();
const scriptPaths = [sharedPlaceholderUtilsPath].concat(playerRegionScriptPaths);
const statSignature = scriptPaths.map(function (filePath) {
return fs.statSync(filePath).mtimeMs;
}).join('|');
if (playerRegionScriptsCache && playerRegionScriptsCache.signature === statSignature) {
return playerRegionScriptsCache.value;
}
const value = playerRegionScriptPaths.map(function (filePath) {
const value = scriptPaths.map(function (filePath) {
return fs.readFileSync(filePath, 'utf8').trim();
}).join('\n\n');
playerRegionScriptsCache = {
@@ -403,6 +495,10 @@ module.exports = {
getPlayerPageCommandsScript: getPlayerPageCommandsScript,
getPlayerPageRenderingScript: getPlayerPageRenderingScript,
getPlayerPagePlaybackScript: getPlayerPagePlaybackScript,
getAnnouncementIconsDataScript: getAnnouncementIconsDataScript,
getPlayerAnnouncementTemplatesDataScript: getPlayerAnnouncementTemplatesDataScript,
getPlayerAnnouncementTemplatesScript: getPlayerAnnouncementTemplatesScript,
getPlayerPageAnnouncementsScript: getPlayerPageAnnouncementsScript,
getPlayerPageScript: getPlayerPageScript,
getPlayerRegionScripts: getPlayerRegionScripts,
getPlayerOnboardingLandingScript: getPlayerOnboardingLandingScript,