Fixed bug #5896: Inserting a divider (<hr>) on the RTE breaks XHTML validation
authorStanislas Rolland <typo3@sjbr.ca>
Thu, 23 Dec 2010 00:01:08 +0000 (00:01 +0000)
committerStanislas Rolland <typo3@sjbr.ca>
Thu, 23 Dec 2010 00:01:08 +0000 (00:01 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@9883 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
t3lib/class.t3lib_parsehtml_proc.php
typo3/sysext/cms/tslib/class.tslib_content.php
typo3/sysext/css_styled_content/static/setup.txt

index a42210a..e985206 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
 2010-12-22  Stanislas Rolland  <typo3@sjbr.ca>
 
        * Fixed bug #16823: htmlArea RTE: Abbreviation dialogue and table lack contextual help
+       * Fixed bug #5896: Inserting a divider (<hr>) on the RTE breaks XHTML validation
 
 2010-12-22  Jigal van Hemert <jigal@xs4all.nl>
 
index c7b23a9..863214d 100644 (file)
@@ -91,7 +91,7 @@
 class t3lib_parsehtml_proc extends t3lib_parsehtml {
 
                // Static:
-       var $blockElementList = 'PRE,UL,OL,H1,H2,H3,H4,H5,H6,HR,ADDRESS,DL,DD'; // List of tags for these elements
+       var $blockElementList = 'PRE,UL,OL,H1,H2,H3,H4,H5,H6,ADDRESS,DL,DD'; // List of tags for these elements
 
                // Internal, static:
        var $recPid = 0; // Set this to the pid of the record manipulated by the class.
@@ -898,13 +898,17 @@ class t3lib_parsehtml_proc extends t3lib_parsehtml {
                                                }
                                        break;
                                        default:
-                                                       // Eliminate true linebreaks inside other headlist tags and after hr tag
+                                                       // Eliminate true linebreaks inside other headlist tags
                                                $blockSplit[$k] = preg_replace('/[' . preg_quote(LF . CR) . ']+/', ' ', $this->transformStyledATags($blockSplit[$k])) . $lastBR;
                                        break;
                                }
                        } else { // NON-block:
                                if (strcmp(trim($blockSplit[$k]), '')) {
-                                       $blockSplit[$k] = $this->divideIntoLines(preg_replace('/[' . preg_quote(LF . CR) . ']+/', ' ', $blockSplit[$k])) . $lastBR;
+                                               // Remove linebreaks following hr tags
+                                       $blockSplit[$k] = preg_replace('/<(hr)(\s[^>\/]*)?[[:space:]]*\/?>[' . preg_quote(LF . CR) . ']+/', '<$1$2 />', $blockSplit[$k]);
+                                               // Replace other linebreaks with space
+                                       $blockSplit[$k] = preg_replace('/[' . preg_quote(LF . CR) . ']+/', ' ', $blockSplit[$k]);
+                                       $blockSplit[$k] = $this->divideIntoLines($blockSplit[$k]) . $lastBR;
                                        $blockSplit[$k] = $this->transformStyledATags($blockSplit[$k]);
                                } else {
                                        unset($blockSplit[$k]);
@@ -1222,7 +1226,7 @@ class t3lib_parsehtml_proc extends t3lib_parsehtml {
                }
 
                        // Setting configuration for processing:
-               $allowTagsOutside = t3lib_div::trimExplode(',', strtolower($this->procOptions['allowTagsOutside'] ? $this->procOptions['allowTagsOutside'] : 'img'), 1);
+               $allowTagsOutside = t3lib_div::trimExplode(',', strtolower($this->procOptions['allowTagsOutside'] ? 'hr,' . $this->procOptions['allowTagsOutside'] : 'hr,img'), 1);
                $remapParagraphTag = strtoupper($this->procOptions['remapParagraphTag']);
                $divSplit = $this->splitIntoBlock('div,p', $value, 1); // Setting the third param to 1 will eliminate false end-tags. Maybe this is a good thing to do...?
 
@@ -1234,7 +1238,11 @@ class t3lib_parsehtml_proc extends t3lib_parsehtml {
 
                        // Returns plainly the value if there was no div/p sections in it
                if (count($divSplit) <= 1 || $count <= 0) {
-                       return $value;
+                               // Wrap hr tags with LF's
+                       $newValue = preg_replace('/<(hr)(\s[^>\/]*)?[[:space:]]*\/?>/i', LF . '<$1$2 />' . LF, $value);
+                       $newValue = preg_replace('/' . preg_quote(LF . LF) . '/i', LF, $newValue);
+                       $newValue = preg_replace('/(^' . preg_quote(LF) . ')|(' . preg_quote(LF) . '$)/i', '', $newValue);
+                       return $newValue;
                }
 
                        // Traverse the splitted sections:
@@ -1323,6 +1331,10 @@ class t3lib_parsehtml_proc extends t3lib_parsehtml {
                        } else { // outside div:
                                        // Remove positions which are outside div/p tags and without content
                                $divSplit[$k] = trim(strip_tags($divSplit[$k], '<' . implode('><', $allowTagsOutside) . '>'));
+                                       // Wrap hr tags with LF's
+                               $divSplit[$k] = preg_replace('/<(hr)(\s[^>\/]*)?[[:space:]]*\/?>/i', LF . '<$1$2 />' . LF, $divSplit[$k]);
+                               $divSplit[$k] = preg_replace('/' . preg_quote(LF . LF) . '/i', LF, $divSplit[$k]);
+                               $divSplit[$k] = preg_replace('/(^' . preg_quote(LF) . ')|(' . preg_quote(LF) . '$)/i', '', $divSplit[$k]);
                                if (!strcmp($divSplit[$k], '')) {
                                        unset($divSplit[$k]);
                                } // Remove part if it's empty
@@ -1364,12 +1376,14 @@ class t3lib_parsehtml_proc extends t3lib_parsehtml {
                                }
                        }
 
-                               // Wrapping the line in <$dT> is not already wrapped:
-                       $testStr = strtolower(trim($parts[$k]));
-                       if (substr($testStr, 0, 4) != '<div' || substr($testStr, -6) != '</div>') {
-                               if (substr($testStr, 0, 2) != '<p' || substr($testStr, -4) != '</p>') {
-                                       // Only set p-tags if there is not already div or p tags:
-                                       $parts[$k] = '<' . $dT . '>' . $parts[$k] . '</' . $dT . '>';
+                               // Wrapping the line in <$dT> if not already wrapped and does not contain an hr tag
+                       if (!preg_match('/<(hr)(\s[^>\/]*)?[[:space:]]*\/?>/i', $parts[$k])) {
+                               $testStr = strtolower(trim($parts[$k]));
+                               if (substr($testStr, 0, 4) != '<div' || substr($testStr, -6) != '</div>') {
+                                       if (substr($testStr, 0, 2) != '<p' || substr($testStr, -4) != '</p>') {
+                                               // Only set p-tags if there is not already div or p tags:
+                                               $parts[$k] = '<' . $dT . '>' . $parts[$k] . '</' . $dT . '>';
+                                       }
                                }
                        }
                }
index b3b274c..653aa08 100644 (file)
@@ -4405,7 +4405,7 @@ class tslib_cObj {
                                                $contentAccumP++;
                                                $treated = 1;
                                                        // in-out-tag: img and other empty tags
-                                               if ($tag[0] == 'img' || substr($tag[1], -3, 2) == ' /') {
+                                               if (preg_match('/^(area|base|br|col|hr|img|input|meta|param)$/i', $tag[0])) {
                                                        $tag['out'] = 1;
                                                }
                                        }
@@ -4510,17 +4510,28 @@ class tslib_cObj {
 
                foreach ($lParts as $k => $l) {
                        $sameBeginEnd = 0;
+                       $emptyTag = 0;
                        $l = trim($l);
                        $attrib = array();
                        $nWrapped = 0;
-                       $byPass = 0;
                        if (substr($l, 0, 1) == '<' && substr($l, -1) == '>') {
                                $fwParts = explode('>', substr($l, 1), 2);
-                               $backParts = t3lib_div::revExplode('<', substr($fwParts[1], 0, -1), 2);
-                               $attrib = t3lib_div::get_tag_attributes('<' . $fwParts[0] . '>');
-                               list ($tagName) = explode(' ', $fwParts[0]);
-                               $str_content = $backParts[0];
-                               $sameBeginEnd = (substr(strtolower($backParts[1]), 1, strlen($tagName)) == strtolower($tagName));
+                               list($tagName, $tagParams) = explode(' ',$fwParts[0], 2);
+                               if (!$fwParts[1]) {
+                                       if (substr($tagName, -1) == '/') {
+                                               $tagName = substr($tagName, 0, -1);
+                                       }
+                                       if (substr($fwParts[0], -1) == '/') {
+                                               $sameBeginEnd = 1;
+                                               $emptyTag = 1;
+                                               $attrib = t3lib_div::get_tag_attributes('<'.substr($fwParts[0], 0, -1).'>');
+                                       }
+                               } else {
+                                       $backParts = t3lib_div::revExplode('<', substr($fwParts[1],0,-1), 2);
+                                       $attrib = t3lib_div::get_tag_attributes('<'.$fwParts[0].'>');
+                                       $str_content = $backParts[0];
+                                       $sameBeginEnd = (substr(strtolower($backParts[1]),1,strlen($tagName))==strtolower($tagName));
+                               }
                        }
 
                        if ($sameBeginEnd && in_array(strtolower($tagName), $encapTags)) {
@@ -4564,12 +4575,14 @@ class tslib_cObj {
                                        $attrib['align'] = $defaultAlign;
 
                                $params = t3lib_div::implodeAttributes($attrib, 1);
-                               if ($conf['removeWrapping']) {
+                               if ($conf['removeWrapping'] && !($emptyTag && $conf['removeWrapping.']['keepSingleTag'])) {
                                        $str_content = $str_content;
                                } else {
-                                       $str_content = '<' . strtolower($uTagName) . (trim($params) ? ' ' . trim($params) : '') . '>' .
-                                               $str_content .
-                                               '</' . strtolower($uTagName) . '>';
+                                       if ($emptyTag) {
+                                               $str_content='<'.strtolower($uTagName).(trim($params)?' '.trim($params):'').' />';
+                                       } else {
+                                               $str_content='<'.strtolower($uTagName).(trim($params)?' '.trim($params):'').'>'.$str_content.'</'.strtolower($uTagName).'>';
+                                       }
                                }
                        }
 
index 873f98a..4dcb6bf 100644 (file)
@@ -123,7 +123,7 @@ lib.parseFunc_RTE {
                div.callRecursive = 1
        }
        nonTypoTagStdWrap.encapsLines {
-               encapsTagList = p,pre,h1,h2,h3,h4,h5,h6
+               encapsTagList = p,pre,h1,h2,h3,h4,h5,h6,hr
                remapTag.DIV = P
                nonWrappedTag = P
                innerStdWrap_all.ifBlank = &nbsp;