From eabd9d2de5eab010b18b5a40402e7e0a0fb76cd7 Mon Sep 17 00:00:00 2001
From: Wx-2025 <351320169@qq.com>
Date: Wed, 19 Nov 2025 22:47:19 +0800
Subject: [PATCH] Update renderer.js
---
core/tavern-helper/renderer.js | 104 ++++++++++++++++++++++++++++++++-
1 file changed, 101 insertions(+), 3 deletions(-)
diff --git a/core/tavern-helper/renderer.js b/core/tavern-helper/renderer.js
index c615d35..f481f0d 100644
--- a/core/tavern-helper/renderer.js
+++ b/core/tavern-helper/renderer.js
@@ -16,6 +16,71 @@ const hashToBlobUrl = new Map();
const blobLRU = [];
const BLOB_CACHE_LIMIT = 32;
+const viewport_adjust_script = `
+
+`;
+
+function processAllVhUnits(htmlContent) {
+ const viewportHeight = window.innerHeight;
+
+ let processedContent = htmlContent.replace(
+ /((?:document\.body\.style\.minHeight|\.style\.minHeight|setProperty\s*\(\s*['"]min-height['"])\s*[=,]\s*['"`])([^'"`]*?)(['"`])/g,
+ (match, prefix, value, suffix) => {
+ if (value.includes('vh')) {
+ const convertedValue = value.replace(/(\d+(?:\.\d+)?)vh/g, (num) => {
+ const numValue = parseFloat(num);
+ if (numValue === 100) {
+ return `var(--viewport-height, ${viewportHeight}px)`;
+ } else {
+ return `calc(var(--viewport-height, ${viewportHeight}px) * ${numValue / 100})`;
+ }
+ });
+ return prefix + convertedValue + suffix;
+ }
+ return match;
+ },
+ );
+
+ processedContent = processedContent.replace(/min-height:\s*([^;]*vh[^;]*);/g, expression => {
+ const processedExpression = expression.replace(/(\d+(?:\.\d+)?)vh/g, num => {
+ const numValue = parseFloat(num);
+ if (numValue === 100) {
+ return `var(--viewport-height, ${viewportHeight}px)`;
+ } else {
+ return `calc(var(--viewport-height, ${viewportHeight}px) * ${numValue / 100})`;
+ }
+ });
+ return `${processedExpression};`;
+ });
+
+ processedContent = processedContent.replace(
+ /style\s*=\s*["']([^"']*min-height:\s*[^"']*vh[^"']*?)["']/gi,
+ (match, styleContent) => {
+ const processedStyleContent = styleContent.replace(/min-height:\s*([^;]*vh[^;]*)/g, (expression) => {
+ const processedExpression = expression.replace(/(\d+(?:\.\d+)?)vh/g, num => {
+ const numValue = parseFloat(num);
+ if (numValue === 100) {
+ return `var(--viewport-height, ${viewportHeight}px)`;
+ } else {
+ return `calc(var(--viewport-height, ${viewportHeight}px) * ${numValue / 100})`;
+ }
+ });
+ return processedExpression;
+ });
+ return match.replace(styleContent, processedStyleContent);
+ },
+ );
+
+ return processedContent;
+}
+
function generateUniqueId() {
return `amily2-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
}
@@ -144,11 +209,13 @@ function iframeClientScript() {
})();`;
}
-function buildWrappedHtml(html) {
+function buildWrappedHtml(html, needsVh) {
const origin = (typeof location !== 'undefined' && location.origin) ? location.origin : '';
const baseTag = settings && settings.useBlob ? `` : "";
const headHints = buildResourceHints(html);
const vhFix = ``;
+ const vhStyle = needsVh ? `` : '';
+ const vhScript = needsVh ? viewport_adjust_script : '';
const apiScript = `
${headHints}
${vhFix}
+${vhStyle}
${apiScript}
+${vhScript}
`;
const isFullHtml = //i.test(html);
@@ -477,6 +546,17 @@ function releaseIframeBlob(iframe) {
function renderHtmlInIframe(htmlContent, container, preElement) {
try {
+ let processedHtml = htmlContent;
+ let needsVh = false;
+
+ const hasMinVh = /min-height:\s*[^;]*vh/.test(htmlContent);
+ const hasJsVhUsage = /\d+vh/.test(htmlContent);
+
+ if (hasMinVh || hasJsVhUsage) {
+ processedHtml = processAllVhUnits(htmlContent);
+ needsVh = true;
+ }
+
const originalHash = djb2(htmlContent);
const iframe = document.createElement('iframe');
iframe.id = generateUniqueId();
@@ -490,6 +570,11 @@ function renderHtmlInIframe(htmlContent, container, preElement) {
} else {
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-modals allow-popups');
}
+
+ if (needsVh) {
+ iframe.dataset.needsVh = 'true';
+ }
+
const wrapper = getOrCreateWrapper(preElement);
wrapper.querySelectorAll('.amily2-iframe').forEach(old => {
try { old.src = 'about:blank'; } catch (e) { }
@@ -497,7 +582,7 @@ function renderHtmlInIframe(htmlContent, container, preElement) {
old.remove();
});
const codeHash = djb2(htmlContent);
- const full = buildWrappedHtml(htmlContent);
+ const full = buildWrappedHtml(processedHtml, needsVh);
if (settings.useBlob) {
setIframeBlobHTML(iframe, full, codeHash);
} else {
@@ -517,7 +602,7 @@ function renderHtmlInIframe(htmlContent, container, preElement) {
}
function processCodeBlocks(messageElement) {
- if (extension_settings[extensionName].render_enabled === false) return;
+ if (extension_settings[extensionName].amily_render_enabled === false) return;
try {
const codeBlocks = messageElement.querySelectorAll('pre > code');
codeBlocks.forEach(codeBlock => {
@@ -576,6 +661,19 @@ export function initializeRenderer() {
});
window.addEventListener('message', handleIframeMessage);
+
+ window.addEventListener('resize', function () {
+ const viewportHeight = window.innerHeight;
+ const iframes = document.querySelectorAll('iframe.amily2-iframe');
+ iframes.forEach(iframe => {
+ if (iframe.dataset.needsVh === 'true') {
+ iframe.contentWindow?.postMessage({
+ request: 'updateViewportHeight',
+ newHeight: viewportHeight
+ }, '*');
+ }
+ });
+ });
console.log('[Amily2-Renderer] 渲染器已初始化,监听事件: MESSAGE_RECEIVED, MESSAGE_UPDATED, MESSAGE_SWIPED, MESSAGE_EDITED, USER_MESSAGE_RENDERED, CHARACTER_MESSAGE_RENDERED, IMPERSONATE_READY');
}