在wordpress上为md格式远程链接添加灯箱效果
环境:
wordpress6.9版本,ari fancy Lightbox插件1.3.18版本
问题:
要让灯箱插件可以识别到本地以md格式插入的远程链接
解决办法:
注意使用时关闭主题或者其他插件附带的灯箱效果。
在主题的functions.php末尾中追加
//这个版本会误识别多余的特色图片
// 前端保险脚本(只在单篇页面加载)
if (!function_exists('ari_enqueue_md_fallback_script')) {
add_action('wp_enqueue_scripts', 'ari_enqueue_md_fallback_script');
function ari_enqueue_md_fallback_script() {
if (!is_singular()) return;
wp_register_script('ari-md-fallback', '', [], false, true);
wp_enqueue_script('ari-md-fallback');
wp_add_inline_script('ari-md-fallback', "
(function($){
$(function(){
$('.entry-content, article, .post').find('img').each(function(){
var \$img = $(this);
if (\$img.parent('a').length === 0){
var src = \$img.attr('src');
if (src && /^https?:\\/\\/.+\\.(jpe?g|png|gif|webp|svg)(\\?.*)?$/i.test(src)){
\$img.wrap('<a href=\"'+src+'\" class=\"ari-fancybox\" data-ari=\"gallery\"></a>');
}
} else {
var \$a = \$img.parent('a');
if (!\$a.attr('data-ari') && !\$a.hasClass('ari-fancybox')){
var href = \$a.attr('href') || '';
if (/^https?:\\/\\/.+\\.(jpe?g|png|gif|webp|svg)(\\?.*)?$/i.test(href)){
\$a.addClass('ari-fancybox').attr('data-ari','gallery');
}
}
}
});
});
})(jQuery);
");
}
}
// 服务器端:用 DOMDocument 安全解析并为每个 img 添加/包裹 <a>
if (!function_exists('ari_wrap_remote_images_for_lightbox')) {
add_filter('the_content', 'ari_wrap_remote_images_for_lightbox', 20);
function ari_wrap_remote_images_for_lightbox($content) {
if (!is_singular() || empty($content)) {
return $content;
}
// 如果已经有 ARI 标记则跳过(避免重复处理)
if (strpos($content, 'data-ari') !== false || strpos($content, 'ari-fancybox') !== false) {
return $content;
}
// 使用 DOMDocument 解析 HTML(比复杂正则更稳健)
libxml_use_internal_errors(true);
$doc = new DOMDocument();
// 为避免编码问题,添加 XML 声明
$wrapped = '<?xml encoding="utf-8" ?>' . $content;
if (!$doc->loadHTML($wrapped, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD)) {
libxml_clear_errors();
return $content; // 解析失败则返回原始内容
}
libxml_clear_errors();
// 找到所有 img(注意:getElementsByTagName 返回实时集合)
$imgs = $doc->getElementsByTagName('img');
$toProcess = [];
foreach ($imgs as $img) {
$toProcess[] = $img;
}
foreach ($toProcess as $img) {
$parent = $img->parentNode;
// 如果父节点是 <a>,并且 href 指向图片,则给父 <a> 添加 ARI 属性
if ($parent && $parent->nodeName === 'a') {
$href = $parent->getAttribute('href');
if ($href && preg_match('/\.(jpe?g|png|gif|webp|svg)(\?.*)?$/i', $href)) {
$existing_class = $parent->getAttribute('class');
if (strpos($existing_class, 'ari-fancybox') === false) {
$parent->setAttribute('class', trim($existing_class . ' ari-fancybox'));
}
if (!$parent->hasAttribute('data-ari')) {
$parent->setAttribute('data-ari', 'gallery');
}
}
continue;
}
// 否则检查 img 的 src 是否为远程图片(http/https)并且是常见图片扩展
$src = $img->getAttribute('src');
if (!$src || !preg_match('/^https?:\\/\\//i', $src)) {
continue;
}
if (!preg_match('/\.(jpe?g|png|gif|webp|svg)(\?.*)?$/i', $src)) {
continue;
}
// 创建 <a> 并把 img 移入其中
$a = $doc->createElement('a');
$a->setAttribute('href', $src);
$a->setAttribute('class', 'ari-fancybox');
$a->setAttribute('data-ari', 'gallery');
// cloneNode(true) 保留 img 的所有属性
$newImg = $img->cloneNode(true);
$a->appendChild($newImg);
// 用 a 替换原 img 节点
$parent->replaceChild($a, $img);
}
// 导出处理后的 HTML,去掉我们加的 xml 声明
$html = $doc->saveHTML();
$html = preg_replace('/^<\\?xml.*?\\?>/','', $html);
return $html;
}
}
使用最新版ari fancy(1.4.1)灯箱插件
在functions中添加
/**
* 开启灯箱,仅使用灯箱的点击图片效果
* 自动为 Markdown 图片添加灯箱链接包裹
*/
function add_lightbox_to_markdown_images($content) {
// 匹配没有被 <a> 标签包裹的 <img> 标签
// 只针对文章详情页生效
if (is_singular() && is_main_query()) {
$pattern = '/<img(.*?)src="(.*?)"(.*?)>/i';
$replacement = '<a href="$2" class="ari-fancybox" title="点击放大"><img$1src="$2"$3></a>';
// 执行替换,但排除掉已经有链接的图片
$content = preg_replace_callback($pattern, function($matches) {
// 如果图片外层已经是 <a> 标签,则不处理
return $matches[0];
}, $content);
// 更简单的正则处理:直接包装所有图片(ARI 插件通常会自动处理重复链接)
$content = preg_replace('/(?<!<a href=")(<img[^>]*src="([^"]*)"[^>]*>)(?!<\/a>)/i', '<a href="$2" class="ari-fancybox">$1</a>', $content);
}
return $content;
}
add_filter('the_content', 'add_lightbox_to_markdown_images', 99);
/**
* 注意:使用了插件,但是全部预览图不能正常加载
* 自动为 Markdown 图片添加灯箱链接包裹,并实现“上一张/下一张”分组
*/
function add_lightbox_group_to_markdown_images($content) {
// 仅在文章详情页处理
if (is_singular() && is_main_query()) {
global $post;
$post_id = $post->ID; // 获取文章ID作为组名
// 匹配 img 标签
$pattern = '/<img(.*?)src="(.*?)"(.*?)>/i';
/**
* 关键点:
* 给 a 标签加上 data-fancybox="gallery-{$post_id}"
* 这样 ARI Fancy Lightbox 会把所有拥有相同 data-fancybox 值的图片归为一组
*/
$replacement = '<a href="$2" class="ari-fancybox" data-fancybox="gallery-' . $post_id . '" title="点击放大"><img$1src="$2"$3></a>';
// 排除掉已经手动带了 a 标签链接的图片,避免嵌套
$content = preg_replace_callback($pattern, function($matches) use ($post_id) {
// 如果图片已经在 a 标签里,就不再包裹(或者你可以根据需求强制替换)
// 这里我们采用简单直接的替换,如果发现图片已经被 a 标签包裹,正则逻辑会略微复杂
// 为了保证 Markdown 兼容,我们直接处理未被包裹的情况
return '<a href="' . $matches[2] . '" class="ari-fancybox" data-fancybox="gallery-' . $post_id . '"><img' . $matches[1] . 'src="' . $matches[2] . '"' . $matches[3] . '></a>';
}, $content);
}
return $content;
}
add_filter('the_content', 'add_lightbox_group_to_markdown_images', 100);
无插件解决方案
关闭所有灯箱插件。
在functions.php后追加
add_filter('the_content', function($content) {
if (is_singular() && is_main_query()) {
global $post;
$pattern = '/<img(.*?)src="(.*?)"(.*?)>/i';
$replacement = '<a href="$2" class="spotlight" data-gallery="gallery-' . $post->ID . '" data-control="zoom,close,prev,next,fullscreen,theme"><img$1src="$2"$3></a>';
$content = preg_replace($pattern, $replacement, $content);
}
return $content;
}, 100);
add_action('wp_footer', function() {
if (is_singular()) {
echo '
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/spotlight.bundle.js"></script>
<script type="text/javascript">
(function() {
var refreshSpotlight = function() {
var links = document.querySelectorAll(".spotlight");
links.forEach(function(link) {
if (link.getAttribute("data-hooked") !== "true") {
link.setAttribute("data-hooked", "true");
link.onclick = function(e) {
e.preventDefault();
e.stopPropagation();
// 启动灯箱并强制指定 UI 按钮
Spotlight.show(links, {
index: Array.from(links).indexOf(this),
theme: "dark",
show: ["zoom", "close", "prev", "next", "fullscreen", "theme"],
thumbs: false // 彻底移除预览图模块
});
return false;
};
}
});
};
refreshSpotlight();
setInterval(refreshSpotlight, 1000);
})();
</script>
<style>
/* 1. 强制显示切换按钮(那个半圆图标) */
.spl-theme {
display: inline-block !important;
visibility: visible !important;
opacity: 1 !important;
}
/* 2. 定义切换后的白色背景样式,否则点按钮没反应 */
#spotlight.white { background-color: #ffffff !important; }
#spotlight.white .spl-pane,
#spotlight.white .spl-footer { color: #333 !important; }
/* 3. 彻底隐藏缩略图容器 */
.spl-thumbs { display: none !important; height: 0 !important; }
/* 4. 基础 UI 修正 */
.spotlight { cursor: zoom-in !important; }
#spotlight { z-index: 99999999 !important; }
</style>
';
}
}, 100);