Milestone admin and frontend stage
This commit is contained in:
parent
66d59eba0a
commit
e9c0dd56c2
|
|
@ -220,6 +220,12 @@ const STATIC_FALLBACK = {
|
|||
appIconAlt: "Иконка NODE.DC",
|
||||
appWordmarkSrc: "./assets/webflow/images/69ad96a28b06b7552a339137_logtype.svg?v=node-dc",
|
||||
appWordmarkAlt: "Логотип NODE.DC",
|
||||
faviconSvg: "./assets/uploads/favicon/icon-adaptive.svg",
|
||||
faviconIco: "./assets/uploads/favicon/favicon.ico",
|
||||
faviconAppleTouchIcon: "./assets/uploads/favicon/apple-touch-icon.png",
|
||||
faviconPng192: "./assets/uploads/favicon/icon-192.png",
|
||||
faviconPng512: "./assets/uploads/favicon/icon-512.png",
|
||||
faviconManifest: "./assets/uploads/favicon/manifest.webmanifest.json",
|
||||
},
|
||||
},
|
||||
editableFields: [
|
||||
|
|
@ -289,6 +295,12 @@ const STATIC_FALLBACK = {
|
|||
field("content.assets.appIconAlt", "Иконка приложения: alt", "text", "text", "Модель и логотипы"),
|
||||
field("content.assets.appWordmarkSrc", "Wordmark приложения", "media", "attr", "Модель и логотипы"),
|
||||
field("content.assets.appWordmarkAlt", "Wordmark приложения: alt", "text", "text", "Модель и логотипы"),
|
||||
field("content.assets.faviconSvg", "Favicon SVG", "media", "attr", "Модель и логотипы"),
|
||||
field("content.assets.faviconIco", "Favicon ICO", "media", "attr", "Модель и логотипы"),
|
||||
field("content.assets.faviconAppleTouchIcon", "Favicon Apple 180", "media", "attr", "Модель и логотипы"),
|
||||
field("content.assets.faviconPng192", "Favicon PNG 192", "media", "attr", "Модель и логотипы"),
|
||||
field("content.assets.faviconPng512", "Favicon PNG 512", "media", "attr", "Модель и логотипы"),
|
||||
field("content.assets.faviconManifest", "Favicon manifest", "media", "attr", "Модель и логотипы"),
|
||||
],
|
||||
};
|
||||
|
||||
|
|
@ -297,7 +309,7 @@ const GROUP_COPY = {
|
|||
"Шапка: ссылки": "Пункты навигации верхней mac-панели. Каждый пункт можно добавить, удалить и переставить.",
|
||||
Уведомления: "Карточки уведомлений справа сверху. Порядок в админке соответствует порядку на сайте.",
|
||||
Dock: "Нижняя системная панель: приложения, корзина, ссылки и подписи файлов.",
|
||||
"Модель и логотипы": "Базовые ассеты статичного слоя: GLB-модель, PNG/SVG-логотипы и alt-тексты.",
|
||||
"Модель и логотипы": "Базовые ассеты статичного слоя: GLB-модель, PNG/SVG-логотипы, favicon-комплект и alt-тексты.",
|
||||
Заголовок: "Главный заголовок и вводный текст выбранной секции.",
|
||||
"Верхний информационный блок": "Верхняя пара: длинный текст и крупный заголовок над медиаслайдером.",
|
||||
"Нижний информационный блок": "Нижняя зеркальная пара: крупный заголовок и длинный текст под медиаслайдером.",
|
||||
|
|
@ -328,7 +340,8 @@ const GROUP_COPY = {
|
|||
Контент: "Остальные typed-поля выбранного блока.",
|
||||
};
|
||||
|
||||
const MEDIA_ACCEPT = "image/*,video/*,.gif,.webm,.mov,.mp4,.m4v,.avi,.mkv,.glb,.gltf,.svg,.avif,.webp,.woff,.woff2";
|
||||
const MEDIA_ACCEPT =
|
||||
"image/*,video/*,.gif,.webm,.mov,.mp4,.m4v,.avi,.mkv,.glb,.gltf,.svg,.ico,.avif,.webp,.webmanifest,.json,.woff,.woff2";
|
||||
const MEDIA_DRAG_MIME = "application/x-nodedc-media-entry";
|
||||
const MEDIA_KIND_FILTERS = [
|
||||
["all", "Все"],
|
||||
|
|
@ -598,6 +611,11 @@ function ensureStaticElements() {
|
|||
notification.eyebrowClass ||= STATIC_FALLBACK.content.notifications[index]?.eyebrowClass || "red-txt gray";
|
||||
});
|
||||
state.page.staticElements.content.assets ||= clone(STATIC_FALLBACK.content.assets);
|
||||
for (const [key, value] of Object.entries(STATIC_FALLBACK.content.assets)) {
|
||||
if (!Object.prototype.hasOwnProperty.call(state.page.staticElements.content.assets, key)) {
|
||||
state.page.staticElements.content.assets[key] = value;
|
||||
}
|
||||
}
|
||||
state.page.staticElements.content.dock ||= clone(STATIC_FALLBACK.content.dock);
|
||||
normalizeDock(state.page.staticElements.content.dock, state.page.staticElements.content.assets);
|
||||
state.page.staticElements.editableFields = clone(STATIC_FALLBACK.editableFields);
|
||||
|
|
@ -715,7 +733,7 @@ function adminPreviewUrl(value) {
|
|||
function mediaKindFromValue(value) {
|
||||
if (!value) return null;
|
||||
if (/\.(mp4|webm|mov|m4v|avi|mkv)(\?.*)?$/i.test(value)) return "video";
|
||||
if (/\.(png|jpe?g|gif|svg|avif|webp)(\?.*)?$/i.test(value)) return "image";
|
||||
if (/\.(png|jpe?g|gif|svg|ico|avif|webp)(\?.*)?$/i.test(value)) return "image";
|
||||
if (/\.(glb|gltf)(\?.*)?$/i.test(value)) return "model";
|
||||
if (/\.(woff2?|ttf|otf)(\?.*)?$/i.test(value)) return "font";
|
||||
return null;
|
||||
|
|
@ -781,6 +799,7 @@ function uploadBucketForField(block, editableField) {
|
|||
if (path.includes("webgl") || currentValue.endsWith(".glb") || currentValue.endsWith(".gltf")) root = "models";
|
||||
if (path.includes("video") || path.includes("media") || path.includes("sliders") || path.includes("slideritems")) root = "media";
|
||||
if (path.includes("font") || /\.(woff2?|ttf|otf)(\?.*)?$/i.test(currentValue)) root = "fonts";
|
||||
if (path.includes("favicon")) return "favicon";
|
||||
|
||||
return `${root}/${blockSegment}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,3 +5,4 @@
|
|||
.pricing-table-section .pricing-table-shell{padding-top:12svh;padding-bottom:12svh}@media screen and (max-width:767px){.pricing-table-section .pricing-table-shell{padding-top:8svh;padding-bottom:8svh}}
|
||||
[data-module=notification-w][data-notification-stack-ready]{height:auto;max-height:calc(100svh - 3.2rem);overflow:visible;scrollbar-width:none;overscroll-behavior:contain}[data-module=notification-w][data-notification-stack-ready]::-webkit-scrollbar{display:none}[data-module=notification-w][data-notification-stack-ready]:not(:hover):not([data-notification-expanded=true]){height:var(--notification-collapsed-height,6.6rem);max-height:var(--notification-collapsed-height,6.6rem)}[data-module=notification-w][data-notification-stack-ready]:is(:hover,[data-notification-expanded=true]){overflow-x:visible;overflow-y:auto;padding-bottom:.2rem}[data-module=notification-w][data-notification-stack-ready]>[data-module=notification]{position:relative;z-index:var(--notification-z,1);transform:translateY(var(--notification-stack-y,0));transition:transform .3s cubic-bezier(.22,1,.36,1)}[data-module=notification-w][data-notification-stack-ready]:is(:hover,[data-notification-expanded=true])>[data-module=notification]{transform:translateY(0)}
|
||||
.dock-icon.ssscript{overflow:hidden;background-color:transparent;background-image:none}.dock-icon.ssscript>img{display:block;width:100%;height:100%;max-width:none;object-fit:cover;border-radius:inherit}
|
||||
[data-module=dock]{overflow:visible}[data-module=dock] .dock-icon{position:relative;overflow:visible}[data-module=dock] .dock-icon.ssscript{overflow:visible}[data-module=dock] .dock-icon::after{content:attr(data-dock-title);position:absolute;z-index:30;left:50%;bottom:calc(100% + .64rem);max-width:14rem;transform:translate(-50%,.28rem) scale(.96);transform-origin:50% 100%;opacity:0;pointer-events:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border:1px solid rgba(255,255,255,.12);border-radius:.72rem;background:linear-gradient(180deg,rgba(255,255,255,.07),rgba(255,255,255,.018)),rgba(34,34,38,.86);box-shadow:inset 0 1px 0 rgba(255,255,255,.08),0 20px 60px rgba(0,0,0,.42);-webkit-backdrop-filter:blur(22px) saturate(1.15);backdrop-filter:blur(22px) saturate(1.15);color:rgba(255,255,255,.92);padding:.42rem .68rem;font-size:.68rem;font-weight:760;line-height:1;letter-spacing:0;transition:opacity .16s ease,transform .16s ease}[data-module=dock] .dock-icon:is(:hover,:focus-visible){z-index:20}[data-module=dock] .dock-icon:is(:hover,:focus-visible)::after{opacity:1;transform:translate(-50%,0) scale(1)}[data-module=dock] .dock-icon[data-dock-title=""]::after{display:none}
|
||||
|
|
|
|||
|
|
@ -5,3 +5,4 @@
|
|||
.pricing-table-section .pricing-table-shell{padding-top:12svh;padding-bottom:12svh}@media screen and (max-width:767px){.pricing-table-section .pricing-table-shell{padding-top:8svh;padding-bottom:8svh}}
|
||||
[data-module=notification-w][data-notification-stack-ready]{height:auto;max-height:calc(100svh - 3.2rem);overflow:visible;scrollbar-width:none;overscroll-behavior:contain}[data-module=notification-w][data-notification-stack-ready]::-webkit-scrollbar{display:none}[data-module=notification-w][data-notification-stack-ready]:not(:hover):not([data-notification-expanded=true]){height:var(--notification-collapsed-height,6.6rem);max-height:var(--notification-collapsed-height,6.6rem)}[data-module=notification-w][data-notification-stack-ready]:is(:hover,[data-notification-expanded=true]){overflow-x:visible;overflow-y:auto;padding-bottom:.2rem}[data-module=notification-w][data-notification-stack-ready]>[data-module=notification]{position:relative;z-index:var(--notification-z,1);transform:translateY(var(--notification-stack-y,0));transition:transform .3s cubic-bezier(.22,1,.36,1)}[data-module=notification-w][data-notification-stack-ready]:is(:hover,[data-notification-expanded=true])>[data-module=notification]{transform:translateY(0)}
|
||||
.dock-icon.ssscript{overflow:hidden;background-color:transparent;background-image:none}.dock-icon.ssscript>img{display:block;width:100%;height:100%;max-width:none;object-fit:cover;border-radius:inherit}
|
||||
[data-module=dock]{overflow:visible}[data-module=dock] .dock-icon{position:relative;overflow:visible}[data-module=dock] .dock-icon.ssscript{overflow:visible}[data-module=dock] .dock-icon::after{content:attr(data-dock-title);position:absolute;z-index:30;left:50%;bottom:calc(100% + .64rem);max-width:14rem;transform:translate(-50%,.28rem) scale(.96);transform-origin:50% 100%;opacity:0;pointer-events:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border:1px solid rgba(255,255,255,.12);border-radius:.72rem;background:linear-gradient(180deg,rgba(255,255,255,.07),rgba(255,255,255,.018)),rgba(34,34,38,.86);box-shadow:inset 0 1px 0 rgba(255,255,255,.08),0 20px 60px rgba(0,0,0,.42);-webkit-backdrop-filter:blur(22px) saturate(1.15);backdrop-filter:blur(22px) saturate(1.15);color:rgba(255,255,255,.92);padding:.42rem .68rem;font-size:.68rem;font-weight:760;line-height:1;letter-spacing:0;transition:opacity .16s ease,transform .16s ease}[data-module=dock] .dock-icon:is(:hover,:focus-visible){z-index:20}[data-module=dock] .dock-icon:is(:hover,:focus-visible)::after{opacity:1;transform:translate(-50%,0) scale(1)}[data-module=dock] .dock-icon[data-dock-title=""]::after{display:none}
|
||||
|
|
|
|||
|
|
@ -372,7 +372,15 @@
|
|||
const hasAppTarget = Boolean(targetId && document.getElementById(targetId));
|
||||
const isInertHref = !href || href === "#" || href === "#hero" || href.toLowerCase().startsWith("javascript:");
|
||||
|
||||
if (!hasAppTarget && !isInertHref) return;
|
||||
if (!isInertHref) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
link.setAttribute("target", "_blank");
|
||||
link.setAttribute("rel", "noopener noreferrer");
|
||||
window.open(href, "_blank", "noopener,noreferrer");
|
||||
window.requestAnimationFrame(() => link.blur());
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
window.requestAnimationFrame(() => link.blur());
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
|
|
@ -0,0 +1,13 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.icon-fav-01 { fill: #333334; } /* Тёмный цвет для светлого таб-бара */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.icon-fav-01 { fill: #FEFEFE; } /* Светлый цвет для тёмного таб-бара */
|
||||
}
|
||||
@media (prefers-color-scheme: light) {
|
||||
.icon-fav-01 { fill: #000000; } /* Тёмный цвет для светлого таб-бара (для явности) */
|
||||
}
|
||||
</style>
|
||||
<path class="icon-fav-01" d="M17.8738 15.9159L16.0002 18.9718L14.1267 15.9159H17.8738ZM23.6307 12.7864H8.36914L15.9999 25.2308L23.6307 12.7864Z"/>
|
||||
<path class="icon-fav-01" d="M10.9793 19.4872L6.67269 11.5918H25.5344L21.2281 19.4872H25.0581L31.2614 8H0.738281L7.16244 19.4872H10.9793Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 852 B |
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"theme_color": "#eeeff4",
|
||||
"background_color": "#eeeff4",
|
||||
"display": "browser",
|
||||
"scope": "/",
|
||||
"start_url": "/",
|
||||
"icons": [
|
||||
{
|
||||
"src": "icon-adaptive.svg",
|
||||
"type": "image/svg+xml",
|
||||
"sizes": "any"
|
||||
},
|
||||
{
|
||||
"src": "icon-192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "icon-512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
},
|
||||
{
|
||||
"src": "apple-touch-icon.png",
|
||||
"type": "image/png",
|
||||
"sizes": "180x180"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -150,7 +150,13 @@
|
|||
"appIconSrc": "./assets/uploads/images/Logo/dclogo_white_alpha-mqus5if2.png",
|
||||
"appIconAlt": "Иконка NODE.DC",
|
||||
"appWordmarkSrc": "./assets/webflow/images/69ad96a28b06b7552a339137_logtype.svg?v=node-dc",
|
||||
"appWordmarkAlt": "Логотип NODE.DC"
|
||||
"appWordmarkAlt": "Логотип NODE.DC",
|
||||
"faviconSvg": "./assets/uploads/favicon/icon-adaptive.svg",
|
||||
"faviconIco": "./assets/uploads/favicon/favicon.ico",
|
||||
"faviconAppleTouchIcon": "./assets/uploads/favicon/apple-touch-icon.png",
|
||||
"faviconPng192": "./assets/uploads/favicon/icon-192.png",
|
||||
"faviconPng512": "./assets/uploads/favicon/icon-512.png",
|
||||
"faviconManifest": "./assets/uploads/favicon/manifest.webmanifest.json"
|
||||
}
|
||||
},
|
||||
"editableFields": [
|
||||
|
|
@ -382,6 +388,48 @@
|
|||
"kind": "text",
|
||||
"renderAs": "text",
|
||||
"group": "Модель и логотипы"
|
||||
},
|
||||
{
|
||||
"path": "content.assets.faviconSvg",
|
||||
"label": "Favicon SVG",
|
||||
"kind": "media",
|
||||
"renderAs": "attr",
|
||||
"group": "Модель и логотипы"
|
||||
},
|
||||
{
|
||||
"path": "content.assets.faviconIco",
|
||||
"label": "Favicon ICO",
|
||||
"kind": "media",
|
||||
"renderAs": "attr",
|
||||
"group": "Модель и логотипы"
|
||||
},
|
||||
{
|
||||
"path": "content.assets.faviconAppleTouchIcon",
|
||||
"label": "Favicon Apple 180",
|
||||
"kind": "media",
|
||||
"renderAs": "attr",
|
||||
"group": "Модель и логотипы"
|
||||
},
|
||||
{
|
||||
"path": "content.assets.faviconPng192",
|
||||
"label": "Favicon PNG 192",
|
||||
"kind": "media",
|
||||
"renderAs": "attr",
|
||||
"group": "Модель и логотипы"
|
||||
},
|
||||
{
|
||||
"path": "content.assets.faviconPng512",
|
||||
"label": "Favicon PNG 512",
|
||||
"kind": "media",
|
||||
"renderAs": "attr",
|
||||
"group": "Модель и логотипы"
|
||||
},
|
||||
{
|
||||
"path": "content.assets.faviconManifest",
|
||||
"label": "Favicon manifest",
|
||||
"kind": "media",
|
||||
"renderAs": "attr",
|
||||
"group": "Модель и логотипы"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -66,6 +66,8 @@ const MEDIA_EXTENSIONS = new Set([
|
|||
".gif",
|
||||
".glb",
|
||||
".gltf",
|
||||
".ico",
|
||||
".json",
|
||||
".jpeg",
|
||||
".jpg",
|
||||
".m4v",
|
||||
|
|
@ -73,6 +75,7 @@ const MEDIA_EXTENSIONS = new Set([
|
|||
".mp4",
|
||||
".png",
|
||||
".svg",
|
||||
".webmanifest",
|
||||
".webm",
|
||||
".webp",
|
||||
".woff",
|
||||
|
|
@ -91,6 +94,7 @@ const REFERENCE_TEXT_EXTENSIONS = new Set([
|
|||
".ts",
|
||||
".tsx",
|
||||
".txt",
|
||||
".webmanifest",
|
||||
".xml",
|
||||
]);
|
||||
|
||||
|
|
@ -100,6 +104,8 @@ const MIME = {
|
|||
".js": "text/javascript; charset=utf-8",
|
||||
".json": "application/json; charset=utf-8",
|
||||
".svg": "image/svg+xml",
|
||||
".ico": "image/x-icon",
|
||||
".webmanifest": "application/manifest+json; charset=utf-8",
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
|
|
@ -150,6 +156,15 @@ function sendStream(req, res, status, stream, headers) {
|
|||
stream.pipe(res);
|
||||
}
|
||||
|
||||
function contentTypeForPath(filePath) {
|
||||
const normalizedPath = String(filePath || "").toLowerCase();
|
||||
if (normalizedPath.endsWith(".webmanifest") || normalizedPath.endsWith(".webmanifest.json")) {
|
||||
return "application/manifest+json; charset=utf-8";
|
||||
}
|
||||
|
||||
return MIME[extname(filePath).toLowerCase()] || "application/octet-stream";
|
||||
}
|
||||
|
||||
function sendJson(res, status, payload) {
|
||||
send(res, status, `${JSON.stringify(payload, null, 2)}\n`, "application/json; charset=utf-8");
|
||||
}
|
||||
|
|
@ -225,6 +240,8 @@ function sanitizeUploadBucket(value) {
|
|||
function extensionFromMimeType(mimeType) {
|
||||
const map = {
|
||||
"image/svg+xml": ".svg",
|
||||
"image/x-icon": ".ico",
|
||||
"image/vnd.microsoft.icon": ".ico",
|
||||
"image/png": ".png",
|
||||
"image/jpeg": ".jpg",
|
||||
"image/gif": ".gif",
|
||||
|
|
@ -233,6 +250,8 @@ function extensionFromMimeType(mimeType) {
|
|||
"video/mp4": ".mp4",
|
||||
"video/webm": ".webm",
|
||||
"video/quicktime": ".mov",
|
||||
"application/manifest+json": ".webmanifest",
|
||||
"application/json": ".json",
|
||||
"model/gltf-binary": ".glb",
|
||||
"model/gltf+json": ".gltf",
|
||||
"font/woff": ".woff",
|
||||
|
|
@ -503,7 +522,7 @@ function serializedAssetReplacements(replacements) {
|
|||
}
|
||||
|
||||
function mediaKindFromExtension(extension) {
|
||||
if ([".avif", ".gif", ".jpeg", ".jpg", ".png", ".svg", ".webp"].includes(extension)) return "image";
|
||||
if ([".avif", ".gif", ".ico", ".jpeg", ".jpg", ".png", ".svg", ".webp"].includes(extension)) return "image";
|
||||
if ([".m4v", ".mov", ".mp4", ".webm"].includes(extension)) return "video";
|
||||
if ([".glb", ".gltf"].includes(extension)) return "model";
|
||||
if ([".woff", ".woff2"].includes(extension)) return "font";
|
||||
|
|
@ -1383,8 +1402,7 @@ async function serveStatic(req, res) {
|
|||
return;
|
||||
}
|
||||
|
||||
const ext = extname(filePath);
|
||||
const contentType = MIME[ext] || "application/octet-stream";
|
||||
const contentType = contentTypeForPath(filePath);
|
||||
const range = req.headers.range;
|
||||
|
||||
if (range) {
|
||||
|
|
|
|||
|
|
@ -720,6 +720,12 @@ const staticElements = {
|
|||
appIconAlt: "Иконка NODE.DC",
|
||||
appWordmarkSrc: "./assets/webflow/images/69ad96a28b06b7552a339137_logtype.svg?v=node-dc",
|
||||
appWordmarkAlt: "Логотип NODE.DC",
|
||||
faviconSvg: "./assets/uploads/favicon/icon-adaptive.svg",
|
||||
faviconIco: "./assets/uploads/favicon/favicon.ico",
|
||||
faviconAppleTouchIcon: "./assets/uploads/favicon/apple-touch-icon.png",
|
||||
faviconPng192: "./assets/uploads/favicon/icon-192.png",
|
||||
faviconPng512: "./assets/uploads/favicon/icon-512.png",
|
||||
faviconManifest: "./assets/uploads/favicon/manifest.webmanifest.json",
|
||||
},
|
||||
},
|
||||
editableFields: [
|
||||
|
|
@ -753,6 +759,12 @@ const staticElements = {
|
|||
field("content.assets.appIconAlt", "Иконка приложения: alt"),
|
||||
field("content.assets.appWordmarkSrc", "Wordmark приложения", "media", "attr"),
|
||||
field("content.assets.appWordmarkAlt", "Wordmark приложения: alt"),
|
||||
field("content.assets.faviconSvg", "Favicon SVG", "media", "attr"),
|
||||
field("content.assets.faviconIco", "Favicon ICO", "media", "attr"),
|
||||
field("content.assets.faviconAppleTouchIcon", "Favicon Apple 180", "media", "attr"),
|
||||
field("content.assets.faviconPng192", "Favicon PNG 192", "media", "attr"),
|
||||
field("content.assets.faviconPng512", "Favicon PNG 512", "media", "attr"),
|
||||
field("content.assets.faviconManifest", "Favicon manifest", "media", "attr"),
|
||||
],
|
||||
};
|
||||
|
||||
|
|
@ -772,6 +784,39 @@ function tokenizeStaticShell(source, definition) {
|
|||
const { navigation, notifications, dock } = definition.content;
|
||||
|
||||
let tokenized = source;
|
||||
const faviconHead = [
|
||||
`{{#if staticElements.content.assets.faviconSvg}}<link rel="icon" type="image/svg+xml" sizes="any" href="${shellToken(
|
||||
"attr",
|
||||
"content.assets.faviconSvg",
|
||||
)}"/>{{/if}}`,
|
||||
`{{#if staticElements.content.assets.faviconIco}}<link rel="icon" type="image/x-icon" href="${shellToken(
|
||||
"attr",
|
||||
"content.assets.faviconIco",
|
||||
)}"/>{{/if}}`,
|
||||
`{{#if staticElements.content.assets.faviconAppleTouchIcon}}<link rel="apple-touch-icon" sizes="180x180" href="${shellToken(
|
||||
"attr",
|
||||
"content.assets.faviconAppleTouchIcon",
|
||||
)}"/>{{/if}}`,
|
||||
`{{#if staticElements.content.assets.faviconPng192}}<link rel="icon" type="image/png" sizes="192x192" href="${shellToken(
|
||||
"attr",
|
||||
"content.assets.faviconPng192",
|
||||
)}"/>{{/if}}`,
|
||||
`{{#if staticElements.content.assets.faviconPng512}}<link rel="icon" type="image/png" sizes="512x512" href="${shellToken(
|
||||
"attr",
|
||||
"content.assets.faviconPng512",
|
||||
)}"/>{{/if}}`,
|
||||
`{{#if staticElements.content.assets.faviconManifest}}<link rel="manifest" href="${shellToken(
|
||||
"attr",
|
||||
"content.assets.faviconManifest",
|
||||
)}"/>{{/if}}`,
|
||||
].join("");
|
||||
|
||||
tokenized = replaceShellLiteral(
|
||||
tokenized,
|
||||
`<link href="./assets/webflow/images/69b83bc24411350dcdb86781_favicon.png" rel="shortcut icon" type="image/x-icon"/><link href="./assets/webflow/images/69b83bc6ad9e108637556ec5_webclip.png" rel="apple-touch-icon"/>`,
|
||||
faviconHead,
|
||||
"favicon links",
|
||||
);
|
||||
|
||||
tokenized = replaceShellLiteral(
|
||||
tokenized,
|
||||
|
|
|
|||
|
|
@ -78,6 +78,11 @@ function isExternalHref(value) {
|
|||
return /^(https?:)?\/\//i.test(String(value || "")) || /^(mailto:|tel:)/i.test(String(value || ""));
|
||||
}
|
||||
|
||||
function isInertHref(value) {
|
||||
const href = String(value || "").trim();
|
||||
return !href || href === "#" || href === "#hero" || href.toLowerCase().startsWith("javascript:");
|
||||
}
|
||||
|
||||
function normalizeLinkForRender(item) {
|
||||
if (!item || typeof item !== "object") return;
|
||||
|
||||
|
|
@ -103,12 +108,28 @@ function normalizeLinkForRender(item) {
|
|||
item.resolvedTarget = mode === "href" ? linkTarget : "";
|
||||
}
|
||||
|
||||
function normalizeDockItemForRender(item) {
|
||||
if (!item || typeof item !== "object") return;
|
||||
|
||||
const href = String(item.href || "").trim();
|
||||
const opensWindow = !isInertHref(href);
|
||||
|
||||
item.resolvedDockHref = href || "#";
|
||||
item.resolvedDockTarget = opensWindow ? "_blank" : "";
|
||||
item.resolvedDockRel = opensWindow ? "noopener noreferrer" : "";
|
||||
}
|
||||
|
||||
function applyRenderableLinks(model) {
|
||||
const staticLinks = model.staticElements?.content?.navigation?.links;
|
||||
if (Array.isArray(staticLinks)) {
|
||||
staticLinks.forEach(normalizeLinkForRender);
|
||||
}
|
||||
|
||||
const dockItems = model.staticElements?.content?.dock?.items;
|
||||
if (Array.isArray(dockItems)) {
|
||||
dockItems.forEach(normalizeDockItemForRender);
|
||||
}
|
||||
|
||||
for (const block of allBlocks(model)) {
|
||||
const footer = block.content?.footer;
|
||||
if (!footer) continue;
|
||||
|
|
|
|||
Loading…
Reference in New Issue