我写了一个小函数来在我的首页上显示最新的视频。功能本身工作得很好。唯一的问题是,wordpress继续在代码的一个位置插入一个开放的<p>
标记。这是我的功能:
function video_start() {
// the query
$the_query = new WP_Query(array('post_type'=>'page','post_parent'=>'17','order'=>'ASC','orderby' => 'date','posts_per_page'=>1));
// The Loop
if ( $the_query->have_posts() )
{
while ( $the_query->have_posts() )
{
$the_query->the_post();
if ( has_post_thumbnail() )
{
$picid = get_post_thumbnail_id($post_id);
$alt_text = get_post_meta($picid , '_wp_attachment_image_alt', true);
$string .= '<div class="featured-start">';
$string .= '<a href="' . get_the_permalink() .'" class="b-link" rel="bookmark">';
$string .= '<h2 class="mar-bot">Latest Video</h2>';
$string .= '<img src="'.wp_get_attachment_url(get_post_thumbnail_id($post_id)).'" class="img-responsive" alt="'.$alt_text.'" />';
$string .= '<p>'.get_the_title().'</p>';
$string .= '<div class="orange-button">Watch Video</div></a></div>';
}
}
}
else
{
// no posts found
}
$string .= '<div class="clear"></div>';
return $string;
/* Restore original Post Data */
wp_reset_postdata();
}
// Add a shortcode
add_shortcode('video_startpage', 'video_start');
// Enable shortcodes in text widgets
add_filter('widget_text', 'do_shortcode');
我遇到问题的输出是这样的:
<div class="featured-start">
<a href="http://www.kundenwebseite.inweco.de/videos/pet-project-09-part-1/" class="b-link" rel="bookmark"><br />
<h2 class="mar-bot">Latest Video</h2>
<p><img src="http://www.kundenwebseite.inweco.de/wp-content/uploads/2015/11/pet-project-2009-part-1.jpg" class="img-responsive" alt="" />
<p>Pet Project 09 – Part 1</p>
<div class="orange-button">Watch Video</div>
<p></a></div>
<div class="clear"></div>
我试过几种方法删除wp-autop过滤器,但它根本无法工作。即使使用谷歌超过两个小时,我现在无法找到解决方案。
好的。经过长时间的搜索(得到史蒂夫的大量帮助),我终于找到了解决方案。我从中获取了wpautop函数(从第456行开始到第604行结束)
https://core.trac.wordpress.org/browser/tags/4.3.1/src/wp-includes/formatting.php#L0
并使用提供的链接中的新qpautop函数替换/ wp-includes /文件夹中的formatting.php文件中的现有wpautop函数。然后我评论了499行。
所有这一切都让它为我工作。
这是多年来的一个已知问题。请看看Wordpress Ticket。
正如之前提到的其他人一样,有一个插件可以解决这个问题。它被称为“Shortcode Empty Paragraph Fix”。它不是最好的解决方案,但也不是那么糟糕。
我不喜欢给我的wp安装带来很多膨胀 - 所以我将短代码包装在没有类的div中并修复了问题。
<div> [woocommerce_cart] </div>
我希望这个问题会在接下来的几年中得到解决;)所以我可以删除我的div - 在我看来是一种更安全的方式,因为有时候funcitons.php中的额外功能可能会导致一些问题。
Wordpress会自动对您的内容应用wpautop过滤器,直接添加到帖子编辑器或由短码生成,
为了避免wordpress在您的内容上添加不需要的标签,
您可以使用块元素包装所有内联元素,而无需向该内联元素添加新行,.e.g
<div><a href="#">Hello</a></div>
将输出<div><a href="#">Hello</a></div>
<div>
<a href="#">Hello</a>
</div>
将输出<div><p><a href="#">Hello</a><p></div>
你的选择是;
return trim(preg_replace('/\s+/', ' ', $string));
下面这段代码是我主题的内置函数
function my_custom_content_formatter($content) { $new_content = ''; $pattern_full = '{(\[raw\].*?\[/raw\])}is'; $pattern_contents = '{\[raw\](.*?)\[/raw\]}is'; $pieces = preg_split($pattern_full, $content, -1, PREG_SPLIT_DELIM_CAPTURE); foreach ($pieces as $piece) { if (preg_match($pattern_contents, $piece, $matches)) { $new_content .= $matches[1]; } else { $new_content .= wptexturize(wpautop($piece)); } } return $new_content; } // Remove the 2 main auto-formatters remove_filter('the_content', 'wpautop'); remove_filter('the_content', 'wptexturize'); // apply new auto-formatter add_filter('the_content', 'my_custom_content_formatter', 99); add_filter('widget_text', 'my_custom_content_formatter', 99);
然后,您可以添加像[raw][video_startpage][/raw]
这样的短代码
wpautop()函数位于wp-includes / formatting.php中,它允许您指定是否需要<p>
,但似乎传递参数以将其关闭在您的情况下不起作用 - 这些方法可能有些使用。
这个使用str_replace()
并没有那么糟糕,并提供了其他几个选项:
https://wordpress.org/support/topic/shortcode-is-being-surrounded-by-p-tags
也是同一页上的一个产品,删除了自动转换为<p>
标签的换行符str_replace(array("\n\r", "\n", "\r"), '', $content );
这是一个在该页面上提供的插件,但我不知道它是否正常 - 你好像能够提供所提供的功能并将其添加到你的functions.php
- 如果你有一个孩子主题https://codex.wordpress.org/Child_Themes你可以把它放在功能.php里面的内容,所以当你的父主题更新时它不会丢失。 (被视为最佳实践)。
https://wordpress.org/plugins/shortcode-empty-paragraph-fix/
我有同样的问题,因为上面没有任何真正有用的东西,我决定解决它。所以这是我的解决方案(虽然只适用于具有结束标签的短代码)。
就这样我们都在同一页面上,如果我们在wp编辑器中有这个,那么有一个行和col的基本短代码,用它们的特定类输出div:
lorem test
[row]
[col]inside col[/col]
[/row]
dolor
结果输出将是:
<p>lorem test<br />
<div class="row "><div class="columns ">inside col</div></div><br />
dolor</p>
这是错的,正确的方法应该是:
<p>lorem test</p>
<div class="row "><div class="columns ">inside col</div></div>
<p>dolor</p>
为实现这一目标,我们首先用自己的替换wpautop过滤器
add_action('init','cod_custom_wpautop',90);
function cod_custom_wpautop() {
remove_filter('the_content', 'wpautop');
remove_filter('acf_the_content', 'wpautop');
add_filter('the_content', 'cod_wpautop');
add_filter('acf_the_content', 'cod_wpautop');
}
然后实际的函数与wp-includes / formating.php上的函数大致相同,但是我们自己的更改:
function cod_wpautop( $pee, $br = true ) {
$pre_tags = array();
if ( trim($pee) === '' )
return '';
// Just to make things a little easier, pad the end.
$pee = $pee . "\n";
/*
* Pre tags shouldn't be touched by autop.
* Replace pre tags with placeholders and bring them back after autop.
*/
if ( strpos($pee, '<pre') !== false ) {
$pee_parts = explode( '</pre>', $pee );
$last_pee = array_pop($pee_parts);
$pee = '';
$i = 0;
foreach ( $pee_parts as $pee_part ) {
$start = strpos($pee_part, '<pre');
// Malformed html?
if ( $start === false ) {
$pee .= $pee_part;
continue;
}
$name = "<pre wp-pre-tag-$i></pre>";
$pre_tags[$name] = substr( $pee_part, $start ) . '</pre>';
$pee .= substr( $pee_part, 0, $start ) . $name;
$i++;
}
$pee .= $last_pee;
}
// Change multiple <br>s into two line breaks, which will turn into paragraphs.
$pee = preg_replace('|<br\s*/?>\s*<br\s*/?>|', "\n\n", $pee);
$allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)';
// Add a double line break above block-level opening tags.
$pee = preg_replace('!(<' . $allblocks . '[\s/>])!', "\n\n$1", $pee);
// Add a double line break below block-level closing tags.
$pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee);
$shortcode_blocks = '(?:row|col)';
$pee = preg_replace('!(\[' . $shortcode_blocks . '[\s/\]])!', "\n\n$1", $pee);
$pee = preg_replace('!(\[/' . $shortcode_blocks . '\])!', "$1\n\n", $pee);
// Standardize newline characters to "\n".
$pee = str_replace(array("\r\n", "\r"), "\n", $pee);
// Find newlines in all elements and add placeholders.
$pee = wp_replace_in_html_tags( $pee, array( "\n" => " <!-- wpnl --> " ) );
// Collapse line breaks before and after <option> elements so they don't get autop'd.
if ( strpos( $pee, '<option' ) !== false ) {
$pee = preg_replace( '|\s*<option|', '<option', $pee );
$pee = preg_replace( '|</option>\s*|', '</option>', $pee );
}
/*
* Collapse line breaks inside <object> elements, before <param> and <embed> elements
* so they don't get autop'd.
*/
if ( strpos( $pee, '</object>' ) !== false ) {
$pee = preg_replace( '|(<object[^>]*>)\s*|', '$1', $pee );
$pee = preg_replace( '|\s*</object>|', '</object>', $pee );
$pee = preg_replace( '%\s*(</?(?:param|embed)[^>]*>)\s*%', '$1', $pee );
}
/*
* Collapse line breaks inside <audio> and <video> elements,
* before and after <source> and <track> elements.
*/
if ( strpos( $pee, '<source' ) !== false || strpos( $pee, '<track' ) !== false ) {
$pee = preg_replace( '%([<\[](?:audio|video)[^>\]]*[>\]])\s*%', '$1', $pee );
$pee = preg_replace( '%\s*([<\[]/(?:audio|video)[>\]])%', '$1', $pee );
$pee = preg_replace( '%\s*(<(?:source|track)[^>]*>)\s*%', '$1', $pee );
}
// Remove more than two contiguous line breaks.
$pee = preg_replace("/\n\n+/", "\n\n", $pee);
// Split up the contents into an array of strings, separated by double line breaks.
$pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY);
// Reset $pee prior to rebuilding.
$pee = '';
// Rebuild the content as a string, wrapping every bit with a <p>.
foreach ( $pees as $tinkle ) {
$pee .= '<p>' . trim($tinkle, "\n") . "</p>\n";
}
// Under certain strange conditions it could create a P of entirely whitespace.
$pee = preg_replace('|<p>\s*</p>|', '', $pee);
// Add a closing <p> inside <div>, <address>, or <form> tag if missing.
$pee = preg_replace('!<p>([^<]+)</(div|address|form)>!', "<p>$1</p></$2>", $pee);
// If an opening or closing block element tag is wrapped in a <p>, unwrap it.
$pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee);
$pee = preg_replace('!<p>\s*(\[/?' . $shortcode_blocks . '[^\]]*\])\s*</p>!', "$1", $pee);
// In some cases <li> may get wrapped in <p>, fix them.
$pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee);
// If a <blockquote> is wrapped with a <p>, move it inside the <blockquote>.
$pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee);
$pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee);
// If an opening or closing block element tag is preceded by an opening <p> tag, remove it.
$pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee);
$pee = preg_replace('!<p>\s*(\[/?' . $allblocks . '[^\]]*\])!', "$1", $pee);
// If an opening or closing block element tag is followed by a closing <p> tag, remove it.
$pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee);
$pee = preg_replace('!(\[/?' . $allblocks . '[^\]]*\])\s*</p>!', "$1", $pee);
// Optionally insert line breaks.
if ( $br ) {
// Replace newlines that shouldn't be touched with a placeholder.
$pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', '_autop_newline_preservation_helper', $pee);
// Normalize <br>
$pee = str_replace( array( '<br>', '<br/>' ), '<br />', $pee );
// Replace any new line characters that aren't preceded by a <br /> with a <br />.
$pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee);
// Replace newline placeholders with newlines.
$pee = str_replace('<WPPreserveNewline />', "\n", $pee);
}
// If a <br /> tag is after an opening or closing block tag, remove it.
$pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee);
$pee = preg_replace('!(\[/?' . $shortcode_blocks . '[^\]]*\])\s*<br />!', "$1", $pee);
// If a <br /> tag is before a subset of opening or closing block tags, remove it.
$pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee);
$pee = preg_replace( "|\n</p>$|", '</p>', $pee );
// Replace placeholder <pre> tags with their original content.
if ( !empty($pre_tags) )
$pee = str_replace(array_keys($pre_tags), array_values($pre_tags), $pee);
// Restore newlines in all elements.
if ( false !== strpos( $pee, '<!-- wpnl -->' ) ) {
$pee = str_replace( array( ' <!-- wpnl --> ', '<!-- wpnl -->' ), "\n", $pee );
}
return $pee;
}
为了解释一下,我们添加了一个$ shortcode_blocks,它与$ allblocks做了同样的事情,基本上使它们被识别为一个块而不仅仅是一个简单的文本。这样,首先这些标记将包含一个段落标记,稍后将删除。
对我有用,所以希望它能为你服务;)