Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/roundcube/roundcubemail.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <alec@alec.pl>2022-01-09 18:29:09 +0300
committerAleksander Machniak <alec@alec.pl>2022-01-09 18:29:09 +0300
commita5fd2117128a1e81912fcfb6671ce4a16cd7f6d4 (patch)
tree2375e87a4a417b667b39e2464db9261d42226cb3
parent953be4bbe1a15e324714dcc3289c177425af618b (diff)
Improve/Fix wrapping of plain text messages on preview and reply (#6974, #8391, #8378, #8289)
In short, we always wrap, but we detect patches/diffs in the text and make them unwrappable.
-rw-r--r--CHANGELOG.md2
-rw-r--r--program/actions/mail/index.php1
-rw-r--r--program/lib/Roundcube/rcube_text2html.php52
-rw-r--r--skins/elastic/styles/styles.less12
-rw-r--r--tests/Framework/Text2Html.php39
5 files changed, 91 insertions, 15 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4bc3cca6d..8145d677a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,7 +33,7 @@
- Add option to purge deleted mails older than 30, 60 or 90 days (#5493)
- Add ability to mark multiple messages as not deleted at once (#5133)
- Add possibility to disable line-wrapping of sent mail body (#5101)
-- Improve auto-wrapping of plain text messages on preview and reply, don't wrap non-format=flowed content (#6974)
+- Improve/Fix wrapping of plain text messages on preview and reply (#6974, #8391, #8378, #8289)
- Improve searching by sender/recipient headers, support Reply-To and Followup-To (#6582)
- Add option to control links handling behavior on html to text conversion (#6485)
- Add 'loginform_content' plugin hook (#8273, #6569)
diff --git a/program/actions/mail/index.php b/program/actions/mail/index.php
index 76f1c5da2..428329449 100644
--- a/program/actions/mail/index.php
+++ b/program/actions/mail/index.php
@@ -1066,7 +1066,6 @@ class rcmail_action_mail_index extends rcmail_action
{
$options = [
'flowed' => $flowed,
- 'wrap' => $flowed,
'replacer' => 'rcmail_string_replacer',
'delsp' => $delsp
];
diff --git a/program/lib/Roundcube/rcube_text2html.php b/program/lib/Roundcube/rcube_text2html.php
index 7d751b6f1..86cfc1405 100644
--- a/program/lib/Roundcube/rcube_text2html.php
+++ b/program/lib/Roundcube/rcube_text2html.php
@@ -56,7 +56,10 @@ class rcube_text2html
];
/** @var bool Internal state */
- protected $_converted = false;
+ protected $converted = false;
+
+ /** @var bool Internal no-wrap mode state */
+ protected $nowrap = false;
/**
@@ -96,7 +99,7 @@ class rcube_text2html
$this->text = $source;
}
- $this->_converted = false;
+ $this->converted = false;
}
/**
@@ -106,8 +109,8 @@ class rcube_text2html
*/
function get_html()
{
- if (!$this->_converted) {
- $this->_convert();
+ if (!$this->converted) {
+ $this->convert();
}
return $this->html;
@@ -122,13 +125,13 @@ class rcube_text2html
}
/**
- * Workhorse function that does actual conversion (calls _converter() method).
+ * Workhorse function that does actual conversion (calls converter() method).
*/
- protected function _convert()
+ protected function convert()
{
// Convert TXT to HTML
- $this->html = $this->_converter($this->text);
- $this->_converted = true;
+ $this->html = $this->converter($this->text);
+ $this->converted = true;
}
/**
@@ -138,7 +141,7 @@ class rcube_text2html
*
* @return string HTML content
*/
- protected function _converter($text)
+ protected function converter($text)
{
// make links and email-addresses clickable
$attribs = ['link_attribs' => ['rel' => 'noreferrer', 'target' => '_blank']];
@@ -167,7 +170,7 @@ class rcube_text2html
if ($first == '>' && preg_match('/^(>+ {0,1})+/', $text[$n], $regs)) {
$q = substr_count($regs[0], '>');
$text[$n] = substr($text[$n], strlen($regs[0]));
- $text[$n] = $this->_convert_line($text[$n]);
+ $text[$n] = $this->convert_line($text[$n]);
$_length = strlen(str_replace(' ', '', $text[$n]));
if ($q > $quote_level) {
@@ -199,7 +202,7 @@ class rcube_text2html
}
}
else {
- $text[$n] = $this->_convert_line($text[$n]);
+ $text[$n] = $this->convert_line($text[$n]);
$q = 0;
$_length = strlen(str_replace(' ', '', $text[$n]));
@@ -260,7 +263,7 @@ class rcube_text2html
*
* @return string Converted text
*/
- protected function _convert_line($text)
+ protected function convert_line($text)
{
static $table;
@@ -273,16 +276,39 @@ class rcube_text2html
$table["\t"] = ' ';
}
+ // empty line?
+ if ($text === '') {
+ return $text;
+ }
+
// skip signature separator
if ($text == '-- ') {
return '--' . $this->config['space'];
}
+ if ($this->nowrap) {
+ if (!in_array($text[0], [' ', '-', '+', '@'])) {
+ $this->nowrap = false;
+ }
+ }
+ else {
+ // Detect start of a unified diff
+ // TODO: Support normal diffs
+ // TODO: Support diff header and comment
+ if (
+ ($text[0] === '-' && preg_match('/^--- \S+/', $text))
+ || ($text[0] === '+' && preg_match('/^\+\+\+ \S+/', $text))
+ || ($text[0] === '@' && preg_match('/^@@ [0-9 ,+-]+ @@/', $text))
+ ) {
+ $this->nowrap = true;
+ }
+ }
+
// replace HTML special and whitespace characters
$text = strtr($text, $table);
$nbsp = $this->config['space'];
- $wrappable = $this->config['flowed'] || $this->config['wrap'];
+ $wrappable = !$this->nowrap && ($this->config['flowed'] || $this->config['wrap']);
// make the line wrappable
if ($wrappable) {
diff --git a/skins/elastic/styles/styles.less b/skins/elastic/styles/styles.less
index 827df9dfc..b6932edbd 100644
--- a/skins/elastic/styles/styles.less
+++ b/skins/elastic/styles/styles.less
@@ -405,6 +405,18 @@ body.task-error-login #layout {
font-family: monospace;
font-size: 13px;
}
+
+ // This is needed for proper display of quoted plain text
+ blockquote {
+ display: inline-block;
+ min-width: 100%;
+
+ & + br {
+ // compensate the spacing "removed" by the inline-block style above
+ display: block;
+ margin-top: 1em;
+ }
+ }
}
#compose-attachments {
diff --git a/tests/Framework/Text2Html.php b/tests/Framework/Text2Html.php
index 619e7d03a..c035350b8 100644
--- a/tests/Framework/Text2Html.php
+++ b/tests/Framework/Text2Html.php
@@ -157,4 +157,43 @@ class Framework_Text2Html extends PHPUnit\Framework\TestCase
$this->assertEquals($expected, $html);
}
+
+ /**
+ * Test patches/diffs handling
+ */
+ function test_text2html_patches_handling()
+ {
+ $input = "Start\n"
+ . "diff --git a/test.txt b/test.txt\n"
+ . "index 7642f44b9..6ce0170aa 100644\n"
+ . "--- a/test.txt\n"
+ . "+++ b/test.txt\n"
+ . "@@ -1982,7 +1982,7 @@ class test\n"
+ . " test1\n"
+ . " test2\n"
+ . " test3\n"
+ . "-test4\n"
+ . "+test5\n"
+ . " \n"
+ . "End";
+
+ $expected = "<div class=\"pre\">Start<br>\n"
+ . "diff --git a/test.txt b/test.txt<br>\n"
+ . "index 7642f44b9..6ce0170aa 100644<br>\n"
+ . "<span style=\"white-space:nowrap\">---_a/test.txt</span><br>\n"
+ . "<span style=\"white-space:nowrap\">+++_b/test.txt</span><br>\n"
+ . "<span style=\"white-space:nowrap\">@@_-1982,7_+1982,7_@@_class_test</span><br>\n"
+ . "<span style=\"white-space:nowrap\">_test1</span><br>\n"
+ . "<span style=\"white-space:nowrap\">_test2</span><br>\n"
+ . "<span style=\"white-space:nowrap\">_test3</span><br>\n"
+ . "<span style=\"white-space:nowrap\">-test4</span><br>\n"
+ . "<span style=\"white-space:nowrap\">+test5</span><br>\n"
+ . "<span style=\"white-space:nowrap\">_</span><br>\n"
+ . "End</div>";
+
+ $t2h = new rcube_text2html($input, false, ['space' => '_']);
+ $html = $t2h->get_html();
+
+ $this->assertEquals($expected, $html);
+ }
}