Browse Source

ComposeArea: Replace whitespace when pasting

Unfortunately, setting `white-space: pre-wrap` on the compose area
results in a behavioral change in the way child nodes are managed in
Chromium. This breaks some tests.

Replacing spaces with escape sequences when pasting is ugly, but seems
to work.
Danilo Bargen 6 years ago
parent
commit
f46bc8c69e
4 changed files with 23 additions and 4 deletions
  1. 9 2
      src/directives/compose_area.ts
  2. 9 0
      src/helpers.ts
  3. 0 1
      src/sass/sections/_compose_area.scss
  4. 5 1
      tests/ts/helpers.ts

+ 9 - 2
src/directives/compose_area.ts

@@ -15,7 +15,7 @@
  * along with Threema Web. If not, see <http://www.gnu.org/licenses/>.
  */
 
-import {extractText, isActionTrigger, logAdapter} from '../helpers';
+import {extractText, isActionTrigger, logAdapter, replaceWhitespace} from '../helpers';
 import {BrowserService} from '../services/browser';
 import {StringService} from '../services/string';
 import {TimeoutService} from '../services/timeout';
@@ -436,7 +436,14 @@ export default [
                         const escaped = escapeHtml(text);
 
                         // Apply filters (emojify, convert newline, etc)
-                        const formatted = nlToBr(mentionify(emojify(escaped, true, false, scope.emojiImagePath)), true);
+                        const formatted = replaceWhitespace(
+                            nlToBr(
+                                mentionify(
+                                    emojify(escaped, true, false, scope.emojiImagePath),
+                                ),
+                                true,
+                            ),
+                        );
 
                         // Insert resulting HTML
                         document.execCommand('insertHTML', false, formatted);

+ 9 - 0
src/helpers.ts

@@ -442,3 +442,12 @@ export function extractText(targetNode: HTMLElement, logWarning: (msg: string) =
     visitChildNodes(targetNode);
     return trim ? text.trim() : text;
 }
+
+/**
+ * Replace spaces with `&nbsp;` and tabs with `&nbsp;&nbsp;`.
+ */
+export function replaceWhitespace(text: string): string {
+    return text
+        .replace(/ /g, '&nbsp;')
+        .replace(/\t/, '&nbsp;&nbsp;');
+}

+ 0 - 1
src/sass/sections/_compose_area.scss

@@ -40,7 +40,6 @@ compose-area {
                     max-height: calc(1.3em * 5);
                     min-height: 22px;
                     cursor: text;
-                    white-space: pre-wrap;
 
                     img.e1 {
                         vertical-align: middle;

+ 5 - 1
tests/ts/helpers.ts

@@ -17,11 +17,15 @@
  * along with Threema Web. If not, see <http://www.gnu.org/licenses/>.
  */
 
-import {u8aToHex} from '../../src/helpers';
+import {replaceWhitespace, u8aToHex} from '../../src/helpers';
 
 describe('Helpers', () => {
     it('u8aToHex', function() {
         const arr = Uint8Array.of(1, 2, 4, 8, 254, 255);
         expect(u8aToHex(arr)).toEqual('01020408feff');
     });
+
+    it('replaceWhitespace', function() {
+        expect(replaceWhitespace('	Hello wor  ld')).toEqual('&nbsp;&nbsp;Hello&nbsp;wor&nbsp;&nbsp;ld');
+    });
 });