diff --git a/include/bbcode.php b/include/bbcode.php
index db4147c1e..86944ba60 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -1054,6 +1054,15 @@ function bb_fixtable_lf($match) {
}
+function bb_fix_lf($match) {
+ // remove extraneous whitespace between element tags since newlines will all
+ // be converted to '
' and turn your neatly crafted tables into a whole lot of
+ // empty space.
+
+ $new_content = str_replace(["\n\r", "\n", "\r"], '', $match[1]);
+ return str_replace($match[1], $new_content, $match[0]);
+}
+
function bbtopoll($s) {
$pl = [];
@@ -1207,8 +1216,6 @@ function bbcode($text, $options = []) {
}
}
-
-
$text = bb_format_attachdata($text);
// If we find any event code, turn it into an event.
@@ -1249,7 +1256,7 @@ function bbcode($text, $options = []) {
$text = str_replace("<", "<", $text);
$text = str_replace(">", ">", $text);
- $text = preg_replace_callback("/\[table\](.*?)\[\/table\]/ism",'bb_fixtable_lf',$text);
+
$text = str_replace(array("\t", " "), array(" ", " "), $text);
// Check for [code] text here, before the linefeeds are messed with.
@@ -1487,10 +1494,10 @@ function bbcode($text, $options = []) {
// Check for list text
- $text = preg_replace("/
\[\*\]/ism",'[*]',$text);
-
+ $text = str_replace(["\r\n[*]", "\r[*]", "\n[*]"], "[*]", $text);
$text = str_replace("[*]", "
", $text);
+
// handle nested lists
$endlessloop = 0;
@@ -1499,16 +1506,35 @@ function bbcode($text, $options = []) {
((strpos($text, "[/ul]") !== false) && (strpos($text, "[ul]") !== false)) ||
((strpos($text, "[/dl]") !== false) && (strpos($text, "[dl") !== false)) ||
((strpos($text, "[/li]") !== false) && (strpos($text, "[li]") !== false))) && (++$endlessloop < 20)) {
+
+ $text = preg_replace_callback("/\[list\](.*?)\[\/list\]/ism",'bb_fix_lf', $text);
$text = preg_replace("/\[list\](.*?)\[\/list\]/ism", '', $text);
+
+ $text = preg_replace_callback("/\[list=\](.*?)\[\/list\]/ism",'bb_fix_lf', $text);
$text = preg_replace("/\[list=\](.*?)\[\/list\]/ism", '', $text);
+
+ $text = preg_replace_callback("/\[list=1\](.*?)\[\/list\]/ism",'bb_fix_lf', $text);
$text = preg_replace("/\[list=1\](.*?)\[\/list\]/ism", '', $text);
+
+ $text = preg_replace_callback("/\[list=((?-i)i)\](.*?)\[\/list\]/ism",'bb_fix_lf', $text);
$text = preg_replace("/\[list=((?-i)i)\](.*?)\[\/list\]/ism",'', $text);
+
+ $text = preg_replace_callback("/\[list=((?-i)I)\](.*?)\[\/list\]/ism",'bb_fix_lf', $text);
$text = preg_replace("/\[list=((?-i)I)\](.*?)\[\/list\]/ism", '', $text);
+
+ $text = preg_replace_callback("/\[list=((?-i)a)\](.*?)\[\/list\]/ism",'bb_fix_lf', $text);
$text = preg_replace("/\[list=((?-i)a)\](.*?)\[\/list\]/ism", '', $text);
+
+ $text = preg_replace_callback("/\[list=((?-i)A)\](.*?)\[\/list\]/ism",'bb_fix_lf', $text);
$text = preg_replace("/\[list=((?-i)A)\](.*?)\[\/list\]/ism", '', $text);
- $text = preg_replace("/\[ul\](.*?)\[\/ul\]/ism", '', $text);
+
+ $text = preg_replace_callback("/\[ol\](.*?)\[\/ol\]/ism",'bb_fix_lf', $text);
$text = preg_replace("/\[ol\](.*?)\[\/ol\]/ism", '', $text);
- $text = preg_replace("/\[\/li\]
\[li\]/ism",'[/li][li]',$text);
+
+ $text = preg_replace_callback("/\[ul\](.*?)\[\/ul\]/ism",'bb_fix_lf', $text);
+ $text = preg_replace("/\[ul\](.*?)\[\/ul\]/ism", '', $text);
+
+ $text = preg_replace("/\[\/li\]
\[li\]/ism",'[/li][li]', $text);
$text = preg_replace("/\[li\](.*?)\[\/li\]/ism", '$1', $text);
// [dl] tags have an optional [dl terms="bi"] form where bold/italic/underline/mono/large
@@ -1521,24 +1547,29 @@ function bbcode($text, $options = []) {
}
if (strpos($text,'[checklist]') !== false) {
+ $text = preg_replace_callback("/\[checklist\](.*?)\[\/checklist\]/ism",'bb_fix_lf', $text);
$text = preg_replace_callback("/\[checklist\](.*?)\[\/checklist\]/ism", 'bb_checklist', $text);
}
if (strpos($text,'[th]') !== false) {
$text = preg_replace("/\[th\](.*?)\[\/th\]/sm", '$1 | ', $text);
}
+
if (strpos($text,'[td]') !== false) {
$text = preg_replace("/\[td\](.*?)\[\/td\]/sm", '$1 | ', $text);
}
+
if (strpos($text,'[tr]') !== false) {
$text = preg_replace("/\[tr\](.*?)\[\/tr\]/sm", '$1
', $text);
}
+
if (strpos($text,'[/table]') !== false) {
+ $text = preg_replace_callback("/\[table\](.*?)\[\/table\]/ism",'bb_fix_lf',$text);
$text = preg_replace("/\[table\](.*?)\[\/table\]/sm", '', $text);
$text = preg_replace("/\[table border=1\](.*?)\[\/table\]/sm", '', $text);
$text = preg_replace("/\[table border=0\](.*?)\[\/table\]/sm", '', $text);
}
- $text = str_replace('
', "
\n", $text);
+
$text = str_replace('[hr]', '
', $text);
// This is actually executed in prepare_body()
diff --git a/tests/unit/includes/BBCodeTest.php b/tests/unit/includes/BBCodeTest.php
index 6f79c45f4..100d28fc4 100644
--- a/tests/unit/includes/BBCodeTest.php
+++ b/tests/unit/includes/BBCodeTest.php
@@ -107,6 +107,18 @@ class BBCodeTest extends UnitTestCase {
"[code]\ntestvar = \"this is a test\"\necho \"the message is \$testvar\"\n[/code]",
'testvar = "this is a test"
echo "the message is $testvar"
',
],
+ 'list with linebreaks \n' => [
+ "some text\n[list]\n[*] item1\n[*] item2\n[/list]\nsome more text",
+ 'some text
some more text'
+ ],
+ 'list with linebreaks \r' => [
+ "some text\r[list]\r[*] item1\r[*] item2\r[/list]\rsome more text",
+ 'some text
some more text'
+ ],
+ 'list with linebreaks \r\n' => [
+ "some text\r\n[list]\r\n[*] item1\r\n[*] item2\r\n[/list]\r\nsome more text",
+ 'some text
some more text'
+ ]
];
}
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 9c1c3eb6a..4386e70b5 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -3,7 +3,7 @@
'name' => 'zotlabs/hubzilla',
'pretty_version' => 'dev-9.0RC',
'version' => 'dev-9.0RC',
- 'reference' => '8754f72e63ea0fd9067c20104a2b068e5c518d0a',
+ 'reference' => 'a18e873d08e733225c70b0ace31c3cbb025ff906',
'type' => 'application',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -340,7 +340,7 @@
'zotlabs/hubzilla' => array(
'pretty_version' => 'dev-9.0RC',
'version' => 'dev-9.0RC',
- 'reference' => '8754f72e63ea0fd9067c20104a2b068e5c518d0a',
+ 'reference' => 'a18e873d08e733225c70b0ace31c3cbb025ff906',
'type' => 'application',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),