diff --git a/program/lib/Roundcube/rcube_text2html.php b/program/lib/Roundcube/rcube_text2html.php
index 2ffe5301d..5c240d515 100644
--- a/program/lib/Roundcube/rcube_text2html.php
+++ b/program/lib/Roundcube/rcube_text2html.php
@@ -46,10 +46,6 @@ class rcube_text2html
protected $config = array(
// non-breaking space
'space' => "\xC2\xA0",
- // word-joiner (zero-width no-break space)
- // 'wordjoiner' => "\xEF\xBB\xBF", // U+2060
- // use deprecated U+FEFF character because of webkit issue with displaying U+2060 (#1490353)
- 'wordjoiner' => "\xEF\xBB\xBF", // U+FEFF
// enables format=flowed parser
'flowed' => false,
// enables wrapping for non-flowed text
@@ -63,6 +59,9 @@ class rcube_text2html
'links' => true,
// string replacer class
'replacer' => 'rcube_string_replacer',
+ // prefix and suffix of unwrappable line
+ 'nobr_start' => '',
+ 'nobr_end' => '',
);
@@ -281,12 +280,11 @@ class rcube_text2html
// replace HTML special characters
$text = strtr($text, $table);
- $nbsp = $this->config['space'];
- $nobr = $this->config['wordjoiner'];
-
// replace some whitespace characters
$text = str_replace(array("\r", "\t"), array('', ' '), $text);
+ $nbsp = $this->config['space'];
+
// replace spaces with non-breaking spaces
if ($is_flowed) {
$pos = 0;
@@ -304,15 +302,13 @@ class rcube_text2html
$text = $copy;
}
- // make the whole line non-breakable
- else {
- $repl = array(
- ' ' => $nbsp,
- '-' => $nobr . '-' . $nobr,
- '/' => $nobr . '/',
- );
-
- $text = str_replace(array_keys($repl), array_values($repl), $text);
+ // make the whole line non-breakable if needed
+ else if ($text !== '' && preg_match('/[^a-zA-Z0-9_]/', $text)) {
+ // use non-breakable spaces to correctly display
+ // trailing/leading spaces and multi-space inside
+ $text = str_replace(' ', $nbsp, $text);
+ // wrap in nobr element, so it's not wrapped on e.g. - or /
+ $text = $this->config['nobr_start'] . $text . $this->config['nobr_end'];
}
return $text;
diff --git a/tests/Framework/Text2Html.php b/tests/Framework/Text2Html.php
index 771e14703..a08f9c036 100644
--- a/tests/Framework/Text2Html.php
+++ b/tests/Framework/Text2Html.php
@@ -21,49 +21,53 @@ class Framework_Text2Html extends PHPUnit_Framework_TestCase
'flowed' => false,
'wrap' => false,
'space' => '_', // replace UTF-8 non-breaking space for simpler testing
+ 'nobr_start' => '>',
+ 'nobr_end' => '<',
);
- $data[] = array(" aaaa", "_aaaa", $options);
- $data[] = array("aaaa aaaa", "aaaa_aaaa", $options);
- $data[] = array("aaaa aaaa", "aaaa__aaaa", $options);
- $data[] = array("aaaa aaaa", "aaaa___aaaa", $options);
- $data[] = array("aaaa\taaaa", "aaaa____aaaa", $options);
+ $data[] = array(" aaaa", ">_aaaa<", $options);
+ $data[] = array("aa>aa", ">aa>aa<", $options);
+ $data[] = array("aaaa aaaa", ">aaaa_aaaa<", $options);
+ $data[] = array("aaaa aaaa", ">aaaa__aaaa<", $options);
+ $data[] = array("aaaa aaaa", ">aaaa___aaaa<", $options);
+ $data[] = array("aaaa\taaaa", ">aaaa____aaaa<", $options);
$data[] = array("aaaa\naaaa", "aaaa
aaaa", $options);
- $data[] = array("aaaa\n aaaa", "aaaa
_aaaa", $options);
- $data[] = array("aaaa\n aaaa", "aaaa
__aaaa", $options);
- $data[] = array("aaaa\n aaaa", "aaaa
___aaaa", $options);
- $data[] = array("\taaaa", "____aaaa", $options);
+ $data[] = array("aaaa\n aaaa", "aaaa
>_aaaa<", $options);
+ $data[] = array("aaaa\n aaaa", "aaaa
>__aaaa<", $options);
+ $data[] = array("aaaa\n aaaa", "aaaa
>___aaaa<", $options);
+ $data[] = array("\n", "
", $options);
+ $data[] = array("\taaaa", ">____aaaa<", $options);
$data[] = array("\naaaa", "
aaaa", $options);
- $data[] = array("\n aaaa", "
_aaaa", $options);
- $data[] = array("\n aaaa", "
__aaaa", $options);
- $data[] = array("\n aaaa", "
___aaaa", $options);
+ $data[] = array("\n aaaa", "
>_aaaa<", $options);
+ $data[] = array("\n aaaa", "
>__aaaa<", $options);
+ $data[] = array("\n aaaa", "
>___aaaa<", $options);
$data[] = array("aaaa\n\nbbbb", "aaaa
bbbb", $options);
- $data[] = array(">aaaa \n>aaaa", "
aaaa_", $options); + $data[] = array(">aaaa \n>aaaa", "
aaaa
>aaaa_<", $options); $data[] = array(">aaaa\n>aaaa", "
aaaa
aaaa", $options); - $data[] = array(">aaaa \n>bbbb\ncccc dddd", "
aaaa
aaaa_cccc_dddd", $options); - $data[] = array("aaaa-bbbb/cccc", "aaaa\xEF\xBB\xBF-\xEF\xBB\xBFbbbb\xEF\xBB\xBF/cccc", $options); + $data[] = array(">aaaa \n>bbbb\ncccc dddd", "
bbbb
>aaaa_<>cccc_dddd<", $options); + $data[] = array("aaaa-bbbb/cccc", ">aaaa-bbbb/cccc<", $options); $options['flowed'] = true; $data[] = array(" aaaa", "aaaa", $options); - $data[] = array("aaaa aaaa", "aaaa_aaaa", $options); - $data[] = array("aaaa aaaa", "aaaa__aaaa", $options); - $data[] = array("aaaa aaaa", "aaaa___aaaa", $options); - $data[] = array("aaaa\taaaa", "aaaa____aaaa", $options); + $data[] = array("aaaa aaaa", ">aaaa_aaaa<", $options); + $data[] = array("aaaa aaaa", ">aaaa__aaaa<", $options); + $data[] = array("aaaa aaaa", ">aaaa___aaaa<", $options); + $data[] = array("aaaa\taaaa", ">aaaa____aaaa<", $options); $data[] = array("aaaa\naaaa", "aaaa
bbbb
aaaa aaaa", $options); $data[] = array(">aaaa\n>aaaa", "
aaaa", $options); - $data[] = array(">aaaa \n>bbbb\ncccc dddd", "
aaaa
aaaa bbbbcccc_dddd", $options); - $data[] = array(chr(0x002).chr(0x003), chr(0x002).chr(0x003), $options); + $data[] = array(">aaaa \n>bbbb\ncccc dddd", "
aaaa bbbb>cccc_dddd<", $options); + $data[] = array("\x02\x03", ">\x02\x03<", $options); $options['flowed'] = false; $options['wrap'] = true;