tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

insertparagraph-with-white-space-style.tentative.html (22930B)


      1 <!doctype html>
      2 <meta charset=utf-8>
      3 <meta name="timeout" content="long">
      4 <meta name="variant" content="?white-space=pre&command=insertParagraph">
      5 <meta name="variant" content="?white-space=pre-wrap&command=insertParagraph">
      6 <meta name="variant" content="?white-space=pre-line&command=insertParagraph">
      7 <meta name="variant" content="?white-space=nowrap&command=insertParagraph">
      8 <meta name="variant" content="?white-space=pre&command=insertText">
      9 <meta name="variant" content="?white-space=pre-wrap&command=insertText">
     10 <meta name="variant" content="?white-space=pre-line&command=insertText">
     11 <meta name="variant" content="?white-space=nowrap&command=insertText">
     12 <script src="/resources/testharness.js"></script>
     13 <script src="/resources/testharnessreport.js"></script>
     14 <script src="../include/editor-test-utils.js"></script>
     15 <link rel=stylesheet href=../include/reset.css>
     16 <title>insertparagraph in white-space specified element</title>
     17 <body><div contenteditable></div></body>
     18 <script>
     19 /**
     20 * This test checks how insertParagraph command and insertText of "\n" works
     21 * in valid styles of parent (editing host itself or in an splittable element).
     22 */
     23 const params = new URLSearchParams(location.search);
     24 const style = params.get("white-space");
     25 const isNewLineSignificant = style == "pre" || style == "pre-wrap" || style == "pre-line";
     26 const command = params.get("command");
     27 const editingHost = document.querySelector("div[contenteditable]");
     28 function execInsertTextOrParagraphCommand() {
     29  if (command == "insertParagraph") {
     30    document.execCommand(command);
     31  } else {
     32    // Inserting a linefeed by insertText command should be equivalent of insertParagraph
     33    document.execCommand(command, false, "\n");
     34  }
     35 }
     36 for (const defaultParagraphSeparator of ["div", "p"]) {
     37  document.execCommand("defaultParagraphSeparator", false, defaultParagraphSeparator);
     38  for (const display of ["block", "inline", "inline-block"]) {
     39    // Inserting paragraph or inserting a linefeed in a text node which is
     40    // a direct child of the editing host.
     41    test(() => {
     42      editingHost.style.whiteSpace = style;
     43      editingHost.style.display = display;
     44      const utils = new EditorTestUtils(editingHost);
     45      utils.setupEditingHost(`abc[]`);
     46      editingHost.getBoundingClientRect();
     47      execInsertTextOrParagraphCommand();
     48      // If the editing host is a block, at least the new paragraph should be
     49      // the default paragraph separator element.
     50      if (display == "block") {
     51        assert_in_array(
     52          editingHost.innerHTML,
     53          [
     54            `abc<${defaultParagraphSeparator}><br></${defaultParagraphSeparator}>`,
     55            `<${defaultParagraphSeparator}>abc</${defaultParagraphSeparator}><${defaultParagraphSeparator}><br></${defaultParagraphSeparator}>`,
     56          ],
     57          "New paragraph should be inserted at end of the editing host"
     58        );
     59      }
     60      // Otherwise, i.e., the editing host is inline, insert a line break (a
     61      // linefeed or <br>) should be inserted instead because it's better
     62      // look for the users.
     63      // Note that an extra line break is required for making the last line
     64      // visible because the editing host is the last visible inline in the
     65      // parent block (<body>).
     66      else if (isNewLineSignificant) {
     67        assert_in_array(
     68          editingHost.innerHTML,
     69          [
     70            `abc\n\n`,
     71            `abc\n<br>`,
     72          ],
     73          "A linefeed should be inserted at end"
     74        );
     75      } else {
     76        assert_equals(
     77          editingHost.innerHTML,
     78          `abc<br><br>`,
     79          "A <br> should be inserted at end"
     80        );
     81      }
     82    }, `<div contenteditable style="white-space:${style}; display:${display}">abc[]</div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
     83 
     84    // Same as above test except the caret position.
     85    test(() => {
     86      editingHost.style.whiteSpace = style;
     87      editingHost.style.display = display;
     88      const utils = new EditorTestUtils(editingHost);
     89      utils.setupEditingHost(`[]abc`);
     90      editingHost.getBoundingClientRect();
     91      execInsertTextOrParagraphCommand();
     92      if (display == "block") {
     93        assert_in_array(
     94          editingHost.innerHTML,
     95          [
     96            `<${defaultParagraphSeparator}><br></${defaultParagraphSeparator}>abc`,
     97            `<${defaultParagraphSeparator}><br></${defaultParagraphSeparator}><${defaultParagraphSeparator}>abc</${defaultParagraphSeparator}>`,
     98          ],
     99          "New paragraph should be inserted at start of the editing host"
    100        );
    101      } else if (isNewLineSignificant) {
    102        assert_in_array(
    103          editingHost.innerHTML,
    104          [
    105            `\nabc`,
    106            `\nabc<br>`,
    107          ],
    108          "A linefeed should be inserted at start"
    109        );
    110      } else {
    111        assert_in_array(
    112          editingHost.innerHTML,
    113          [
    114            `<br>abc`,
    115            `<br>abc<br>`,
    116          ],
    117          "A <br> should be inserted at start"
    118        );
    119      }
    120    }, `<div contenteditable style="white-space:${style}; display:${display}">[]abc</div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
    121 
    122    // Same as above test except the caret position.
    123    test(() => {
    124      editingHost.style.whiteSpace = style;
    125      editingHost.style.display = display;
    126      const utils = new EditorTestUtils(editingHost);
    127      utils.setupEditingHost(`a[]bc`);
    128      editingHost.getBoundingClientRect();
    129      execInsertTextOrParagraphCommand();
    130      if (display == "block") {
    131        assert_in_array(
    132          editingHost.innerHTML,
    133          [
    134            `a<${defaultParagraphSeparator}>bc</${defaultParagraphSeparator}>`,
    135            `<${defaultParagraphSeparator}>a</${defaultParagraphSeparator}><${defaultParagraphSeparator}>bc</${defaultParagraphSeparator}>`,
    136          ],
    137          "New paragraph should split the text"
    138        );
    139      } else if (isNewLineSignificant) {
    140        assert_in_array(
    141          editingHost.innerHTML,
    142          [
    143            `a\nbc`,
    144            `a\nbc<br>`,
    145          ],
    146          "A linefeed should be inserted"
    147        );
    148      } else {
    149        assert_in_array(
    150          editingHost.innerHTML,
    151          [
    152            `a<br>bc`,
    153            `a<br>bc<br>`,
    154          ],
    155          "A <br> should be inserted"
    156        );
    157      }
    158    }, `<div contenteditable style="white-space:${style}; display:${display}">a[]bc</div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
    159 
    160    // Inserting paragraph or inserting a linefeed in a text node after
    161    // executing the "italic" command.  The paragraph or line break result
    162    // should be same as above, but the text in the new paragraph or new line
    163    // should be wrapped in <i>.
    164    test(() => {
    165      editingHost.style.whiteSpace = style;
    166      editingHost.style.display = display;
    167      const utils = new EditorTestUtils(editingHost);
    168      utils.setupEditingHost(`abc[]`);
    169      editingHost.getBoundingClientRect();
    170      document.execCommand("italic");
    171      execInsertTextOrParagraphCommand();
    172      document.execCommand("inserttext", false, "def");
    173      if (display == "block") {
    174        assert_in_array(
    175          editingHost.innerHTML,
    176          [
    177            `abc<${defaultParagraphSeparator}><i>def</i></${defaultParagraphSeparator}>`,
    178            `<${defaultParagraphSeparator}>abc</${defaultParagraphSeparator}><${defaultParagraphSeparator}><i>def</i></${defaultParagraphSeparator}>`,
    179            `<${defaultParagraphSeparator}>abc</${defaultParagraphSeparator}><${defaultParagraphSeparator}><i>def<br></i></${defaultParagraphSeparator}>`,
    180            `<${defaultParagraphSeparator}>abc</${defaultParagraphSeparator}><${defaultParagraphSeparator}><i>def</i><br></${defaultParagraphSeparator}>`,
    181          ],
    182          "New paragraph should be inserted at end of the editing host whose text should be italic"
    183        );
    184      } else if (isNewLineSignificant) {
    185        assert_in_array(
    186          editingHost.innerHTML,
    187          [
    188            `abc\n<i>def</i>`,
    189            `abc\n<i>def\n</i>`,
    190            `abc\n<i>def<br></i>`,
    191            `abc\n<i>def</i>\n`,
    192            `abc\n<i>def</i><br>`,
    193          ],
    194          "The new line should be italic"
    195        );
    196      } else {
    197        assert_in_array(
    198          editingHost.innerHTML,
    199          [
    200            `abc<br><i>def</i>`,
    201            `abc<br><i>def<br></i>`,
    202            `abc<br><i>def</i><br>`,
    203          ],
    204          "The new line should be italic"
    205        );
    206      }
    207    }, `<div contenteditable style="white-space:${style}; display:${display}">abc[]</div> (defaultParagraphSeparator: ${defaultParagraphSeparator}) (preserving temporary inline style test)`);
    208 
    209    // Inserting paragraph or inserting a linefeed in a text node which is
    210    // wrapped in a <b>.  The paragraph or line break result should be same as
    211    // above, but the <b> element should be duplicated in the new paragraph
    212    // or shouldn't be split if inserting a line break.
    213    test(() => {
    214      editingHost.style.whiteSpace = style;
    215      editingHost.style.display = display;
    216      const utils = new EditorTestUtils(editingHost);
    217      utils.setupEditingHost(`<b>abc[]</b>`);
    218      editingHost.getBoundingClientRect();
    219      execInsertTextOrParagraphCommand();
    220      document.execCommand("inserttext", false, "def");
    221      if (display == "block") {
    222        assert_in_array(
    223          editingHost.innerHTML,
    224          [
    225            `<b>abc</b><${defaultParagraphSeparator}><b>def</b></${defaultParagraphSeparator}>`,
    226            `<${defaultParagraphSeparator}><b>abc</b></${defaultParagraphSeparator}><${defaultParagraphSeparator}><b>def</b></${defaultParagraphSeparator}>`,
    227            `<${defaultParagraphSeparator}><b>abc</b></${defaultParagraphSeparator}><${defaultParagraphSeparator}><b>def<br></b></${defaultParagraphSeparator}>`,
    228            `<${defaultParagraphSeparator}><b>abc</b></${defaultParagraphSeparator}><${defaultParagraphSeparator}><b>def</b><br></${defaultParagraphSeparator}>`,
    229          ],
    230          "New paragraph should be inserted at end of the editing host whose text should be bold"
    231        );
    232      } else if (isNewLineSignificant) {
    233        assert_in_array(
    234          editingHost.innerHTML,
    235          [
    236            `<b>abc\ndef</b>`,
    237            `<b>abc\ndef\n</b>`,
    238            `<b>abc\ndef<br></b>`,
    239            `<b>abc\ndef</b>\n`,
    240            `<b>abc\ndef</b><br>`,
    241          ],
    242          "The new line should be bold"
    243        );
    244      } else {
    245        assert_in_array(
    246          editingHost.innerHTML,
    247          [
    248            `<b>abc<br>def</b>`,
    249            `<b>abc<br>def<br></b>`,
    250            `<b>abc<br>def</b><br>`,
    251          ],
    252          "The new line should be bold"
    253        );
    254      }
    255    }, `<div contenteditable style="white-space:${style}; display:${display}"><b>abc[]</b></div> (defaultParagraphSeparator: ${defaultParagraphSeparator}) (preserving inline style test)`);
    256 
    257    for (const paragraph of ["div", "p"]) {
    258      // Inserting paragraph or inserting a linefeed in a splittable paragraph
    259      // (<p> or <div>) whose `white-space` is specified.
    260      test(() => {
    261        editingHost.style.whiteSpace = "normal";
    262        editingHost.style.display = display;
    263        const utils = new EditorTestUtils(editingHost);
    264        utils.setupEditingHost(`<${paragraph} style="white-space:${style}">abc[]</${paragraph}>`);
    265        editingHost.getBoundingClientRect();
    266        execInsertTextOrParagraphCommand();
    267        // Even if the editing host is inline, the command should be handled
    268        // with in the splittable paragraph.  Therefore, the paragraph should
    269        // be just split and the style attribute should be cloned to keep same
    270        // style in the new paragraph.
    271        assert_equals(
    272          editingHost.innerHTML,
    273          `<${paragraph} style="white-space:${style}">abc</${paragraph}><${paragraph} style="white-space:${style}"><br></${paragraph}>`,
    274          "New paragraph should be inserted at end of the paragraph"
    275        );
    276      }, `<div contenteditable style="display:${display}"><${paragraph} style="white-space:${style}">abc[]</${paragraph}></div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
    277 
    278      // Same as above test except the caret position.
    279      test(() => {
    280        editingHost.style.whiteSpace = "normal";
    281        editingHost.style.display = display;
    282        const utils = new EditorTestUtils(editingHost);
    283        utils.setupEditingHost(`<${paragraph} style="white-space:${style}">[]abc</${paragraph}>`);
    284        editingHost.getBoundingClientRect();
    285        execInsertTextOrParagraphCommand();
    286        assert_in_array(
    287          editingHost.innerHTML,
    288          [
    289            `<${paragraph} style="white-space:${style}"><br></${paragraph}><${paragraph} style="white-space:${style}">abc</${paragraph}>`,
    290            `<${paragraph} style="white-space:${style}"><br></${paragraph}><${paragraph} style="white-space:${style}">abc<br></${paragraph}>`,
    291          ],
    292          "New paragraph should be inserted at start of the paragraph"
    293        );
    294      }, `<div contenteditable style="display:${display}"><${paragraph} style="white-space:${style}">[]abc</${paragraph}></div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
    295 
    296      // Same as above test except the caret position.
    297      test(() => {
    298        editingHost.style.whiteSpace = "normal";
    299        editingHost.style.display = display;
    300        const utils = new EditorTestUtils(editingHost);
    301        utils.setupEditingHost(`<${paragraph} style="white-space:${style}">a[]bc</${paragraph}>`);
    302        editingHost.getBoundingClientRect();
    303        execInsertTextOrParagraphCommand();
    304        assert_in_array(
    305          editingHost.innerHTML,
    306          [
    307            `<${paragraph} style="white-space:${style}">a</${paragraph}><${paragraph} style="white-space:${style}">bc</${paragraph}>`,
    308            `<${paragraph} style="white-space:${style}">a</${paragraph}><${paragraph} style="white-space:${style}">bc<br></${paragraph}>`,
    309          ],
    310          "The paragraph should be split"
    311        );
    312      }, `<div contenteditable style="display:${display}"><${paragraph} style="white-space:${style}">a[]bc</${paragraph}></div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
    313 
    314      // Inserting paragraph or inserting a linefeed in a splittable paragraph
    315      // in the editing host whose `white-space` is specified.
    316      test(() => {
    317        editingHost.style.whiteSpace = style;
    318        editingHost.style.display = display;
    319        const utils = new EditorTestUtils(editingHost);
    320        utils.setupEditingHost(`<${paragraph}>abc[]</${paragraph}>`);
    321        editingHost.getBoundingClientRect();
    322        execInsertTextOrParagraphCommand();
    323        // Same as previous tests, the splittable paragraph should be split.
    324        // The `white-space` style of the ancestor block or the inline editing
    325        // host should not affect to the behavior because we can just split
    326        // the paragraph.
    327        assert_equals(
    328          editingHost.innerHTML,
    329          `<${paragraph}>abc</${paragraph}><${paragraph}><br></${paragraph}>`,
    330          "New paragraph should be inserted at end of the paragraph"
    331        );
    332      }, `<div contenteditable style="display:${display}; white-space:${style}"><${paragraph}>abc[]</${paragraph}></div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
    333 
    334      // Same as above test except the caret position.
    335      test(() => {
    336        editingHost.style.whiteSpace = style;
    337        editingHost.style.display = display;
    338        const utils = new EditorTestUtils(editingHost);
    339        utils.setupEditingHost(`<${paragraph}>[]abc</${paragraph}>`);
    340        editingHost.getBoundingClientRect();
    341        execInsertTextOrParagraphCommand();
    342        assert_in_array(
    343          editingHost.innerHTML,
    344          [
    345            `<${paragraph}><br></${paragraph}><${paragraph}>abc</${paragraph}>`,
    346            `<${paragraph}><br></${paragraph}><${paragraph}>abc<br></${paragraph}>`,
    347          ],
    348          "New paragraph should be inserted at start of the paragraph"
    349        );
    350      }, `<div contenteditable style="display:${display}; white-space:${style}"><${paragraph}>[]abc</${paragraph}></div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
    351 
    352      // Same as above test except the caret position.
    353      test(() => {
    354        editingHost.style.whiteSpace = style;
    355        editingHost.style.display = display;
    356        const utils = new EditorTestUtils(editingHost);
    357        utils.setupEditingHost(`<${paragraph}>a[]bc</${paragraph}>`);
    358        editingHost.getBoundingClientRect();
    359        execInsertTextOrParagraphCommand();
    360        assert_in_array(
    361          editingHost.innerHTML,
    362          [
    363            `<${paragraph}>a</${paragraph}><${paragraph}>bc</${paragraph}>`,
    364            `<${paragraph}>a</${paragraph}><${paragraph}>bc<br></${paragraph}>`,
    365          ],
    366          "The paragraph should be split"
    367        );
    368      }, `<div contenteditable style="display:${display}; white-space:${style}"><${paragraph}>a[]bc</${paragraph}></div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
    369 
    370      // Inserting paragraph or inserting a linefeed in a splittable paragraph
    371      // element whose `display` and `white-space` are specified.
    372      test(() => {
    373        editingHost.style.whiteSpace = "normal";
    374        editingHost.style.display = "block";
    375        const utils = new EditorTestUtils(editingHost);
    376        const styleAttr = `style="display:${display}; white-space:${style}"`;
    377        utils.setupEditingHost(`<${paragraph} ${styleAttr}>abc[]</${paragraph}>`);
    378        editingHost.getBoundingClientRect();
    379        execInsertTextOrParagraphCommand();
    380        // If the paragraph is a normal block, we can just split the paragraph.
    381        if (display == "block") {
    382          assert_equals(
    383            editingHost.innerHTML,
    384            `<${paragraph} ${styleAttr}>abc</${paragraph}><${paragraph} ${styleAttr}><br></${paragraph}>`,
    385            "New paragraph should be inserted at end of the paragraph"
    386          );
    387        }
    388        // Otherwise, the paragraph is an inline, splitting the paragraph
    389        // element does not look like inserting paragraph for the users
    390        // because it would just duplicate the inlined element.
    391        // Therefore, the split paragraph should be wrapped into the new
    392        // paragraph (considered with the default paragraph separator) at
    393        // least.  However, <p> cannot contain <p> nor <div> which may be
    394        // styled as inline.  Therefore, <div> should be used for the new
    395        // paragraph even if the default paragraph separator is <p>.
    396        else {
    397          assert_in_array(
    398            editingHost.innerHTML,
    399            [
    400              `<${paragraph} ${styleAttr}>abc</${paragraph}><div><${paragraph} ${styleAttr}><br></${paragraph}></div>`,
    401              `<div><${paragraph} ${styleAttr}>abc</${paragraph}></div><div><${paragraph} ${styleAttr}><br></${paragraph}></div>`,
    402            ],
    403            "New paragraph should be inserted at end of the paragraph which is wrapped by a new <div>"
    404          );
    405        }
    406      }, `<div contenteditable><${paragraph} style="display:${display}; white-space:${style}">abc[]</${paragraph}></div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
    407 
    408      // Same as above test except the caret position.
    409      test(() => {
    410        editingHost.style.whiteSpace = "normal";
    411        editingHost.style.display = "block";
    412        const utils = new EditorTestUtils(editingHost);
    413        const styleAttr = `style="display:${display}; white-space:${style}"`;
    414        utils.setupEditingHost(`<${paragraph} ${styleAttr}>[]abc</${paragraph}>`);
    415        editingHost.getBoundingClientRect();
    416        execInsertTextOrParagraphCommand();
    417        if (display == "block") {
    418          assert_in_array(
    419            editingHost.innerHTML,
    420            [
    421              `<${paragraph} ${styleAttr}><br></${paragraph}><${paragraph} ${styleAttr}>abc</${paragraph}>`,
    422              `<${paragraph} ${styleAttr}><br></${paragraph}><${paragraph} ${styleAttr}>abc<br></${paragraph}>`,
    423            ],
    424            "New paragraph should be inserted at start of the paragraph"
    425          );
    426        } else {
    427          assert_in_array(
    428            editingHost.innerHTML,
    429            [
    430              `<div><${paragraph} ${styleAttr}><br></${paragraph}></div><${paragraph} ${styleAttr}>abc</${paragraph}>`,
    431              `<div><${paragraph} ${styleAttr}><br></${paragraph}></div><${paragraph} ${styleAttr}>abc<br></${paragraph}>`,
    432              `<div><${paragraph} ${styleAttr}><br></${paragraph}></div><div><${paragraph} ${styleAttr}>abc</${paragraph}></div>`,
    433              `<div><${paragraph} ${styleAttr}><br></${paragraph}></div><div><${paragraph} ${styleAttr}>abc<br></${paragraph}></div>`,
    434            ],
    435            "New paragraph should be inserted at start of the paragraph which is wrapped by a new <div>"
    436          );
    437        }
    438 
    439      }, `<div contenteditable><${paragraph} style="display:${display}; white-space:${style}">[]abc</${paragraph}></div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
    440 
    441      // Same as above test except the caret position.
    442      test(() => {
    443        editingHost.style.whiteSpace = "normal";
    444        editingHost.style.display = "block";
    445        const styleAttr = `style="display:${display}; white-space:${style}"`;
    446        const utils = new EditorTestUtils(editingHost);
    447        utils.setupEditingHost(`<${paragraph} ${styleAttr}>a[]bc</${paragraph}>`);
    448        editingHost.getBoundingClientRect();
    449        execInsertTextOrParagraphCommand();
    450        if (display == "block") {
    451          assert_in_array(
    452            editingHost.innerHTML,
    453            [
    454              `<${paragraph} ${styleAttr}>a</${paragraph}><${paragraph} ${styleAttr}>bc</${paragraph}>`,
    455              `<${paragraph} ${styleAttr}>a</${paragraph}><${paragraph} ${styleAttr}>bc<br></${paragraph}>`,
    456            ],
    457            "The paragraph should be split"
    458          );
    459        } else {
    460          assert_in_array(
    461            editingHost.innerHTML,
    462            [
    463              `<${paragraph} ${styleAttr}>a</${paragraph}><div><${paragraph} ${styleAttr}>bc</${paragraph}></div>`,
    464              `<${paragraph} ${styleAttr}>a</${paragraph}><div><${paragraph} ${styleAttr}>bc<br></${paragraph}></div>`,
    465              `<div><${paragraph} ${styleAttr}>a</${paragraph}></div><div><${paragraph} ${styleAttr}>bc</${paragraph}></div>`,
    466              `<div><${paragraph} ${styleAttr}>a</${paragraph}></div><div><${paragraph} ${styleAttr}>bc<br></${paragraph}></div>`,
    467            ],
    468            "The paragraph should be split and the latter one should be wrapped by a new <div>"
    469          );
    470        }
    471      }, `<div contenteditable><${paragraph} style="display:${display}; white-space:${style}">a[]bc</${paragraph}></div> (defaultParagraphSeparator: ${defaultParagraphSeparator})`);
    472    }
    473  }
    474 }
    475 </script>