Release 2.7.2
Publish Docker Image / build-and-push (./build/Dockerfile, git.lzstealth.com/lzstealth/pulse-signage-web, web) (push) Successful in 1m16s
Publish Docker Image / build-and-push (./build/Dockerfile.player, git.lzstealth.com/lzstealth/pulse-signage-player, player) (push) Successful in 32s
Publish Docker Image / build-and-push (./build/Dockerfile, git.lzstealth.com/lzstealth/pulse-signage-web, web) (push) Successful in 1m16s
Publish Docker Image / build-and-push (./build/Dockerfile.player, git.lzstealth.com/lzstealth/pulse-signage-player, player) (push) Successful in 32s
This commit is contained in:
@@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## 2.7.2 - 2026-08-14
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- HTML and webpage region previews now normalize object-shaped content before rendering, so the player, thumbnails, and popup preview show the intended iframe content instead of leaking raw objects.
|
||||||
|
- HTML and webpage preview iframes now size explicitly to the full region bounds in the player, thumbnails, and popup preview.
|
||||||
|
|
||||||
## 2.7.1 - 2026-08-14
|
## 2.7.1 - 2026-08-14
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pulse-signage-player",
|
"name": "pulse-signage-player",
|
||||||
"version": "2.7.1",
|
"version": "2.7.2",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "Pulse Signage player application bundle",
|
"description": "Pulse Signage player application bundle",
|
||||||
"main": "src/common.js",
|
"main": "src/common.js",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pulse-signage-web",
|
"name": "pulse-signage-web",
|
||||||
"version": "2.7.1",
|
"version": "2.7.2",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "Pulse Signage web and bridge application bundle",
|
"description": "Pulse Signage web and bridge application bundle",
|
||||||
"main": "src/common.js",
|
"main": "src/common.js",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pulse-signage",
|
"name": "pulse-signage",
|
||||||
"version": "2.7.1",
|
"version": "2.7.2",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "Pulse Signage application with MySQL and media storage",
|
"description": "Pulse Signage application with MySQL and media storage",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -2,16 +2,49 @@
|
|||||||
|
|
||||||
var registry = window.pulsePlayerRegionTypes;
|
var registry = window.pulsePlayerRegionTypes;
|
||||||
|
|
||||||
|
function normalizeRenderableValue(value) {
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
if (value.value !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.value);
|
||||||
|
}
|
||||||
|
if (value.text !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.text);
|
||||||
|
}
|
||||||
|
if (value.html !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.html);
|
||||||
|
}
|
||||||
|
if (value.content !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.content);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(value === undefined || value === null ? '' : value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildHtmlDocument(html) {
|
||||||
|
var raw = String(html || '').trim();
|
||||||
|
if (!raw) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^<!doctype\b/i.test(raw) || /^<html\b/i.test(raw)) {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<!doctype html><html><head><style>html,body{margin:0;width:100%;height:100%;overflow:hidden;background:transparent;}</style></head><body>' + raw + '</body></html>';
|
||||||
|
}
|
||||||
|
|
||||||
function renderHtmlRegionContent(value) {
|
function renderHtmlRegionContent(value) {
|
||||||
var html = String(value || '').trim();
|
var html = normalizeRenderableValue(value).trim();
|
||||||
if (!html) {
|
if (!html) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return '<iframe class="template-region-html-frame" sandbox="" scrolling="no" srcdoc="<!doctype html><html><head><style>html,body{margin:0;width:100%;height:100%;overflow:hidden;background:transparent;}</style></head><body>' + escapeHtml(html) + '</body></html>" title="HTML region" loading="eager"></iframe>';
|
return '<iframe class="template-region-html-frame" sandbox="" scrolling="no" srcdoc="' + escapeHtml(buildHtmlDocument(html)) + '" title="HTML region" loading="eager" style="width:100%;height:100%;border:0;display:block;background:transparent;overflow:hidden;"></iframe>';
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderHtmlRegion(region, regionContent) {
|
function renderHtmlRegion(region, regionContent) {
|
||||||
return '<div class="template-region html" style="' + region.baseStyle + '">' + renderHtmlRegionContent(regionContent.value || '') + '</div>';
|
return '<div class="template-region html" style="' + region.baseStyle + '">' + renderHtmlRegionContent(regionContent && regionContent.value !== undefined ? regionContent.value : '') + '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
registry.register('html', {
|
registry.register('html', {
|
||||||
|
|||||||
@@ -2,12 +2,38 @@
|
|||||||
|
|
||||||
var registry = window.pulsePlayerRegionTypes;
|
var registry = window.pulsePlayerRegionTypes;
|
||||||
|
|
||||||
|
function normalizeRenderableValue(value) {
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
if (value.value !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.value);
|
||||||
|
}
|
||||||
|
if (value.text !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.text);
|
||||||
|
}
|
||||||
|
if (value.url !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.url);
|
||||||
|
}
|
||||||
|
if (value.href !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.href);
|
||||||
|
}
|
||||||
|
if (value.src !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.src);
|
||||||
|
}
|
||||||
|
if (value.content !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.content);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(value === undefined || value === null ? '' : value);
|
||||||
|
}
|
||||||
|
|
||||||
function renderWebpageRegion(region, regionContent) {
|
function renderWebpageRegion(region, regionContent) {
|
||||||
var url = String(regionContent.value || '').trim();
|
var url = normalizeRenderableValue(regionContent && regionContent.value !== undefined ? regionContent.value : '').trim();
|
||||||
if (!url) {
|
if (!url) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return '<div class="template-region webpage" style="' + region.baseStyle + '"><iframe src="' + escapeHtml(url) + '" title="' + escapeHtml(region.label) + '" loading="eager" referrerpolicy="no-referrer" scrolling="no"></iframe></div>';
|
return '<div class="template-region webpage" style="' + region.baseStyle + '"><iframe src="' + escapeHtml(url) + '" title="' + escapeHtml(region.label) + '" loading="eager" referrerpolicy="no-referrer" scrolling="no" style="width:100%;height:100%;border:0;display:block;background:#fff;overflow:hidden;"></iframe></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
registry.register('webpage', {
|
registry.register('webpage', {
|
||||||
|
|||||||
@@ -279,12 +279,45 @@ function renderEditorJsContent(value) {
|
|||||||
return wrapRichTextParagraph(sanitizeRichText(raw));
|
return wrapRichTextParagraph(sanitizeRichText(raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildHtmlDocument(html) {
|
||||||
|
const raw = String(html || '').trim();
|
||||||
|
if (!raw) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^<!doctype\b/i.test(raw) || /^<html\b/i.test(raw)) {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<!doctype html><html><head><style>html,body{margin:0;width:100%;height:100%;overflow:hidden;background:transparent;}</style></head><body>' + raw + '</body></html>';
|
||||||
|
}
|
||||||
|
|
||||||
function renderHtmlRegionContent(value) {
|
function renderHtmlRegionContent(value) {
|
||||||
const html = String(value || '').trim();
|
const html = normalizeRenderableValue(value).trim();
|
||||||
if (!html) {
|
if (!html) {
|
||||||
return '<div class="template-region-placeholder">HTML</div>';
|
return '<div class="template-region-placeholder">HTML</div>';
|
||||||
}
|
}
|
||||||
return '<iframe class="template-region-html-frame" sandbox="" srcdoc="' + escapeHtml(html) + '" title="HTML region" loading="eager"></iframe>';
|
return '<iframe class="template-region-html-frame" sandbox="" srcdoc="' + escapeHtml(buildHtmlDocument(html)) + '" title="HTML region" loading="eager" style="width:100%;height:100%;border:0;display:block;background:transparent;overflow:hidden;"></iframe>';
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeRenderableValue(value) {
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
if (value.value !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.value);
|
||||||
|
}
|
||||||
|
if (value.text !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.text);
|
||||||
|
}
|
||||||
|
if (value.html !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.html);
|
||||||
|
}
|
||||||
|
if (value.content !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.content);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(value === undefined || value === null ? '' : value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function fitCanvasSize(canvasWidth, canvasHeight, maxWidth, maxHeight) {
|
function fitCanvasSize(canvasWidth, canvasHeight, maxWidth, maxHeight) {
|
||||||
|
|||||||
@@ -30,6 +30,35 @@ function resolveAssetUrl(baseUrl, value) {
|
|||||||
return normalizedBaseUrl + '/' + raw.replace(/^\/+/, '');
|
return normalizedBaseUrl + '/' + raw.replace(/^\/+/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeRenderableValue(value) {
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
if (value.value !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.value);
|
||||||
|
}
|
||||||
|
if (value.text !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.text);
|
||||||
|
}
|
||||||
|
if (value.html !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.html);
|
||||||
|
}
|
||||||
|
if (value.url !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.url);
|
||||||
|
}
|
||||||
|
if (value.href !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.href);
|
||||||
|
}
|
||||||
|
if (value.src !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.src);
|
||||||
|
}
|
||||||
|
if (value.content !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.content);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(value === undefined || value === null ? '' : value);
|
||||||
|
}
|
||||||
|
|
||||||
function getThumbnailCanvasSize(slide) {
|
function getThumbnailCanvasSize(slide) {
|
||||||
const template = slide && slide.template ? slide.template : null;
|
const template = slide && slide.template ? slide.template : null;
|
||||||
return {
|
return {
|
||||||
@@ -79,7 +108,7 @@ function buildTextRegionMarkup(region, regionContent) {
|
|||||||
|
|
||||||
function buildRegionInnerHtml(region, regionContent, baseUrl) {
|
function buildRegionInnerHtml(region, regionContent, baseUrl) {
|
||||||
const regionType = String(regionContent.type || region.region_type || 'text').trim().toLowerCase();
|
const regionType = String(regionContent.type || region.region_type || 'text').trim().toLowerCase();
|
||||||
const rawValue = regionContent && regionContent.value !== undefined ? regionContent.value : '';
|
const rawValue = normalizeRenderableValue(regionContent && regionContent.value !== undefined ? regionContent.value : '');
|
||||||
|
|
||||||
if (regionType === 'image') {
|
if (regionType === 'image') {
|
||||||
const src = resolveAssetUrl(baseUrl, rawValue);
|
const src = resolveAssetUrl(baseUrl, rawValue);
|
||||||
@@ -98,7 +127,7 @@ function buildRegionInnerHtml(region, regionContent, baseUrl) {
|
|||||||
if (regionType === 'webpage') {
|
if (regionType === 'webpage') {
|
||||||
const src = resolveAssetUrl(baseUrl, rawValue);
|
const src = resolveAssetUrl(baseUrl, rawValue);
|
||||||
return src
|
return src
|
||||||
? '<div class="slide-preview-region slide-preview-webpage-region" style="' + region.baseStyle + '"><iframe src="' + escapeHtml(src) + '" title="' + escapeHtml(region.label || region.region_key || 'webpage') + '" loading="eager" referrerpolicy="no-referrer" scrolling="no"></iframe></div>'
|
? '<div class="slide-preview-region slide-preview-webpage-region" style="' + region.baseStyle + '"><iframe src="' + escapeHtml(src) + '" title="' + escapeHtml(region.label || region.region_key || 'webpage') + '" loading="eager" referrerpolicy="no-referrer" scrolling="no" style="width:100%;height:100%;border:0;display:block;background:#fff;overflow:hidden;"></iframe></div>'
|
||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +143,7 @@ function buildRegionInnerHtml(region, regionContent, baseUrl) {
|
|||||||
if (regionType === 'html') {
|
if (regionType === 'html') {
|
||||||
const html = String(rawValue || '').trim();
|
const html = String(rawValue || '').trim();
|
||||||
return html
|
return html
|
||||||
? '<div class="slide-preview-region slide-preview-html-region" style="' + region.baseStyle + '"><iframe sandbox="" srcdoc="<!doctype html><html><head><style>html,body{margin:0;width:100%;height:100%;overflow:hidden;background:transparent;}</style></head><body>' + escapeHtml(html) + '</body></html>" title="' + escapeHtml(region.label || region.region_key || 'html') + '" loading="eager" scrolling="no"></iframe></div>'
|
? '<div class="slide-preview-region slide-preview-html-region" style="' + region.baseStyle + '"><iframe sandbox="" allowtransparency="true" srcdoc="' + escapeHtml('<!doctype html><html><head><style>html,body{margin:0;width:100%;height:100%;overflow:hidden;background:transparent;}</style></head><body>' + html + '</body></html>') + '" title="' + escapeHtml(region.label || region.region_key || 'html') + '" loading="eager" scrolling="no" style="width:100%;height:100%;border:0;display:block;background:transparent;overflow:hidden;"></iframe></div>'
|
||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,35 @@ function resolveAssetUrl(baseUrl, value) {
|
|||||||
return normalizedBaseUrl + '/' + raw.replace(/^\/+/, '');
|
return normalizedBaseUrl + '/' + raw.replace(/^\/+/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeRenderableValue(value) {
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
if (value.value !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.value);
|
||||||
|
}
|
||||||
|
if (value.text !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.text);
|
||||||
|
}
|
||||||
|
if (value.html !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.html);
|
||||||
|
}
|
||||||
|
if (value.url !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.url);
|
||||||
|
}
|
||||||
|
if (value.href !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.href);
|
||||||
|
}
|
||||||
|
if (value.src !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.src);
|
||||||
|
}
|
||||||
|
if (value.content !== undefined) {
|
||||||
|
return normalizeRenderableValue(value.content);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(value === undefined || value === null ? '' : value);
|
||||||
|
}
|
||||||
|
|
||||||
function getCanvasSize(slide) {
|
function getCanvasSize(slide) {
|
||||||
const template = slide && slide.template ? slide.template : null;
|
const template = slide && slide.template ? slide.template : null;
|
||||||
return {
|
return {
|
||||||
@@ -109,7 +138,7 @@ function buildTextRegionMarkup(region, regionContent) {
|
|||||||
|
|
||||||
function buildRegionInnerHtml(region, regionContent, baseUrl) {
|
function buildRegionInnerHtml(region, regionContent, baseUrl) {
|
||||||
const regionType = String(regionContent.type || region.region_type || 'text').trim().toLowerCase();
|
const regionType = String(regionContent.type || region.region_type || 'text').trim().toLowerCase();
|
||||||
const rawValue = regionContent && regionContent.value !== undefined ? regionContent.value : '';
|
const rawValue = normalizeRenderableValue(regionContent && regionContent.value !== undefined ? regionContent.value : '');
|
||||||
|
|
||||||
if (regionType === 'image') {
|
if (regionType === 'image') {
|
||||||
const src = resolveAssetUrl(baseUrl, rawValue);
|
const src = resolveAssetUrl(baseUrl, rawValue);
|
||||||
@@ -128,7 +157,7 @@ function buildRegionInnerHtml(region, regionContent, baseUrl) {
|
|||||||
if (regionType === 'webpage') {
|
if (regionType === 'webpage') {
|
||||||
const src = resolveAssetUrl(baseUrl, rawValue);
|
const src = resolveAssetUrl(baseUrl, rawValue);
|
||||||
return src
|
return src
|
||||||
? '<div class="slide-preview-region slide-preview-webpage-region" style="' + region.baseStyle + '"><iframe src="' + escapeHtml(src) + '" title="' + escapeHtml(region.label || region.region_key || 'webpage') + '" loading="eager" referrerpolicy="no-referrer" scrolling="no"></iframe></div>'
|
? '<div class="slide-preview-region slide-preview-webpage-region" style="' + region.baseStyle + '"><iframe src="' + escapeHtml(src) + '" title="' + escapeHtml(region.label || region.region_key || 'webpage') + '" loading="eager" referrerpolicy="no-referrer" scrolling="no" style="width:100%;height:100%;border:0;display:block;background:#fff;overflow:hidden;"></iframe></div>'
|
||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +173,7 @@ function buildRegionInnerHtml(region, regionContent, baseUrl) {
|
|||||||
if (regionType === 'html') {
|
if (regionType === 'html') {
|
||||||
const html = String(rawValue || '').trim();
|
const html = String(rawValue || '').trim();
|
||||||
return html
|
return html
|
||||||
? '<div class="slide-preview-region slide-preview-html-region" style="' + region.baseStyle + '"><iframe sandbox="" srcdoc="<!doctype html><html><head><style>html,body{margin:0;width:100%;height:100%;overflow:hidden;background:transparent;}</style></head><body>' + escapeHtml(html) + '</body></html>" title="' + escapeHtml(region.label || region.region_key || 'html') + '" loading="eager" scrolling="no"></iframe></div>'
|
? '<div class="slide-preview-region slide-preview-html-region" style="' + region.baseStyle + '"><iframe sandbox="" allowtransparency="true" srcdoc="' + escapeHtml('<!doctype html><html><head><style>html,body{margin:0;width:100%;height:100%;overflow:hidden;background:transparent;}</style></head><body>' + html + '</body></html>') + '" title="' + escapeHtml(region.label || region.region_key || 'html') + '" loading="eager" scrolling="no" style="width:100%;height:100%;border:0;display:block;background:transparent;overflow:hidden;"></iframe></div>'
|
||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,49 @@
|
|||||||
return utils.escapeHtml ? utils.escapeHtml(value) : String(value === undefined || value === null ? '' : value);
|
return utils.escapeHtml ? utils.escapeHtml(value) : String(value === undefined || value === null ? '' : value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderPreview(value) {
|
function normalizePreviewValue(value) {
|
||||||
var content = value && typeof value === 'object' && value.value !== undefined ? value : null;
|
if (value && typeof value === 'object') {
|
||||||
var html = String(content ? content.value : value || '').trim();
|
if (value.value !== undefined) {
|
||||||
|
return normalizePreviewValue(value.value);
|
||||||
|
}
|
||||||
|
if (value.text !== undefined) {
|
||||||
|
return normalizePreviewValue(value.text);
|
||||||
|
}
|
||||||
|
if (value.html !== undefined) {
|
||||||
|
return normalizePreviewValue(value.html);
|
||||||
|
}
|
||||||
|
if (value.content !== undefined) {
|
||||||
|
return normalizePreviewValue(value.content);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(value === undefined || value === null ? '' : value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildHtmlDocument(html) {
|
||||||
|
var raw = String(html || '').trim();
|
||||||
|
if (!raw) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^<!doctype\b/i.test(raw) || /^<html\b/i.test(raw)) {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<!doctype html><html><head><style>html,body{margin:0;width:100%;height:100%;overflow:hidden;background:transparent;}</style></head><body>' + raw + '</body></html>';
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPreview(region, value) {
|
||||||
|
var html = normalizePreviewValue(value !== undefined ? value : region).trim();
|
||||||
if (!html) {
|
if (!html) {
|
||||||
return '<div class="slide-preview-placeholder">HTML</div>';
|
return '<div class="slide-preview-placeholder">HTML</div>';
|
||||||
}
|
}
|
||||||
return '<iframe class="slide-preview-html-frame" sandbox="" scrolling="no" srcdoc="<!doctype html><html><head><style>html,body{margin:0;width:100%;height:100%;overflow:hidden;background:transparent;}</style></head><body>' + escapeHtml(html) + '</body></html>" title="HTML preview" loading="eager" style="width:100%;height:100%;border:0;display:block;background:transparent;overflow:hidden;"></iframe>';
|
if (/^<!doctype\b/i.test(html) || /^<html\b/i.test(html)) {
|
||||||
|
return '<iframe class="slide-preview-html-frame" sandbox="" allowtransparency="true" scrolling="no" srcdoc="' + escapeHtml(buildHtmlDocument(html)) + '" title="HTML preview" loading="eager" style="width:100%;height:100%;border:0;display:block;background:transparent;overflow:hidden;"></iframe>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<div class="slide-preview-html-frame" style="width:100%;height:100%;overflow:hidden;background:transparent;">' + html + '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderEditorCard(context) {
|
function renderEditorCard(context) {
|
||||||
|
|||||||
@@ -8,9 +8,34 @@
|
|||||||
return utils.escapeHtml ? utils.escapeHtml(value) : String(value === undefined || value === null ? '' : value);
|
return utils.escapeHtml ? utils.escapeHtml(value) : String(value === undefined || value === null ? '' : value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderPreview(value) {
|
function normalizePreviewValue(value) {
|
||||||
var content = value && typeof value === 'object' && value.value !== undefined ? value : null;
|
if (value && typeof value === 'object') {
|
||||||
var src = String(content ? content.value : value || '').trim();
|
if (value.value !== undefined) {
|
||||||
|
return normalizePreviewValue(value.value);
|
||||||
|
}
|
||||||
|
if (value.text !== undefined) {
|
||||||
|
return normalizePreviewValue(value.text);
|
||||||
|
}
|
||||||
|
if (value.url !== undefined) {
|
||||||
|
return normalizePreviewValue(value.url);
|
||||||
|
}
|
||||||
|
if (value.href !== undefined) {
|
||||||
|
return normalizePreviewValue(value.href);
|
||||||
|
}
|
||||||
|
if (value.src !== undefined) {
|
||||||
|
return normalizePreviewValue(value.src);
|
||||||
|
}
|
||||||
|
if (value.content !== undefined) {
|
||||||
|
return normalizePreviewValue(value.content);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(value === undefined || value === null ? '' : value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPreview(region, value) {
|
||||||
|
var src = normalizePreviewValue(value !== undefined ? value : region).trim();
|
||||||
if (!src) {
|
if (!src) {
|
||||||
return '<div class="slide-preview-placeholder">Webpage</div>';
|
return '<div class="slide-preview-placeholder">Webpage</div>';
|
||||||
}
|
}
|
||||||
@@ -24,7 +49,10 @@
|
|||||||
region: region,
|
region: region,
|
||||||
headerActions: '<span class="chip">Webpage</span>',
|
headerActions: '<span class="chip">Webpage</span>',
|
||||||
bodyHtml: '' +
|
bodyHtml: '' +
|
||||||
'<input type="url" name="region_webpage_' + region.id + '" class="form-control" value="' + escapeHtml(current) + '" placeholder="https://example.com" />'
|
'<div class="input-group flex-nowrap">' +
|
||||||
|
'<input type="url" name="region_webpage_' + region.id + '" class="form-control" value="' + escapeHtml(current) + '" placeholder="https://example.com" />' +
|
||||||
|
'<button type="button" class="btn btn-outline-secondary text-nowrap" data-webpage-preview-update data-region-id="' + region.id + '">Update</button>' +
|
||||||
|
'</div>'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -825,6 +825,16 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
templateFields.querySelectorAll('input[type="url"][name^="region_webpage_"]').forEach(function (input) {
|
||||||
|
input.addEventListener('input', function () {
|
||||||
|
templateSelectorLock.markEdited();
|
||||||
|
});
|
||||||
|
|
||||||
|
input.addEventListener('change', function () {
|
||||||
|
templateSelectorLock.markEdited();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
if (existingTemplateId && hasExistingSlideContent()) {
|
if (existingTemplateId && hasExistingSlideContent()) {
|
||||||
templateSelectorLock.arm();
|
templateSelectorLock.arm();
|
||||||
templateSelectorLock.markEdited();
|
templateSelectorLock.markEdited();
|
||||||
@@ -880,18 +890,42 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
|
|||||||
|
|
||||||
templateSelect.addEventListener('change', renderTemplate);
|
templateSelect.addEventListener('change', renderTemplate);
|
||||||
templateFields.addEventListener('change', function () {
|
templateFields.addEventListener('change', function () {
|
||||||
|
var webpageInput = event.target && typeof event.target.matches === 'function' && event.target.matches('input[type="url"][name^="region_webpage_"]');
|
||||||
|
if (webpageInput) {
|
||||||
|
templateSelectorLock.arm();
|
||||||
|
templateSelectorLock.markEdited();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
templateSelectorLock.arm();
|
templateSelectorLock.arm();
|
||||||
templateSelectorLock.markEdited();
|
templateSelectorLock.markEdited();
|
||||||
requestPreviewRender();
|
requestPreviewRender();
|
||||||
});
|
});
|
||||||
templateFields.addEventListener('input', function () {
|
templateFields.addEventListener('input', function () {
|
||||||
|
var webpageInput = event.target && typeof event.target.matches === 'function' && event.target.matches('input[type="url"][name^="region_webpage_"]');
|
||||||
|
if (webpageInput) {
|
||||||
|
templateSelectorLock.arm();
|
||||||
|
templateSelectorLock.markEdited();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
templateSelectorLock.arm();
|
templateSelectorLock.arm();
|
||||||
templateSelectorLock.markEdited();
|
templateSelectorLock.markEdited();
|
||||||
requestPreviewRender();
|
requestPreviewRender();
|
||||||
});
|
});
|
||||||
templateFields.addEventListener('click', function (event) {
|
templateFields.addEventListener('click', function (event) {
|
||||||
var button = event.target && typeof event.target.closest === 'function' ? event.target.closest('[data-api-items-path-reset]') : null;
|
var button = event.target && typeof event.target.closest === 'function' ? event.target.closest('[data-api-items-path-reset]') : null;
|
||||||
|
var webpageUpdateButton = event.target && typeof event.target.closest === 'function' ? event.target.closest('[data-webpage-preview-update]') : null;
|
||||||
if (!button) {
|
if (!button) {
|
||||||
|
if (!webpageUpdateButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (webpageUpdateButton) {
|
||||||
|
templateSelectorLock.arm();
|
||||||
|
templateSelectorLock.markEdited();
|
||||||
|
requestPreviewRender();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,22 @@
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#popup-preview-canvas iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: 0;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-preview-canvas .slide-preview-webpage-region iframe {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup-preview-canvas .slide-preview-html-region iframe {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
.slide-preview-text-content {
|
.slide-preview-text-content {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const {
|
|||||||
mediaKind,
|
mediaKind,
|
||||||
normalizeSlide,
|
normalizeSlide,
|
||||||
renderEditorJsContent,
|
renderEditorJsContent,
|
||||||
|
renderHtmlRegionContent,
|
||||||
sanitizeRichText
|
sanitizeRichText
|
||||||
} = require('../src/player/render-helpers');
|
} = require('../src/player/render-helpers');
|
||||||
|
|
||||||
@@ -86,4 +87,27 @@ test('renderEditorJsContent sanitizes editor blocks and wraps legacy text', () =
|
|||||||
test('timetable region registers the timetable type', () => {
|
test('timetable region registers the timetable type', () => {
|
||||||
assert.ok(timetableRegionSource.includes("registry.register('timetable'"));
|
assert.ok(timetableRegionSource.includes("registry.register('timetable'"));
|
||||||
assert.ok(timetableRegionSource.includes("sanitizeRichText(substituteTimetableVariables(value"));
|
assert.ok(timetableRegionSource.includes("sanitizeRichText(substituteTimetableVariables(value"));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('shared iframe renderers size preview content explicitly', () => {
|
||||||
|
const playerHtmlRegionSource = fs.readFileSync(require.resolve('../src/player/regions/html.js'), 'utf8');
|
||||||
|
const playerWebpageRegionSource = fs.readFileSync(require.resolve('../src/player/regions/webpage.js'), 'utf8');
|
||||||
|
const playerRenderHelpersSource = fs.readFileSync(require.resolve('../src/player/render-helpers.js'), 'utf8');
|
||||||
|
const slideThumbnailPreviewSource = fs.readFileSync(require.resolve('../src/web/lib/media/slide-thumbnail-preview.js'), 'utf8');
|
||||||
|
const slideThumbnailsSource = fs.readFileSync(require.resolve('../src/web/lib/media/slide-thumbnails.js'), 'utf8');
|
||||||
|
|
||||||
|
assert.ok(playerHtmlRegionSource.includes('style="width:100%;height:100%;border:0;display:block;background:transparent;overflow:hidden;"'));
|
||||||
|
assert.ok(playerWebpageRegionSource.includes('style="width:100%;height:100%;border:0;display:block;background:#fff;overflow:hidden;"'));
|
||||||
|
assert.ok(playerRenderHelpersSource.includes('style="width:100%;height:100%;border:0;display:block;background:transparent;overflow:hidden;"'));
|
||||||
|
assert.ok(slideThumbnailPreviewSource.includes('style="width:100%;height:100%;border:0;display:block;background:#fff;overflow:hidden;"'));
|
||||||
|
assert.ok(slideThumbnailPreviewSource.includes('style="width:100%;height:100%;border:0;display:block;background:transparent;overflow:hidden;"'));
|
||||||
|
assert.ok(slideThumbnailsSource.includes('style="width:100%;height:100%;border:0;display:block;background:#fff;overflow:hidden;"'));
|
||||||
|
assert.ok(slideThumbnailsSource.includes('style="width:100%;height:100%;border:0;display:block;background:transparent;overflow:hidden;"'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('html region helpers unwrap object-shaped values before rendering', () => {
|
||||||
|
const rendered = renderHtmlRegionContent({ html: '<div>Hi</div>' });
|
||||||
|
|
||||||
|
assert.match(rendered, /srcdoc="<!doctype html><html><head><style>html,body\{margin:0;width:100%;height:100%;overflow:hidden;background:transparent;\}<\/style><\/head><body><div>Hi<\/div><\/body><\/html>"/);
|
||||||
|
assert.doesNotMatch(rendered, /\[object Object\]/);
|
||||||
});
|
});
|
||||||
@@ -6,6 +6,8 @@ const slideFormEditorSource = fs.readFileSync(require.resolve('../src/web/public
|
|||||||
const slideFormSource = fs.readFileSync(require.resolve('../src/web/public/js/slides/slide-form.js'), 'utf8');
|
const slideFormSource = fs.readFileSync(require.resolve('../src/web/public/js/slides/slide-form.js'), 'utf8');
|
||||||
const slideThumbnailPreviewSource = fs.readFileSync(require.resolve('../src/web/lib/media/slide-thumbnail-preview.js'), 'utf8');
|
const slideThumbnailPreviewSource = fs.readFileSync(require.resolve('../src/web/lib/media/slide-thumbnail-preview.js'), 'utf8');
|
||||||
const slideThumbnailsSource = fs.readFileSync(require.resolve('../src/web/lib/media/slide-thumbnails.js'), 'utf8');
|
const slideThumbnailsSource = fs.readFileSync(require.resolve('../src/web/lib/media/slide-thumbnails.js'), 'utf8');
|
||||||
|
const slideHtmlRegionSource = fs.readFileSync(require.resolve('../src/web/public/js/regions/type/html.js'), 'utf8');
|
||||||
|
const slideWebpageRegionSource = fs.readFileSync(require.resolve('../src/web/public/js/regions/type/webpage.js'), 'utf8');
|
||||||
|
|
||||||
test('slide editor disables pasted data images in TinyMCE', () => {
|
test('slide editor disables pasted data images in TinyMCE', () => {
|
||||||
assert.ok(slideFormEditorSource.includes('paste_data_images: false'));
|
assert.ok(slideFormEditorSource.includes('paste_data_images: false'));
|
||||||
@@ -56,4 +58,24 @@ test('slide form queues editor image cleanup on save and close', () => {
|
|||||||
test('slide thumbnail previews treat image-only text as visible content', () => {
|
test('slide thumbnail previews treat image-only text as visible content', () => {
|
||||||
assert.ok(slideThumbnailPreviewSource.includes('/<img\\b/i.test(raw)'));
|
assert.ok(slideThumbnailPreviewSource.includes('/<img\\b/i.test(raw)'));
|
||||||
assert.ok(slideThumbnailsSource.includes('/<img\\b/i.test(raw)'));
|
assert.ok(slideThumbnailsSource.includes('/<img\\b/i.test(raw)'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('popup preview falls back to iframe sizing rules', () => {
|
||||||
|
const popupPreviewSource = fs.readFileSync(require.resolve('../src/web/views/signage/slides/popup-preview.hbs'), 'utf8');
|
||||||
|
|
||||||
|
assert.ok(popupPreviewSource.includes('#popup-preview-canvas iframe'));
|
||||||
|
assert.ok(popupPreviewSource.includes('#popup-preview-canvas .slide-preview-webpage-region iframe'));
|
||||||
|
assert.ok(popupPreviewSource.includes('#popup-preview-canvas .slide-preview-html-region iframe'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('browser preview helpers normalize object-shaped HTML and webpage values', () => {
|
||||||
|
assert.ok(slideHtmlRegionSource.includes('normalizePreviewValue'));
|
||||||
|
assert.ok(slideWebpageRegionSource.includes('normalizePreviewValue'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('webpage preview updates only through the explicit button', () => {
|
||||||
|
assert.ok(slideWebpageRegionSource.includes('input-group flex-nowrap'));
|
||||||
|
assert.ok(slideWebpageRegionSource.includes('data-webpage-preview-update'));
|
||||||
|
assert.ok(slideFormSource.includes('input[type="url"][name^="region_webpage_"]'));
|
||||||
|
assert.ok(slideFormSource.includes('requestPreviewRender();'));
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user