function _filter_autop
Same name in other branches
- 7.x modules/filter/filter.module \_filter_autop()
- 9 core/modules/filter/filter.module \_filter_autop()
- 8.9.x core/modules/filter/filter.module \_filter_autop()
- 10 core/modules/filter/filter.module \_filter_autop()
Converts line breaks into <p> and <br> in an intelligent fashion.
Based on: http://photomatt.net/scripts/autop
Related topics
3 calls to _filter_autop()
- FilterAutoP::process in core/
modules/ filter/ src/ Plugin/ Filter/ FilterAutoP.php - Performs the filter processing.
- FilterKernelTest::testLineBreakFilter in core/
modules/ filter/ tests/ src/ Kernel/ FilterKernelTest.php - Tests the line break filter.
- FilterKernelTest::testLineBreakFilterTwigDebug in core/
modules/ filter/ tests/ src/ Kernel/ FilterKernelTest.php - Tests that the line break filter does not apply to twig debug.
File
-
core/
modules/ filter/ filter.module, line 631
Code
function _filter_autop($text) {
// All block level tags
$block = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|option|form|map|area|blockquote|address|math|input|p|h[1-6]|fieldset|legend|hr|article|aside|details|figcaption|figure|footer|header|hgroup|menu|nav|section|summary)';
// Split at opening and closing PRE, SCRIPT, STYLE, OBJECT, IFRAME tags
// and comments. We don't apply any processing to the contents of these tags
// to avoid messing up code. We look for matched pairs and allow basic
// nesting. For example:
// "processed <pre> ignored <script> ignored </script> ignored </pre> processed"
$chunks = preg_split('@(<!--.*?-->|</?(?:pre|script|style|object|iframe|drupal-media|svg|!--)[^>]*>)@i', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
// Note: PHP ensures the array consists of alternating delimiters and literals
// and begins and ends with a literal (inserting NULL as required).
$ignore = FALSE;
$ignore_tag = '';
$output = '';
foreach ($chunks as $i => $chunk) {
if ($i % 2) {
if (str_starts_with($chunk, '<!--')) {
// Nothing to do, this is a comment.
$output .= $chunk;
continue;
}
// Opening or closing tag?
$open = $chunk[1] != '/';
[
$tag,
] = preg_split('/[ >]/', substr($chunk, 2 - $open), 2);
if (!$ignore) {
if ($open) {
$ignore = TRUE;
$ignore_tag = $tag;
}
}
elseif (!$open && $ignore_tag == $tag) {
$ignore = FALSE;
$ignore_tag = '';
}
}
elseif (!$ignore) {
// Skip if the next chunk starts with Twig theme debug.
// @see twig_render_template()
if (isset($chunks[$i + 1]) && $chunks[$i + 1] === '<!-- THEME DEBUG -->') {
$chunk = rtrim($chunk, "\n");
$output .= $chunk;
continue;
}
// Skip if the preceding chunk was the end of a Twig theme debug.
// @see twig_render_template()
if (isset($chunks[$i - 1])) {
if (str_starts_with($chunks[$i - 1], '<!-- BEGIN OUTPUT from ') || str_starts_with($chunks[$i - 1], '<!-- 💡 BEGIN CUSTOM TEMPLATE OUTPUT from ')) {
$chunk = ltrim($chunk, "\n");
$output .= $chunk;
continue;
}
}
// Just to make things a little easier, pad the end
$chunk = preg_replace('|\\n*$|', '', $chunk) . "\n\n";
$chunk = preg_replace('|<br />\\s*<br />|', "\n\n", $chunk);
// Space things out a little
$chunk = preg_replace('!(<' . $block . '[^>]*>)!', "\n\$1", $chunk);
// Space things out a little
$chunk = preg_replace('!(</' . $block . '>)!', "\$1\n\n", $chunk);
// Take care of duplicates
$chunk = preg_replace("/\n\n+/", "\n\n", $chunk);
$chunk = preg_replace('/^\\n|\\n\\s*\\n$/', '', $chunk);
// Make paragraphs, including one at the end
$chunk = '<p>' . preg_replace('/\\n\\s*\\n\\n?(.)/', "</p>\n<p>\$1", $chunk) . "</p>\n";
// Problem with nested lists
$chunk = preg_replace("|<p>(<li.+?)</p>|", "\$1", $chunk);
$chunk = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote\$1><p>", $chunk);
$chunk = str_replace('</blockquote></p>', '</p></blockquote>', $chunk);
// Under certain strange conditions it could create a P of entirely whitespace
$chunk = preg_replace('|<p>\\s*</p>\\n?|', '', $chunk);
$chunk = preg_replace('!<p>\\s*(</?' . $block . '[^>]*>)!', "\$1", $chunk);
$chunk = preg_replace('!(</?' . $block . '[^>]*>)\\s*</p>!', "\$1", $chunk);
// Make line breaks
$chunk = preg_replace('|(?<!<br />)\\s*\\n|', "<br />\n", $chunk);
$chunk = preg_replace('!(</?' . $block . '[^>]*>)\\s*<br />!', "\$1", $chunk);
$chunk = preg_replace('!<br />(\\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)!', '$1', $chunk);
$chunk = preg_replace('/&([^#])(?![A-Za-z0-9]{1,8};)/', '&$1', $chunk);
}
$output .= $chunk;
}
return $output;
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.