mirror of
https://gitee.com/ulthon/ulthon_information.git
synced 2026-07-01 16:22:49 +08:00
fix(phone-image): 修复XSS注入、正则兼容性、render锁稳定性和缓存清理
T1: XSS修复 - PHP模板注入改用json_encode,poster URL转义处理
T2: fontSize NaN修复 - parseInt统一处理,lookbehind正则替换为兼容方案
T3: render锁稳定性 - insertPageBreak/removePageBreak添加15次重试上限,
fontsReady添加catch处理,_pending递归添加错误捕获
T4: 缓存清理 - init()清空缓存,render()超过3倍blocks数自动清理
This commit is contained in:
@@ -92,6 +92,9 @@ var PhoneImageEngine = (function () {
|
||||
$.extend(config, userConfig);
|
||||
}
|
||||
|
||||
// 清空缓存,避免旧数据干扰
|
||||
convertedBlockCache = {};
|
||||
|
||||
// 内容流事件委托(只绑定一次)
|
||||
$(document).off('click', '.break-inserter-btn');
|
||||
$(document).off('click', '.remove-break-btn');
|
||||
@@ -142,6 +145,12 @@ var PhoneImageEngine = (function () {
|
||||
var cleanHtml = preprocessContent(postData.content_html);
|
||||
var blocks = parseHtmlToBlocks(cleanHtml);
|
||||
|
||||
// 缓存清理:如果缓存条目过多则清空,防止内存膨胀
|
||||
var cacheKeys = Object.keys(convertedBlockCache);
|
||||
if (cacheKeys.length > blocks.length * 3) {
|
||||
convertedBlockCache = {};
|
||||
}
|
||||
|
||||
// 先渲染内容流(DOM) - 用于实测高度
|
||||
renderContentFlow(blocks);
|
||||
|
||||
@@ -181,7 +190,9 @@ var PhoneImageEngine = (function () {
|
||||
// 如果渲染期间有新的渲染请求排队,自动触发
|
||||
if (render._pending) {
|
||||
render._pending = false;
|
||||
render();
|
||||
render().catch(function () {
|
||||
// 静默处理递归渲染失败
|
||||
});
|
||||
}
|
||||
deferred.resolve(pages);
|
||||
}).catch(function (err) {
|
||||
@@ -553,13 +564,25 @@ var PhoneImageEngine = (function () {
|
||||
return [block];
|
||||
}
|
||||
|
||||
// 按句子拆分:句号、问号、叹号、换行
|
||||
var sentences = text.split(/(?<=[。!?\n])/);
|
||||
// 按句子拆分:句号、问号、叹号、换行(兼容不支持 lookbehind 的浏览器)
|
||||
var effectiveFontSize = parseInt(config.fontSize, 10) || 14;
|
||||
var parts = text.split(/([。!?\n])/);
|
||||
var sentences = [];
|
||||
var current = '';
|
||||
for (var si = 0; si < parts.length; si++) {
|
||||
current += parts[si];
|
||||
if (/[。!?\n]/.test(parts[si]) && current.length > 0) {
|
||||
sentences.push(current);
|
||||
current = '';
|
||||
}
|
||||
}
|
||||
if (current) sentences.push(current);
|
||||
|
||||
if (sentences.length <= 1) {
|
||||
// 无法按句子拆分,按固定字符数拆分
|
||||
sentences = [];
|
||||
var chunkSize = Math.floor(getContentWidth() / config.fontSize) *
|
||||
Math.floor(pageHeight / (config.fontSize * 1.8));
|
||||
var chunkSize = Math.floor(getContentWidth() / effectiveFontSize) *
|
||||
Math.floor(pageHeight / (effectiveFontSize * 1.8));
|
||||
if (chunkSize < 10) chunkSize = 10;
|
||||
for (var ci = 0; ci < text.length; ci += chunkSize) {
|
||||
sentences.push(text.substring(ci, ci + chunkSize));
|
||||
@@ -570,7 +593,7 @@ var PhoneImageEngine = (function () {
|
||||
for (var j = 0; j < sentences.length; j++) {
|
||||
var s = sentences[j].trim();
|
||||
if (!s) continue;
|
||||
var h = estimateTextHeight(s, config.fontSize);
|
||||
var h = estimateTextHeight(s, effectiveFontSize);
|
||||
result.push({
|
||||
type: wrapperTag === 'blockquote' ? 'blockquote' : 'p',
|
||||
html: '<' + wrapperTag + '>' + s + '</' + wrapperTag + '>',
|
||||
@@ -610,7 +633,7 @@ var PhoneImageEngine = (function () {
|
||||
html += '" style="width:' + sizeConfig.width + 'px;height:' + sizeConfig.height + 'px;">';
|
||||
|
||||
if (hasCover) {
|
||||
html += '<img class="cover-image" src="' + postData.poster + '" alt="">';
|
||||
html += '<img class="cover-image" src="' + escapeHtml(postData.poster) + '" alt="">';
|
||||
html += '<div class="cover-title">' + escapeHtml(postData.title) + '</div>';
|
||||
if (postData.desc) {
|
||||
html += '<div class="cover-subtitle">' + escapeHtml(postData.desc) + '</div>';
|
||||
@@ -825,7 +848,9 @@ var PhoneImageEngine = (function () {
|
||||
? document.fonts.ready
|
||||
: $.Deferred().resolve().promise();
|
||||
|
||||
fontsReady.then(function () {
|
||||
fontsReady.catch(function () {
|
||||
// 字体加载失败不影响截图,继续执行
|
||||
}).then(function () {
|
||||
requestAnimationFrame(function () {
|
||||
// html2canvas会跳过visibility:hidden的元素,临时切换为可见
|
||||
$staging.css({ visibility: 'visible' });
|
||||
@@ -1163,9 +1188,16 @@ var PhoneImageEngine = (function () {
|
||||
function insertPageBreak(blockIndex) {
|
||||
// 如果正在渲染,延迟重试
|
||||
if (render._locked) {
|
||||
insertPageBreak._retryCount = (insertPageBreak._retryCount || 0) + 1;
|
||||
if (insertPageBreak._retryCount >= 15) {
|
||||
insertPageBreak._retryCount = 0;
|
||||
layer.msg('操作超时,请重试');
|
||||
return;
|
||||
}
|
||||
setTimeout(function () { insertPageBreak(blockIndex); }, 200);
|
||||
return;
|
||||
}
|
||||
insertPageBreak._retryCount = 0;
|
||||
|
||||
var cleanHtml = preprocessContent(postData.content_html);
|
||||
var $temp = $('<div>').html(cleanHtml);
|
||||
@@ -1191,9 +1223,16 @@ var PhoneImageEngine = (function () {
|
||||
function removePageBreak(blockIndex) {
|
||||
// 如果正在渲染,延迟重试
|
||||
if (render._locked) {
|
||||
removePageBreak._retryCount = (removePageBreak._retryCount || 0) + 1;
|
||||
if (removePageBreak._retryCount >= 15) {
|
||||
removePageBreak._retryCount = 0;
|
||||
layer.msg('操作超时,请重试');
|
||||
return;
|
||||
}
|
||||
setTimeout(function () { removePageBreak(blockIndex); }, 200);
|
||||
return;
|
||||
}
|
||||
removePageBreak._retryCount = 0;
|
||||
|
||||
// 统计这是第几个 page-break
|
||||
var cleanHtml = preprocessContent(postData.content_html);
|
||||
|
||||
@@ -187,13 +187,13 @@
|
||||
|
||||
var postData = {
|
||||
postId: {$post.id},
|
||||
title: '{$post.title|raw}',
|
||||
desc: '{$post.desc|default=""}',
|
||||
coverText: '{$post->getData("cover_text")|default=""}',
|
||||
title: <?php echo json_encode($post->title ?? ''); ?>,
|
||||
desc: <?php echo json_encode($post->desc ?? ''); ?>,
|
||||
coverText: <?php echo json_encode($post->getData('cover_text') ?? ''); ?>,
|
||||
contentHtml: $('#post-content-html').html(),
|
||||
poster: '{$post.poster|default=""}',
|
||||
authorName: '{$post.author_name|default=""}',
|
||||
createTime: '{$post.create_time_text|default=""}',
|
||||
poster: <?php echo json_encode($post->poster ?? ''); ?>,
|
||||
authorName: <?php echo json_encode($post->author_name ?? ''); ?>,
|
||||
createTime: <?php echo json_encode($post->create_time_text ?? ''); ?>,
|
||||
categoryName: ''
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user