From f7c858fcdfd2e4806155d0952838d40a7880332f Mon Sep 17 00:00:00 2001
From: Steven Wittens <steven@10.no-reply.drupal.org>
Date: Mon, 7 Mar 2005 22:44:54 +0000
Subject: [PATCH] #12369: Linebreak filter should leave <pre> sections alone.

---
 modules/filter.module        | 52 +++++++++++++++++++++++-------------
 modules/filter/filter.module | 52 +++++++++++++++++++++++-------------
 2 files changed, 66 insertions(+), 38 deletions(-)

diff --git a/modules/filter.module b/modules/filter.module
index f1408c945e29..6377215c34df 100644
--- a/modules/filter.module
+++ b/modules/filter.module
@@ -942,27 +942,41 @@ function _filter_html($text, $format) {
 
 /**
  * Convert line breaks into <p> and <br> in an intelligent fashion.
- * From: http://photomatt.net/scripts/autop
+ * Based on: http://photomatt.net/scripts/autop
  */
 function _filter_autop($text) {
-  $text = preg_replace('|\n*$|', '', $text) ."\n\n"; // just to make things a little easier, pad the end
-  $text = preg_replace('|<br />\s*<br />|', "\n\n", $text);
-  $text = preg_replace('!(<(?:table|ul|ol|li|pre|form|blockquote|h[1-6])[^>]*>)!', "\n$1", $text); // Space things out a little
-  $text = preg_replace('!(</(?:table|ul|ol|li|pre|form|blockquote|h[1-6])>)!', "$1\n", $text); // Space things out a little
-  $text = preg_replace("/\n\n+/", "\n\n", $text); // take care of duplicates
-  $text = preg_replace('/\n?(.+?)(?:\n\s*\n|\z)/s', "<p>$1</p>\n", $text); // make paragraphs, including one at the end
-  $text = preg_replace('|<p>\s*?</p>|', '', $text); // under certain strange conditions it could create a P of entirely whitespace
-  $text = preg_replace("|<p>(<li.+?)</p>|", "$1", $text); // problem with nested lists
-  $text = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $text);
-  $text = str_replace('</blockquote></p>', '</p></blockquote>', $text);
-  $text = preg_replace('!<p>\s*(</?(?:table|tr|td|th|div|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)!', "$1", $text);
-  $text = preg_replace('!(</?(?:table|tr|td|th|div|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)\s*</p>!', "$1", $text);
-  $text = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $text); // make line breaks
-  $text = preg_replace('!(</?(?:table|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)\s*<br />!', "$1", $text);
-  $text = preg_replace('!<br />(\s*</?(?:p|li|div|th|pre|td|ul|ol)>)!', '$1', $text);
-  $text = preg_replace('/&([^#])(?![a-z]{1,8};)/', '&#038;$1', $text);
-
-  return $text;
+  // Split at <pre> and </pre> tags
+  $chunks = preg_split('@(</?pre[^>]*>)@', $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).
+  $pre = false;
+  $output = '';
+  foreach ($chunks as $i => $chunk) {
+    if ($i % 2) {
+      // Opening or closing pre tag?
+      $pre = ($chunk{1} != '/');
+    }
+    else if (!$pre) {
+      $chunk = preg_replace('|\n*$|', '', $chunk) ."\n\n"; // just to make things a little easier, pad the end
+      $chunk = preg_replace('|<br />\s*<br />|', "\n\n", $chunk);
+      $chunk = preg_replace('!(<(?:table|ul|ol|li|pre|form|blockquote|h[1-6])[^>]*>)!', "\n$1", $chunk); // Space things out a little
+      $chunk = preg_replace('!(</(?:table|ul|ol|li|pre|form|blockquote|h[1-6])>)!', "$1\n", $chunk); // Space things out a little
+      $chunk = preg_replace("/\n\n+/", "\n\n", $chunk); // take care of duplicates
+      $chunk = preg_replace('/\n?(.+?)(?:\n\s*\n|\z)/s', "<p>$1</p>\n", $chunk); // make paragraphs, including one at the end
+      $chunk = preg_replace('|<p>\s*?</p>|', '', $chunk); // under certain strange conditions it could create a P of entirely whitespace
+      $chunk = preg_replace("|<p>(<li.+?)</p>|", "$1", $chunk); // problem with nested lists
+      $chunk = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $chunk);
+      $chunk = str_replace('</blockquote></p>', '</p></blockquote>', $chunk);
+      $chunk = preg_replace('!<p>\s*(</?(?:table|tr|td|th|div|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)!', "$1", $chunk);
+      $chunk = preg_replace('!(</?(?:table|tr|td|th|div|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)\s*</p>!', "$1", $chunk);
+      $chunk = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $chunk); // make line breaks
+      $chunk = preg_replace('!(</?(?:table|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)\s*<br />!', "$1", $chunk);
+      $chunk = preg_replace('!<br />(\s*</?(?:p|li|div|th|pre|td|ul|ol)>)!', '$1', $chunk);
+      $chunk = preg_replace('/&([^#])(?![a-z]{1,8};)/', '&#038;$1', $chunk);
+    }
+    $output .= $chunk;
+  }
+  return $output;
 }
 
 /**
diff --git a/modules/filter/filter.module b/modules/filter/filter.module
index f1408c945e29..6377215c34df 100644
--- a/modules/filter/filter.module
+++ b/modules/filter/filter.module
@@ -942,27 +942,41 @@ function _filter_html($text, $format) {
 
 /**
  * Convert line breaks into <p> and <br> in an intelligent fashion.
- * From: http://photomatt.net/scripts/autop
+ * Based on: http://photomatt.net/scripts/autop
  */
 function _filter_autop($text) {
-  $text = preg_replace('|\n*$|', '', $text) ."\n\n"; // just to make things a little easier, pad the end
-  $text = preg_replace('|<br />\s*<br />|', "\n\n", $text);
-  $text = preg_replace('!(<(?:table|ul|ol|li|pre|form|blockquote|h[1-6])[^>]*>)!', "\n$1", $text); // Space things out a little
-  $text = preg_replace('!(</(?:table|ul|ol|li|pre|form|blockquote|h[1-6])>)!', "$1\n", $text); // Space things out a little
-  $text = preg_replace("/\n\n+/", "\n\n", $text); // take care of duplicates
-  $text = preg_replace('/\n?(.+?)(?:\n\s*\n|\z)/s', "<p>$1</p>\n", $text); // make paragraphs, including one at the end
-  $text = preg_replace('|<p>\s*?</p>|', '', $text); // under certain strange conditions it could create a P of entirely whitespace
-  $text = preg_replace("|<p>(<li.+?)</p>|", "$1", $text); // problem with nested lists
-  $text = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $text);
-  $text = str_replace('</blockquote></p>', '</p></blockquote>', $text);
-  $text = preg_replace('!<p>\s*(</?(?:table|tr|td|th|div|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)!', "$1", $text);
-  $text = preg_replace('!(</?(?:table|tr|td|th|div|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)\s*</p>!', "$1", $text);
-  $text = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $text); // make line breaks
-  $text = preg_replace('!(</?(?:table|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)\s*<br />!', "$1", $text);
-  $text = preg_replace('!<br />(\s*</?(?:p|li|div|th|pre|td|ul|ol)>)!', '$1', $text);
-  $text = preg_replace('/&([^#])(?![a-z]{1,8};)/', '&#038;$1', $text);
-
-  return $text;
+  // Split at <pre> and </pre> tags
+  $chunks = preg_split('@(</?pre[^>]*>)@', $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).
+  $pre = false;
+  $output = '';
+  foreach ($chunks as $i => $chunk) {
+    if ($i % 2) {
+      // Opening or closing pre tag?
+      $pre = ($chunk{1} != '/');
+    }
+    else if (!$pre) {
+      $chunk = preg_replace('|\n*$|', '', $chunk) ."\n\n"; // just to make things a little easier, pad the end
+      $chunk = preg_replace('|<br />\s*<br />|', "\n\n", $chunk);
+      $chunk = preg_replace('!(<(?:table|ul|ol|li|pre|form|blockquote|h[1-6])[^>]*>)!', "\n$1", $chunk); // Space things out a little
+      $chunk = preg_replace('!(</(?:table|ul|ol|li|pre|form|blockquote|h[1-6])>)!', "$1\n", $chunk); // Space things out a little
+      $chunk = preg_replace("/\n\n+/", "\n\n", $chunk); // take care of duplicates
+      $chunk = preg_replace('/\n?(.+?)(?:\n\s*\n|\z)/s', "<p>$1</p>\n", $chunk); // make paragraphs, including one at the end
+      $chunk = preg_replace('|<p>\s*?</p>|', '', $chunk); // under certain strange conditions it could create a P of entirely whitespace
+      $chunk = preg_replace("|<p>(<li.+?)</p>|", "$1", $chunk); // problem with nested lists
+      $chunk = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $chunk);
+      $chunk = str_replace('</blockquote></p>', '</p></blockquote>', $chunk);
+      $chunk = preg_replace('!<p>\s*(</?(?:table|tr|td|th|div|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)!', "$1", $chunk);
+      $chunk = preg_replace('!(</?(?:table|tr|td|th|div|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)\s*</p>!', "$1", $chunk);
+      $chunk = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $chunk); // make line breaks
+      $chunk = preg_replace('!(</?(?:table|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|p|h[1-6])[^>]*>)\s*<br />!', "$1", $chunk);
+      $chunk = preg_replace('!<br />(\s*</?(?:p|li|div|th|pre|td|ul|ol)>)!', '$1', $chunk);
+      $chunk = preg_replace('/&([^#])(?![a-z]{1,8};)/', '&#038;$1', $chunk);
+    }
+    $output .= $chunk;
+  }
+  return $output;
 }
 
 /**
-- 
GitLab