diff --git a/public/js/admin-app-form.js b/public/js/admin-app-form.js index 80e432f..fca5458 100644 --- a/public/js/admin-app-form.js +++ b/public/js/admin-app-form.js @@ -1,4 +1,4 @@ -import { clr, el, inp as inpById, q as qSel, qa, qi, tgt } from '/js/utils.js?v=7d0a2f7d'; +import { clr, el, inp as inpById, q as qSel, qa, qi, tgt } from '/js/utils.js?v=6d4d869b'; import { html, raw, setHtml } from '/js/html.js?v=c71f8903'; import { loadLocalIcons, resolveIcon, iconChain, cdnIconRef, splitIconRef } from '/js/icons.js?v=9c8c550c'; import { state } from '/js/admin-state.js?v=831e219e'; @@ -21,10 +21,10 @@ import { reveal, setTogDisabled, swapContent, -} from '/js/admin-shared.js?v=9d789975'; -import { createListbox } from '/js/listbox.js?v=c14ab216'; +} from '/js/admin-shared.js?v=10665320'; +import { createListbox } from '/js/listbox.js?v=7372c1d5'; import { MAX_LABELS } from '/js/badge-logic.js?v=9e6d9d4b'; -import { renderColorControl, BADGE_DEFAULT } from '/js/admin-color-control.js?v=15d6a495'; +import { renderColorControl, BADGE_DEFAULT } from '/js/admin-color-control.js?v=60fe4b32'; import { badgeErrorAdvice, TONE } from '/js/admin-error.js?v=e4ea7820'; import { fluidHoverClear, fluidHoverKb } from '/js/fluid-hover.js?v=cb886e86'; import { iconSvg } from '/js/icon-set.js?v=34af798f'; diff --git a/public/js/admin-auth.js b/public/js/admin-auth.js index f728468..90ecb79 100644 --- a/public/js/admin-auth.js +++ b/public/js/admin-auth.js @@ -1,7 +1,7 @@ -import { apiGet, apiPost } from '/js/admin-shared.js?v=9d789975'; +import { apiGet, apiPost } from '/js/admin-shared.js?v=10665320'; import { t } from '/js/i18n.js?v=1f1ea9c1'; import { pwStrength } from '/js/password-strength.js?v=42f45ac7'; -import { el, inp as inpById, qa } from '/js/utils.js?v=7d0a2f7d'; +import { el, inp as inpById, qa } from '/js/utils.js?v=6d4d869b'; export async function checkAuth(onLogin) { try { diff --git a/public/js/admin-color-control.js b/public/js/admin-color-control.js index 8906f92..129dbb2 100644 --- a/public/js/admin-color-control.js +++ b/public/js/admin-color-control.js @@ -1,7 +1,7 @@ -import { PE_SVG, initInlineEdit, toast, reveal } from '/js/admin-shared.js?v=9d789975'; +import { PE_SVG, initInlineEdit, toast, reveal } from '/js/admin-shared.js?v=10665320'; import { t } from '/js/i18n.js?v=1f1ea9c1'; import { html, raw, setHtml } from '/js/html.js?v=c71f8903'; -import { qa, q } from '/js/utils.js?v=7d0a2f7d'; +import { qa, q } from '/js/utils.js?v=6d4d869b'; import { iconSvg } from '/js/icon-set.js?v=34af798f'; import { HUE_NAMES, ROLE_NAMES, TILE_KEYWORDS, pageTheme, tileColor } from '/js/palette.js?v=3fb8ae43'; diff --git a/public/js/admin-drag.js b/public/js/admin-drag.js index 5150905..401e5a9 100644 --- a/public/js/admin-drag.js +++ b/public/js/admin-drag.js @@ -12,7 +12,7 @@ import { applyDrop, canJoinFolder, folderRowZone } from '/js/admin-drag-logic.js?v=6b767e76'; import { state } from '/js/admin-state.js?v=831e219e'; import { snapshotItems } from '/js/admin-save-logic.js?v=60a82419'; -import { qa } from '/js/utils.js?v=7d0a2f7d'; +import { qa } from '/js/utils.js?v=6d4d869b'; /** @type {(before: unknown) => void} */ let _save = () => {}; diff --git a/public/js/admin-list.js b/public/js/admin-list.js index 29357a8..1109d1f 100644 --- a/public/js/admin-list.js +++ b/public/js/admin-list.js @@ -14,12 +14,12 @@ import { collapsedFolders, filter, state } from '/js/admin-state.js?v=831e219e'; import { snapshotItems } from '/js/admin-save-logic.js?v=60a82419'; import { reorderItems } from '/js/admin-logic.js?v=cbb7417d'; -import { initDrag, wireRowDrag } from '/js/admin-drag.js?v=e31d2128'; -import { paintIcon } from '/js/admin-shared.js?v=9d789975'; -import { clr, el, qa, setUserText } from '/js/utils.js?v=7d0a2f7d'; +import { initDrag, wireRowDrag } from '/js/admin-drag.js?v=5e47c084'; +import { paintIcon } from '/js/admin-shared.js?v=10665320'; +import { clr, el, qa, setUserText } from '/js/utils.js?v=6d4d869b'; import { html, raw, setHtml } from '/js/html.js?v=c71f8903'; import { t } from '/js/i18n.js?v=1f1ea9c1'; -import { sizeLabel } from '/js/admin-widget-form.js?v=f9235794'; +import { sizeLabel } from '/js/admin-widget-form.js?v=8d526d32'; import { widgetGlyph } from '/js/widget-glyphs.js?v=648cc374'; import { iconSvg } from '/js/icon-set.js?v=34af798f'; diff --git a/public/js/admin-settings.js b/public/js/admin-settings.js index 60b95e6..66b81c5 100644 --- a/public/js/admin-settings.js +++ b/public/js/admin-settings.js @@ -1,4 +1,4 @@ -import { toast, apiGet, apiPost, reveal, swapContent } from '/js/admin-shared.js?v=9d789975'; +import { toast, apiGet, apiPost, reveal, swapContent } from '/js/admin-shared.js?v=10665320'; import { pwStrength } from '/js/password-strength.js?v=42f45ac7'; import { t } from '/js/i18n.js?v=1f1ea9c1'; import { @@ -9,9 +9,9 @@ import { BLOCK, } from '/js/admin-logic.js?v=cbb7417d'; import { confirmText } from '/js/modal.js?v=11fa1eff'; -import { el, inp, setUserText } from '/js/utils.js?v=7d0a2f7d'; -import { renderColorControl } from '/js/admin-color-control.js?v=15d6a495'; -import { BACKDROP } from '/js/background.js?v=92d3f3c2'; +import { el, inp, setUserText } from '/js/utils.js?v=6d4d869b'; +import { renderColorControl } from '/js/admin-color-control.js?v=60fe4b32'; +import { BACKDROP } from '/js/background.js?v=0caab98e'; /* Mirrors the server's rule: auth cannot be switched on with no password. */ let _passwordSet = false; diff --git a/public/js/admin-shared.js b/public/js/admin-shared.js index a22c81b..c448f67 100644 --- a/public/js/admin-shared.js +++ b/public/js/admin-shared.js @@ -1,6 +1,6 @@ /* Stateless helpers shared by the admin modules. Mutable state stays out. */ import { recoversSession, toastHoldMs } from '/js/admin-logic.js?v=cbb7417d'; -import { el, q } from '/js/utils.js?v=7d0a2f7d'; +import { el, q } from '/js/utils.js?v=6d4d869b'; import { t } from '/js/i18n.js?v=1f1ea9c1'; import { iconChain } from '/js/icons.js?v=9c8c550c'; import { iconSvg } from '/js/icon-set.js?v=34af798f'; diff --git a/public/js/admin-widget-form.js b/public/js/admin-widget-form.js index e48a3a7..45d2d3a 100644 --- a/public/js/admin-widget-form.js +++ b/public/js/admin-widget-form.js @@ -1,11 +1,11 @@ import { state } from '/js/admin-state.js?v=831e219e'; -import { PE_SVG, initInlineEdit, swapContent } from '/js/admin-shared.js?v=9d789975'; -import { createListbox } from '/js/listbox.js?v=c14ab216'; -import { renderWidgetConfigForm } from '/js/widget-config-form.js?v=a57a9501'; +import { PE_SVG, initInlineEdit, swapContent } from '/js/admin-shared.js?v=10665320'; +import { createListbox } from '/js/listbox.js?v=7372c1d5'; +import { renderWidgetConfigForm } from '/js/widget-config-form.js?v=cf2a5a6e'; import { html, raw, setHtml } from '/js/html.js?v=c71f8903'; import { sizesForView, widgetConfigMode, rejectionLines, carriesTypedValues } from '/js/admin-logic.js?v=cbb7417d'; import { t } from '/js/i18n.js?v=1f1ea9c1'; -import { q, qi, qa } from '/js/utils.js?v=7d0a2f7d'; +import { q, qi, qa } from '/js/utils.js?v=6d4d869b'; import { iconSvg } from '/js/icon-set.js?v=34af798f'; const SIZES_WITH_ICONS = new Set(['small', 'medium', 'large', 'xlarge']); diff --git a/public/js/admin.js b/public/js/admin.js index a353a07..a2a2a41 100644 --- a/public/js/admin.js +++ b/public/js/admin.js @@ -1,6 +1,6 @@ -import { buildAppForm, buildFolderForm, captureActLabels, serializeKvRows } from '/js/admin-app-form.js?v=7604b201'; -import { checkAuth, requireLogin, wirePasswordStrength } from '/js/admin-auth.js?v=1d822df2'; -import { initList, render, syncFilterUI } from '/js/admin-list.js?v=fe5e00b2'; +import { buildAppForm, buildFolderForm, captureActLabels, serializeKvRows } from '/js/admin-app-form.js?v=cbb0e02c'; +import { checkAuth, requireLogin, wirePasswordStrength } from '/js/admin-auth.js?v=06cea8ee'; +import { initList, render, syncFilterUI } from '/js/admin-list.js?v=333a9833'; import { resolveAdminSection } from '/js/admin-logic.js?v=cbb7417d'; import { buildAppItem, @@ -10,7 +10,7 @@ import { snapshotItems, upsertItem, } from '/js/admin-save-logic.js?v=60a82419'; -import { loadSettings, settingsDirty, showBgFields, showWallpaperFile } from '/js/admin-settings.js?v=9ed2fd03'; +import { loadSettings, settingsDirty, showBgFields, showWallpaperFile } from '/js/admin-settings.js?v=36fd9c08'; import { apiGet, apiPost, @@ -19,12 +19,12 @@ import { reveal, setReauthHandler, toast, -} from '/js/admin-shared.js?v=9d789975'; +} from '/js/admin-shared.js?v=10665320'; import { collapsedFolders, filter, state } from '/js/admin-state.js?v=831e219e'; -import { buildWidgetForm } from '/js/admin-widget-form.js?v=f9235794'; +import { buildWidgetForm } from '/js/admin-widget-form.js?v=8d526d32'; import { initFluidHover } from '/js/fluid-hover.js?v=cb886e86'; import { initGlideSelect, syncGlideSelect } from '/js/glide-select.js?v=8b39e9d0'; -import { createListbox } from '/js/listbox.js?v=c14ab216'; +import { createListbox } from '/js/listbox.js?v=7372c1d5'; import { html, raw, setHtml } from '/js/html.js?v=c71f8903'; import { initI18n, LANGUAGES, t } from '/js/i18n.js?v=1f1ea9c1'; import { loadLocalIcons } from '/js/icons.js?v=9c8c550c'; @@ -49,8 +49,8 @@ import { watchSystemTheme, writeMode, } from '/js/theme.js?v=eeafa4b5'; -import { el, inp, q, qa, clr, setUserText, tgt } from '/js/utils.js?v=7d0a2f7d'; -import { applyBackground, resolveBackground } from '/js/background.js?v=92d3f3c2'; +import { el, inp, q, qa, clr, setUserText, tgt } from '/js/utils.js?v=6d4d869b'; +import { applyBackground, resolveBackground } from '/js/background.js?v=0caab98e'; import { parseYamlTolerant, YamlLiteError } from '/js/yaml-lite.js?v=6ebb564c'; ensureSprite(); diff --git a/public/js/background.js b/public/js/background.js index 0e32251..19bde79 100644 --- a/public/js/background.js +++ b/public/js/background.js @@ -1,5 +1,5 @@ // @ts-check -import { cssColor, sanitizeCssUrl } from '/js/utils.js?v=7d0a2f7d'; +import { cssColor, sanitizeCssUrl } from '/js/utils.js?v=6d4d869b'; import { loadWallpaper, saveWallpaper } from '/js/wallpaper-cache.js?v=c5f8a3e6'; export const BACKDROP = '#0d1117'; diff --git a/public/js/dashboard.js b/public/js/dashboard.js index bad2a2c..3b20496 100644 --- a/public/js/dashboard.js +++ b/public/js/dashboard.js @@ -24,9 +24,9 @@ import { setUserText, teardownWidgets, titleWhenTruncated, -} from '/js/utils.js?v=7d0a2f7d'; +} from '/js/utils.js?v=6d4d869b'; import { initFluidHover } from '/js/fluid-hover.js?v=cb886e86'; -import { initSpotlight } from '/js/spotlight.js?v=a6f5775a'; +import { initSpotlight } from '/js/spotlight.js?v=bc6d6187'; import { html, setHtml, raw } from '/js/html.js?v=c71f8903'; import { initI18n, t, currentLang } from '/js/i18n.js?v=1f1ea9c1'; import { pwStrength, passwordMismatch } from '/js/password-strength.js?v=42f45ac7'; @@ -40,7 +40,7 @@ import { buildMobile, resetMobileChrome, mkFolderGlyph, -} from '/js/ui.js?v=67ae7e42'; +} from '/js/ui.js?v=cb1af792'; import { badgeMinimum, badgeSignature, computeBadgeVisual, readBadgeUpdate } from '/js/badge-logic.js?v=9e6d9d4b'; import { formatNumber } from '/js/format-number.js?v=4a5ccef4'; import { closeBadgePopover, wireBadgePopover } from '/js/badge-popover.js?v=aa52b1a3'; @@ -52,7 +52,7 @@ import { landingAfterSetup, restorePage, } from '/js/dashboard-logic.js?v=0d519f8b'; -import { applyBackground, BACKDROP, resolveBackground } from '/js/background.js?v=92d3f3c2'; +import { applyBackground, BACKDROP, resolveBackground } from '/js/background.js?v=0caab98e'; import { jitter } from '/js/jitter.js?v=4eeef4c9'; import { isMobileLayout, onLayoutChange } from '/js/layout.js?v=e9f4b607'; import { startWakeLock } from '/js/wake-lock.js?v=6b9591cf'; diff --git a/public/js/listbox.js b/public/js/listbox.js index 80638fd..45454b3 100644 --- a/public/js/listbox.js +++ b/public/js/listbox.js @@ -9,7 +9,7 @@ import { nextActiveIndex } from '/js/admin-logic.js?v=cbb7417d'; import { fluidHoverClear, fluidHoverKb } from '/js/fluid-hover.js?v=cb886e86'; import { html, raw, setHtml } from '/js/html.js?v=c71f8903'; -import { qa } from '/js/utils.js?v=7d0a2f7d'; +import { qa } from '/js/utils.js?v=6d4d869b'; import { iconSvg } from '/js/icon-set.js?v=34af798f'; const CHEV = iconSvg('chevrons', 22, 'solid', 'dd-chev'); diff --git a/public/js/spotlight.js b/public/js/spotlight.js index 59033dd..f0cec56 100644 --- a/public/js/spotlight.js +++ b/public/js/spotlight.js @@ -1,5 +1,5 @@ import { fluidHoverClear, fluidHoverKb } from '/js/fluid-hover.js?v=cb886e86'; -import { mk, clr, el, inp as inpById, q, qa, setUserText } from '/js/utils.js?v=7d0a2f7d'; +import { mk, clr, el, inp as inpById, q, qa, setUserText } from '/js/utils.js?v=6d4d869b'; import { t } from '/js/i18n.js?v=1f1ea9c1'; /* Attached to the window so a re-open can undo the previous one. */ diff --git a/public/js/ui.js b/public/js/ui.js index de5392c..7990dd1 100644 --- a/public/js/ui.js +++ b/public/js/ui.js @@ -14,7 +14,7 @@ import { q, qa, setUserText, -} from '/js/utils.js?v=7d0a2f7d'; +} from '/js/utils.js?v=6d4d869b'; import { t, currentLang } from '/js/i18n.js?v=1f1ea9c1'; import { toneForColor } from '/js/label-contrast.js?v=c1ac6fb8'; import { mobileMetrics, gridColumnWidth, gridCellCount } from '/js/mobile-metrics.js?v=349f4300'; diff --git a/public/js/utils.js b/public/js/utils.js index b96120b..153927d 100644 --- a/public/js/utils.js +++ b/public/js/utils.js @@ -211,13 +211,16 @@ const SAFE_IFRAME_FEATURES = new Set([ 'web-share', ]); -/** @param {unknown} value @returns {string} */ -export function safeAllow(value) { +/** @param {unknown} value @param {boolean} [fullscreen] @returns {string} */ +export function safeAllow(value, fullscreen = true) { const kept = String(value == null ? '' : value) .split(';') .map(part => part.trim()) - .filter(part => part && SAFE_IFRAME_FEATURES.has(part.split(/[\s(]/)[0].toLowerCase())); - return kept.join('; ') || 'fullscreen'; + .filter(part => { + const feature = part.split(/[\s(]/)[0].toLowerCase(); + return part && SAFE_IFRAME_FEATURES.has(feature) && (fullscreen || feature !== 'fullscreen'); + }); + return kept.join('; ') || (fullscreen ? 'fullscreen' : ''); } /* Mounts the iframe at a fixed design resolution and scales it to fill `card`. @@ -259,8 +262,10 @@ export function mountScaledWidget(card, { src, title, design, iframeOpts, overla clip.style.cssText = 'position:absolute;inset:0;overflow:hidden;'; const ifr = mk('iframe', { src, scrolling: o.scrolling === true || o.scrolling === 'yes' ? 'yes' : 'no', title }); if (isCrossOrigin(src)) ifr.setAttribute('sandbox', SANDBOX); - ifr.setAttribute('allow', safeAllow(o.allow)); - if (o.allowFullscreen !== false) ifr.setAttribute('allowfullscreen', ''); + const fullscreen = o.allowFullscreen !== false; + const allow = safeAllow(o.allow, fullscreen); + if (allow) ifr.setAttribute('allow', allow); + if (fullscreen) ifr.setAttribute('allowfullscreen', ''); if (o.referrerPolicy) ifr.setAttribute('referrerpolicy', o.referrerPolicy); if (o.loading) ifr.setAttribute('loading', o.loading); ifr.setAttribute('aria-label', title); diff --git a/public/js/widget-config-form.js b/public/js/widget-config-form.js index 3616477..9d47850 100644 --- a/public/js/widget-config-form.js +++ b/public/js/widget-config-form.js @@ -3,9 +3,9 @@ import { t } from '/js/i18n.js?v=1f1ea9c1'; import { html, raw, setHtml } from '/js/html.js?v=c71f8903'; -import { reveal, wireInlineEdit } from '/js/admin-shared.js?v=9d789975'; -import { createListbox } from '/js/listbox.js?v=c14ab216'; -import { renderColorControl } from '/js/admin-color-control.js?v=15d6a495'; +import { reveal, wireInlineEdit } from '/js/admin-shared.js?v=10665320'; +import { createListbox } from '/js/listbox.js?v=7372c1d5'; +import { renderColorControl } from '/js/admin-color-control.js?v=60fe4b32'; import { seedCarried, applyOptionSet, @@ -15,7 +15,7 @@ import { visibleFieldFlags, } from '/js/admin-logic.js?v=cbb7417d'; import { optionsErrorAdvice, TONE } from '/js/admin-error.js?v=e4ea7820'; -import { qi } from '/js/utils.js?v=7d0a2f7d'; +import { qi } from '/js/utils.js?v=6d4d869b'; const PE = '';