函数文档

wpautop()

💡 云策文档标注

概述

wpautop() 是一个 WordPress 函数,用于将文本中的双换行符转换为 HTML 段落元素,并可选处理剩余单换行符。

关键要点

  • 核心功能:通过正则表达式识别换行符,将双换行符替换为

    段落标签。

  • 参数说明:$text 参数为必需,指定要格式化的文本;$br 参数为可选布尔值,控制是否将剩余单换行符转换为
    标签。
  • 默认行为:如果 $br 未设置或为 true,转换后剩余的单换行符会变为
    标签;设置为 0 或 false 则禁用此转换。

📄 原文内容

Replaces double line breaks with paragraph elements.

Description

A group of regex replaces used to identify text formatted with newlines and replace double line breaks with HTML paragraph tags. The remaining line breaks after conversion become <br /> tags, unless $br is set to ‘0’ or ‘false’.

Parameters

$textstringrequired
The text which has to be formatted.
$brbooloptional
If set, this will convert all remaining line breaks after paragraphing. Line breaks within <script>, <style>, and <svg> tags are not affected.

Default:true

Return

string Text which has been converted into correct paragraph tags.

More Information

Disabling the filter

Some people choose to disable the wpautop filter from within their theme’s functions.php:

<br>
remove_filter( 'the_content', 'wpautop' );<br>
remove_filter( 'the_excerpt', 'wpautop' );<br>

There’s also a plugin available to enable/disable the filter on a post-by-post basis.

Source

function wpautop( $text, $br = true ) {
	$pre_tags = array();

	if ( '' === trim( $text ) ) {
		return '';
	}

	// Just to make things a little easier, pad the end.
	$text = $text . "n";

	/*
	 * Pre tags shouldn't be touched by autop.
	 * Replace pre tags with placeholders and bring them back after autop.
	 */
	if ( str_contains( $text, '<pre' ) ) {
		$text_parts = explode( '</pre>', $text );
		$last_part  = array_pop( $text_parts );
		$text       = '';
		$i          = 0;

		foreach ( $text_parts as $text_part ) {
			$start = strpos( $text_part, '<pre' );

			// Malformed HTML?
			if ( false === $start ) {
				$text .= $text_part;
				continue;
			}

			$name              = "<pre wp-pre-tag-$i></pre>";
			$pre_tags[ $name ] = substr( $text_part, $start ) . '</pre>';

			$text .= substr( $text_part, 0, $start ) . $name;
			++$i;
		}

		$text .= $last_part;
	}
	// Change multiple <br>'s into two line breaks, which will turn into paragraphs.
	$text = preg_replace( '|<brs*/?>s*<brs*/?>|', "nn", $text );

	$allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|form|map|area|blockquote|address|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.
	$text = preg_replace( '!(<' . $allblocks . '[s/>])!', "nn$1", $text );

	// Add a double line break below block-level closing tags.
	$text = preg_replace( '!(</' . $allblocks . '>)!', "$1nn", $text );

	// Add a double line break after hr tags, which are self closing.
	$text = preg_replace( '!(<hrs*?/?>)!', "$1nn", $text );

	// Standardize newline characters to "n".
	$text = str_replace( array( "rn", "r" ), "n", $text );

	// Find newlines in all elements and add placeholders.
	$text = wp_replace_in_html_tags( $text, array( "n" => ' <!-- wpnl --> ' ) );

	// Collapse line breaks before and after <option> elements so they don't get autop'd.
	if ( str_contains( $text, '<option' ) ) {
		$text = preg_replace( '|s*<option|', '<option', $text );
		$text = preg_replace( '|</option>s*|', '</option>', $text );
	}

	/*
	 * Collapse line breaks inside <object> elements, before <param> and <embed> elements
	 * so they don't get autop'd.
	 */
	if ( str_contains( $text, '</object>' ) ) {
		$text = preg_replace( '|(<object[^>]*>)s*|', '$1', $text );
		$text = preg_replace( '|s*</object>|', '</object>', $text );
		$text = preg_replace( '%s*(</?(?:param|embed)[^>]*>)s*%', '$1', $text );
	}

	/*
	 * Collapse line breaks inside <audio> and <video> elements,
	 * before and after <source> and <track> elements.
	 */
	if ( str_contains( $text, '<source' ) || str_contains( $text, '<track' ) ) {
		$text = preg_replace( '%([<[](?:audio|video)[^>]]*[>]])s*%', '$1', $text );
		$text = preg_replace( '%s*([<[]/(?:audio|video)[>]])%', '$1', $text );
		$text = preg_replace( '%s*(<(?:source|track)[^>]*>)s*%', '$1', $text );
	}

	// Collapse line breaks before and after <figcaption> elements.
	if ( str_contains( $text, '<figcaption' ) ) {
		$text = preg_replace( '|s*(<figcaption[^>]*>)|', '$1', $text );
		$text = preg_replace( '|</figcaption>s*|', '</figcaption>', $text );
	}

	// Remove more than two contiguous line breaks.
	$text = preg_replace( "/nn+/", "nn", $text );

	// Split up the contents into an array of strings, separated by double line breaks.
	$paragraphs = preg_split( '/ns*n/', $text, -1, PREG_SPLIT_NO_EMPTY );

	// Reset $text prior to rebuilding.
	$text = '';

	// Rebuild the content as a string, wrapping every bit with a <p>.
	foreach ( $paragraphs as $paragraph ) {
		$text .= '<p>' . trim( $paragraph, "n" ) . "</p>n";
	}

	// Under certain strange conditions it could create a P of entirely whitespace.
	$text = preg_replace( '|<p>s*</p>|', '', $text );

	// Add a closing <p> inside <div>, <address>, or <form> tag if missing.
	$text = preg_replace( '!<p>([^<]+)</(div|address|form)>!', '<p>$1</p></$2>', $text );

	// If an opening or closing block element tag is wrapped in a <p>, unwrap it.
	$text = preg_replace( '!<p>s*(</?' . $allblocks . '[^>]*>)s*</p>!', '$1', $text );

	// In some cases <li> may get wrapped in <p>, fix them.
	$text = preg_replace( '|<p>(<li.+?)</p>|', '$1', $text );

	// If a <blockquote> is wrapped with a <p>, move it inside the <blockquote>.
	$text = preg_replace( '|<p><blockquote([^>]*)>|i', '<blockquote$1><p>', $text );
	$text = str_replace( '</blockquote></p>', '</p></blockquote>', $text );

	// If an opening or closing block element tag is preceded by an opening <p> tag, remove it.
	$text = preg_replace( '!<p>s*(</?' . $allblocks . '[^>]*>)!', '$1', $text );

	// If an opening or closing block element tag is followed by a closing <p> tag, remove it.
	$text = preg_replace( '!(</?' . $allblocks . '[^>]*>)s*</p>!', '$1', $text );

	// Optionally insert line breaks.
	if ( $br ) {
		// Replace newlines that shouldn't be touched with a placeholder.
		$text = preg_replace_callback( '/<(script|style|svg|math).*?</\1>/s', '_autop_newline_preservation_helper', $text );

		// Normalize <br>.
		$text = str_replace( array( '<br>', '<br/>' ), '<br />', $text );

		// Replace any new line characters that aren't preceded by a <br /> with a <br />.
		$text = preg_replace( '|(?<!<br />)s*n|', "<br />n", $text );

		// Replace newline placeholders with newlines.
		$text = str_replace( '<WPPreserveNewline />', "n", $text );
	}

	// If a <br /> tag is after an opening or closing block tag, remove it.
	$text = preg_replace( '!(</?' . $allblocks . '[^>]*>)s*<br />!', '$1', $text );

	// If a <br /> tag is before a subset of opening or closing block tags, remove it.
	$text = preg_replace( '!<br />(s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $text );
	$text = preg_replace( "|n</p>$|", '</p>', $text );

	// Replace placeholder <pre> tags with their original content.
	if ( ! empty( $pre_tags ) ) {
		$text = str_replace( array_keys( $pre_tags ), array_values( $pre_tags ), $text );
	}

	// Restore newlines in all elements.
	if ( str_contains( $text, '<!-- wpnl -->' ) ) {
		$text = str_replace( array( ' <!-- wpnl --> ', '<!-- wpnl -->' ), "n", $text );
	}

	return $text;
}

Changelog

Version Description
0.71 Introduced.

User Contributed Notes

  1. Skip to note 4 content

    If you have problems with wpautop adding paragraphs where you don’t want them, you can disable it in the content of your pages by adding the following to your child theme’s functions.php file:

    // Stop WP adding extra <p> </p> to your pages' content
    remove_filter( 'the_content', 'wpautop' );

  2. Skip to note 5 content

    Basic usage

    <?php
    $some_long_text = // Start Text
    Some long text
    that has many lines
    
    and paragraphs in it.
    // end text
    
    echo wpautop( $some_long_text );
    ?>

    This should echo the string with tags around the paragraphs, like this:

    <p>Some long text<br/>
    that has many lines</p>
    <p>and paragraphs in it.</p>

You must log in before being able to contribute a note or feedback.

{“prefetch”:[{“source”:”document”,”where”:{“and”:[{“href_matches”:”/*”},{“not”:{“href_matches”:[“/wp-*.php”,”/wp-admin/*”,”/files/*”,”/wp-content/*”,”/wp-content/plugins/*”,”/wp-content/themes/wporg-developer-2023/*”,”/wp-content/themes/wporg-parent-2021/*”,”/*\?(.+)”]}},{“not”:{“selector_matches”:”a[rel~=”nofollow”]”}},{“not”:{“selector_matches”:”.no-prefetch, .no-prefetch a”}}]},”eagerness”:”conservative”}]}

var prism_settings = {“pluginUrl”:”https://developer.wordpress.org/wp-content/plugins/code-syntax-block/”};
//# sourceURL=mkaz-code-syntax-prism-js-js-extra

var autocomplete = {“ajaxurl”:”https://developer.wordpress.org/wp-admin/admin-ajax.php”,”nonce”:”dc6f8fe9ee”,”post_type”:”wp-parser-function”};
//# sourceURL=autocomplete-js-extra

wp.i18n.setLocaleData( { ‘text directionu0004ltr’: [ ‘ltr’ ] } );
//# sourceURL=wp-i18n-js-after

var wporgFunctionReferenceI18n = {“copy”:”Copy”,”copied”:”Code copied”,”expand”:”Expand code”,”collapse”:”Collapse code”,”sourceFile”:”wp-includes/formatting.php”};
//# sourceURL=wporg-developer-function-reference-js-extra

var quicktagsL10n = {“closeAllOpenTags”:”Close all open tags”,”closeTags”:”close tags”,”enterURL”:”Enter the URL”,”enterImageURL”:”Enter the URL of the image”,”enterImageDescription”:”Enter a description of the image”,”textdirection”:”text direction”,”toggleTextdirection”:”Toggle Editor Text Direction”,”dfw”:”Distraction-free writing mode”,”strong”:”Bold”,”strongClose”:”Close bold tag”,”em”:”Italic”,”emClose”:”Close italic tag”,”link”:”Insert link”,”blockquote”:”Blockquote”,”blockquoteClose”:”Close blockquote tag”,”del”:”Deleted text (strikethrough)”,”delClose”:”Close deleted text tag”,”ins”:”Inserted text”,”insClose”:”Close inserted text tag”,”image”:”Insert image”,”ul”:”Bulleted list”,”ulClose”:”Close bulleted list tag”,”ol”:”Numbered list”,”olClose”:”Close numbered list tag”,”li”:”List item”,”liClose”:”Close list item tag”,”code”:”Code”,”codeClose”:”Close code tag”,”more”:”Insert Read More tag”};
//# sourceURL=quicktags-js-extra

var wporg_note_feedback = {“show”:”Show feedback”,”hide”:”Hide feedback”,”hide_feedback”:”Hide feedback form”,”add_feedback”:”Add feedback”};
//# sourceURL=wporg-developer-user-notes-feedback-js-extra

var wporg_note_preview = {“ajaxurl”:”https://developer.wordpress.org/wp-admin/admin-ajax.php”,”nonce”:”119215fa41″,”preview”:”preview note”,”preview_empty”:”Nothing to preview”,”is_admin”:””};
//# sourceURL=wporg-developer-preview-js-extra

_stq = window._stq || [];
_stq.push([ “view”, {“v”:”ext”,”blog”:”209306761″,”post”:”3421″,”tz”:”0″,”srv”:”developer.wordpress.org”,”j”:”1:15.5″} ]);
_stq.push([ “clickTrackerInit”, “209306761”, “3421” ]);
//# sourceURL=jetpack-stats-js-before

var wporgGlobalHeaderI18n = {“openSearchLabel”:”Open Search”,”closeSearchLabel”:”Close Search”,”overflowMenuLabel”:”More menu”};
//# sourceURL=wporg-global-header-script-js-extra

{“baseUrl”:”https://s.w.org/images/core/emoji/17.0.2/72×72/”,”ext”:”.png”,”svgUrl”:”https://s.w.org/images/core/emoji/17.0.2/svg/”,”svgExt”:”.svg”,”source”:{“concatemoji”:”https://developer.wordpress.org/wp-includes/js/wp-emoji-release.min.js?ver=7.1-alpha-62239″}}

/*! This file is auto-generated */
const a=JSON.parse(document.getElementById(“wp-emoji-settings”).textContent),o=(window._wpemojiSettings=a,”wpEmojiSettingsSupports”),s=[“flag”,”emoji”];function i(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(o,JSON.stringify(t))}catch(e){}}function c(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0);const a=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);return t.every((e,t)=>e===a[t])}function p(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var n=e.getImageData(16,16,1,1);for(let e=0;e{s[e]=t(o,e,n,a)}),s}function r(e){var t=document.createElement(“script”);t.src=e,t.defer=!0,document.head.appendChild(t)}a.supports={everything:!0,everythingExceptFlag:!0},new Promise(t=>{let n=function(){try{var e=JSON.parse(sessionStorage.getItem(o));if(“object”==typeof e&&”number”==typeof e.timestamp&&(new Date).valueOf(){i(n=e.data),r.terminate(),t(n)})}catch(e){}i(n=f(s,u,c,p))}t(n)}).then(e=>{for(const n in e)a.supports[n]=e[n],a.supports.everything=a.supports.everything&&a.supports[n],”flag”!==n&&(a.supports.everythingExceptFlag=a.supports.everythingExceptFlag&&a.supports[n]);var t;a.supports.everythingExceptFlag=a.supports.everythingExceptFlag&&!a.supports.flag,a.supports.everything||((t=a.source||{}).concatemoji?r(t.concatemoji):t.wpemoji&&t.twemoji&&(r(t.twemoji),r(t.wpemoji)))});
//# sourceURL=https://developer.wordpress.org/wp-includes/js/wp-emoji-loader.min.js