如何为非oEmbed格式的视频iframe嵌套videoWrapper类div容器?
实现方案
你可以通过拆分处理逻辑、结合WordPress原生oEmbed标记+视频域名白名单的方式解决误包裹问题,以下是可直接使用的实现:
推荐方案:DOM解析版(兼容性高,无正则匹配漏洞)
利用WordPress oEmbed内容会自动添加wp-block-embed类的特性,先排除所有oEmbed框架内的嵌入标签,再通过视频域名白名单筛选需要包裹的内容:
/** * 仅为非oEmbed的视频iframe添加外层videoWrapper包裹 */ function video_wrapper_only_non_oembed( $content ) { // 内容无嵌入标签直接返回,减少不必要性能消耗 if ( false === strpos( $content, '<iframe' ) && false === strpos( $content, '<embed' ) ) { return $content; } // 忽略DOM解析的HTML规范警告 libxml_use_internal_errors( true ); $dom = new DOMDocument(); // 处理中文编码乱码问题 $dom->loadHTML( mb_convert_encoding( $content, 'HTML-ENTITIES', 'UTF-8' ) ); libxml_clear_errors(); $xpath = new DOMXPath( $dom ); // 筛选所有不在oEmbed块内的iframe和embed标签 $nodes = $xpath->query( '//iframe[not(ancestor::*[contains(@class,"wp-block-embed")])] | //embed[not(ancestor::*[contains(@class,"wp-block-embed")])]' ); // 视频平台域名白名单,可根据自己的需求增减 $video_hosts = [ 'youtube.com', 'youtu.be', 'vimeo.com', 'bilibili.com', 'qq.com/video', 'youku.com', 'tudou.com', 'mgtv.com' ]; foreach ( $nodes as $node ) { $src = $node->getAttribute( 'src' ); $is_video = false; // 校验是否为视频平台嵌入 foreach ( $video_hosts as $host ) { if ( strpos( $src, $host ) !== false ) { $is_video = true; break; } } if ( !$is_video ) { continue; } // 生成包裹div替换原节点 $wrapper = $dom->createElement( 'div' ); $wrapper->setAttribute( 'class', 'videoWrapper' ); $wrapper->appendChild( $node->cloneNode( true ) ); $node->parentNode->replaceChild( $wrapper, $node ); } // 输出处理后的内容,去掉DOM自动生成的html/body外层标签 $new_content = ''; foreach ( $dom->getElementsByTagName( 'body' )->item(0)->childNodes as $child ) { $new_content .= $dom->saveHTML( $child ); } return $new_content; } // 优先级设为20,晚于WordPress默认oEmbed的处理优先级(默认8),确保oEmbed内容已渲染完成 add_filter( 'the_content', 'video_wrapper_only_non_oembed', 20 );
简化方案:正则版(性能更高,适配简单场景)
如果你的场景比较简单,不需要兼容复杂的HTML结构,可以用正则版本快速实现:
function div_wrapper($content) { // 视频平台域名匹配规则 $video_hosts = implode('|', ['youtube\.com', 'youtu\.be', 'vimeo\.com', 'bilibili\.com']); // 匹配不在oEmbed块内、且属于视频平台的iframe $pattern = '~<iframe[^>]*src="[^"]*(?:'.$video_hosts.')[^"]*"[^>]*></iframe>(?!</div><!-- wp-block-embed -->)~'; preg_match_all($pattern, $content, $matches); foreach ($matches[0] as $match) { $wrappedframe = '<div class="videoWrapper">' . $match . '</div>'; $content = str_replace($match, $wrappedframe, $content); } return $content; } add_filter('the_content', 'div_wrapper', 20);
内容的提问来源于stack exchange,提问作者jojoreni
相关产品推荐
相关产品推荐

