Wordpress插入开放 在我的短代码中标记

问题描述 投票:1回答:5

我写了一个小函数来在我的首页上显示最新的视频。功能本身工作得很好。唯一的问题是,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 &#8211; Part 1</p>
<div class="orange-button">Watch Video</div>
<p></a></div>
<div class="clear"></div>

我试过几种方法删除wp-autop过滤器,但它根本无法工作。即使使用谷歌超过两个小时,我现在无法找到解决方案。

php wordpress
5个回答
1
投票

好的。经过长时间的搜索(得到史蒂夫的大量帮助),我终于找到了解决方案。我从中获取了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行。

所有这一切都让它为我工作。


1
投票

这是多年来的一个已知问题。请看看Wordpress Ticket

正如之前提到的其他人一样,有一个插件可以解决这个问题。它被称为“Shortcode Empty Paragraph Fix”。它不是最好的解决方案,但也不是那么糟糕。

我不喜欢给我的wp安装带来很多膨胀 - 所以我将短代码包装在没有类的div中并修复了问题。

<div> [woocommerce_cart] </div>

我希望这个问题会在接下来的几年中得到解决;)所以我可以删除我的div - 在我看来是一种更安全的方式,因为有时候funcitons.php中的额外功能可能会导致一些问题。


0
投票

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>

你的选择是;

  1. 将所有新行修剪为您的短代码生成的内容,尽管这不是一个好主意,因为HTML上没有新行会影响CSS属性

return trim(preg_replace('/\s+/', ' ', $string));

  1. 使用自定义格式化程序覆盖wordpress默认自动格式化程序,

下面这段代码是我主题的内置函数


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]这样的短代码


0
投票

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/


0
投票

我有同样的问题,因为上面没有任何真正有用的东西,我决定解决它。所以这是我的解决方案(虽然只适用于具有结束标签的短代码)。

就这样我们都在同一页面上,如果我们在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做了同样的事情,基本上使它们被识别为一个块而不仅仅是一个简单的文本。这样,首先这些标记将包含一个段落标记,稍后将删除。

对我有用,所以希望它能为你服务;)

© www.soinside.com 2019 - 2024. All rights reserved.