tor-browser

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

insertparagraph-in-inline-editing-host.tentative.html (18574B)


      1 <!doctype html>
      2 <meta chareset="utf-8">
      3 <meta name="timeout" content="long">
      4 
      5 <meta name="variant" content="?white-space=normal&display=inline&method=enter">
      6 <meta name="variant" content="?white-space=normal&display=inline&method=shift-enter">
      7 <meta name="variant" content="?white-space=normal&display=inline-block&method=enter">
      8 <meta name="variant" content="?white-space=normal&display=inline-block&method=shift-enter">
      9 <meta name="variant" content="?white-space=normal&display=block&method=enter">
     10 <meta name="variant" content="?white-space=normal&display=block&method=shift-enter">
     11 <meta name="variant" content="?white-space=normal&display=list-item&method=enter">
     12 <meta name="variant" content="?white-space=normal&display=list-item&method=shift-enter">
     13 <meta name="variant" content="?white-space=normal&display=table-cell&method=enter">
     14 <meta name="variant" content="?white-space=normal&display=table-cell&method=shift-enter">
     15 
     16 <meta name="variant" content="?white-space=pre&display=inline&method=enter">
     17 <meta name="variant" content="?white-space=pre&display=inline&method=shift-enter">
     18 <meta name="variant" content="?white-space=pre&display=inline-block&method=enter">
     19 <meta name="variant" content="?white-space=pre&display=inline-block&method=shift-enter">
     20 <meta name="variant" content="?white-space=pre&display=block&method=enter">
     21 <meta name="variant" content="?white-space=pre&display=block&method=shift-enter">
     22 <meta name="variant" content="?white-space=pre&display=list-item&method=enter">
     23 <meta name="variant" content="?white-space=pre&display=list-item&method=shift-enter">
     24 <meta name="variant" content="?white-space=pre&display=table-cell&method=enter">
     25 <meta name="variant" content="?white-space=pre&display=table-cell&method=shift-enter">
     26 
     27 <meta name="variant" content="?white-space=pre-line&display=inline&method=enter">
     28 <meta name="variant" content="?white-space=pre-line&display=inline&method=shift-enter">
     29 <meta name="variant" content="?white-space=pre-line&display=inline-block&method=enter">
     30 <meta name="variant" content="?white-space=pre-line&display=inline-block&method=shift-enter">
     31 <meta name="variant" content="?white-space=pre-line&display=block&method=enter">
     32 <meta name="variant" content="?white-space=pre-line&display=block&method=shift-enter">
     33 <meta name="variant" content="?white-space=pre-line&display=list-item&method=enter">
     34 <meta name="variant" content="?white-space=pre-line&display=list-item&method=shift-enter">
     35 <meta name="variant" content="?white-space=pre-line&display=table-cell&method=enter">
     36 <meta name="variant" content="?white-space=pre-line&display=table-cell&method=shift-enter">
     37 
     38 <meta name="variant" content="?white-space=pre-wrap&display=inline&method=enter">
     39 <meta name="variant" content="?white-space=pre-wrap&display=inline&method=shift-enter">
     40 <meta name="variant" content="?white-space=pre-wrap&display=inline-block&method=enter">
     41 <meta name="variant" content="?white-space=pre-wrap&display=inline-block&method=shift-enter">
     42 <meta name="variant" content="?white-space=pre-wrap&display=block&method=enter">
     43 <meta name="variant" content="?white-space=pre-wrap&display=block&method=shift-enter">
     44 <meta name="variant" content="?white-space=pre-wrap&display=list-item&method=enter">
     45 <meta name="variant" content="?white-space=pre-wrap&display=list-item&method=shift-enter">
     46 <meta name="variant" content="?white-space=pre-wrap&display=table-cell&method=enter">
     47 <meta name="variant" content="?white-space=pre-wrap&display=table-cell&method=shift-enter">
     48 
     49 <title>Line breaking in inline editing host</title>
     50 <script src="/resources/testharness.js"></script>
     51 <script src="/resources/testharnessreport.js"></script>
     52 <script src="/resources/testdriver.js"></script>
     53 <script src="/resources/testdriver-vendor.js"></script>
     54 <script src="/resources/testdriver-actions.js"></script>
     55 <script src="../include/editor-test-utils.js"></script>
     56 <div><span contenteditable></span></div>
     57 <script>
     58 "use strict";
     59 
     60 const searchParams = new URLSearchParams(document.location.search);
     61 const testingInsertParagraph = searchParams.get("method") == "enter";
     62 const whiteSpace = searchParams.get("white-space");
     63 const display = searchParams.get("display");
     64 
     65 const isPreformatted =
     66  whiteSpace == "pre" || whiteSpace == "pre-line" || whiteSpace == "pre-wrap";
     67 
     68 const editingHost = document.querySelector("span[contenteditable]");
     69 const container = editingHost.parentElement;
     70 const utils = new EditorTestUtils(editingHost);
     71 const modifiers = (() => {
     72  if (testingInsertParagraph) {
     73    return null;
     74  }
     75  // Only Safari treats `Ctrl+Enter` as insertLineBreak
     76  if (navigator.platform.includes("Mac") &&
     77        navigator.userAgent.includes("Safari") &&
     78        !navigator.userAgent.includes("Chrom")) {
     79    return utils.kControl;
     80  }
     81  // The others including WebKitGTK treat `Shift+Enter` as it.
     82  return utils.kShift;
     83 })();
     84 
     85 for (const defaultParagraphSeparator of ["div", "p"]) {
     86  document.execCommand(
     87    "defaultParagraphSeparator",
     88    false,
     89    defaultParagraphSeparator
     90  );
     91 
     92  promise_test(async t => {
     93    editingHost.setAttribute(
     94      "style",
     95      `display:${display};white-space:${whiteSpace}`
     96    );
     97    utils.setupEditingHost("{}");
     98    await utils.sendEnterKey(modifiers);
     99    editingHost.removeAttribute("style");
    100    // In this case, the inserting line break is the last visible thing in the
    101    // block.  Therefore, additional <br> or a preformatted linefeed is also
    102    // required to make the new line visible.
    103    if (!isPreformatted) {
    104      assert_equals(
    105        container.innerHTML,
    106        '<span contenteditable=""><br><br></span>',
    107        `A <br> and additional <br> should be inserted when ${t.name}`
    108      );
    109    } else {
    110      assert_in_array(
    111        container.innerHTML,
    112        [
    113          '<span contenteditable="">\n<br></span>',
    114          '<span contenteditable="">\n\n</span>',
    115        ],
    116        `A linefeed and additional line breaker should be inserted when ${t.name}`
    117      );
    118    }
    119  }, `${
    120    testingInsertParagraph ? "insertParagraph" : "insertLineBreak"
    121  } in <span contenteditable style="display:${
    122    display
    123  };white-space:${whiteSpace}">{}</span> (defaultParagraphSeparator=${
    124    defaultParagraphSeparator
    125  })`);
    126 
    127  promise_test(async t => {
    128    editingHost.setAttribute(
    129      "style",
    130      `display:${display};white-space:${whiteSpace}`
    131    );
    132    const brElement = document.createElement("br");
    133    try {
    134      container.appendChild(brElement);
    135      utils.setupEditingHost("{}");
    136      await utils.sendEnterKey(modifiers);
    137      editingHost.removeAttribute("style");
    138      // Even if the <span> element is followed by an invisible <br>, it does
    139      // not make the new line in the <span> element visible.  Therefore,
    140      // inserting additional line break is required in this case too.
    141      if (!isPreformatted) {
    142        assert_equals(
    143          container.innerHTML,
    144          '<span contenteditable=""><br><br></span><br>',
    145          `A <br> and additional <br> should be inserted when ${t.name}`
    146        );
    147      } else {
    148        assert_in_array(
    149          container.innerHTML,
    150          [
    151            `<span contenteditable="">\n\n</span><br>`,
    152            `<span contenteditable="">\n<br></span><br>`,
    153          ],
    154          `A linefeed and additional line break should be inserted when ${t.name}`
    155        );
    156      }
    157    } finally {
    158      brElement.remove();
    159    }
    160  }, `${
    161    testingInsertParagraph ? "insertParagraph" : "insertLineBreak"
    162  } in <span contenteditable style="display:${
    163    display
    164  };white-space:${
    165    whiteSpace
    166  }">{}</span> followed by a <br> (defaultParagraphSeparator=${
    167    defaultParagraphSeparator
    168  })`);
    169 
    170  promise_test(async t => {
    171    editingHost.setAttribute(
    172      "style",
    173      `display:${display};white-space:${whiteSpace}`
    174    );
    175    const divElement = document.createElement("div");
    176    divElement.textContent = "efg";
    177    try {
    178      container.appendChild(divElement);
    179      utils.setupEditingHost("{}");
    180      await utils.sendEnterKey(modifiers);
    181      editingHost.removeAttribute("style");
    182      // When the <span> element is followed by a <div>, making empty last
    183      // line visible requires an invisible <br> after a line break.
    184      if (!isPreformatted) {
    185        assert_equals(
    186          container.innerHTML,
    187          '<span contenteditable=""><br><br></span><div>efg</div>',
    188          `A <br> and additional <br> should be inserted when ${t.name}`
    189        );
    190      } else {
    191        assert_in_array(
    192          container.innerHTML,
    193          [
    194            `<span contenteditable="">\n\n</span><div>efg</div>`,
    195            `<span contenteditable="">\n<br></span><div>efg</div>`,
    196          ],
    197          `A linefeed and additional line break should be inserted when ${t.name}`
    198        );
    199      }
    200    } finally {
    201      divElement.remove();
    202    }
    203  }, `${
    204    testingInsertParagraph ? "insertParagraph" : "insertLineBreak"
    205  } in <span contenteditable style="display:${
    206    display
    207  };white-space:${
    208    whiteSpace
    209  }">{}</span> followed by a <div> (defaultParagraphSeparator=${
    210    defaultParagraphSeparator
    211  })`);
    212 
    213  promise_test(async t => {
    214    editingHost.setAttribute(
    215      "style",
    216      `display:${display};white-space:${whiteSpace}`
    217    );
    218    const text = document.createTextNode("abc");
    219    try {
    220      container.appendChild(text);
    221      utils.setupEditingHost("{}");
    222      await utils.sendEnterKey(modifiers);
    223      editingHost.removeAttribute("style");
    224      // Even if the <span> element is followed by visible text, it does
    225      // not make the new line in the <span> element visible.  Therefore,
    226      // inserting additional line break is required in this case too.
    227      if (!isPreformatted) {
    228        assert_equals(
    229          container.innerHTML,
    230          '<span contenteditable=""><br><br></span>abc',
    231          `A <br> and additional <br> should be inserted when ${t.name}`
    232        );
    233      } else {
    234        assert_in_array(
    235          container.innerHTML,
    236          [
    237            `<span contenteditable="">\n\n</span>abc`,
    238            `<span contenteditable="">\n<br></span>abc`,
    239          ],
    240          `A linefeed and additional line break should be inserted when ${t.name}`
    241        );
    242      }
    243    } finally {
    244      text.remove();
    245    }
    246  }, `${
    247    testingInsertParagraph ? "insertParagraph" : "insertLineBreak"
    248  } in <span contenteditable style="display:${
    249    display
    250  };white-space:${
    251    whiteSpace
    252  }">{}</span> followed by text (defaultParagraphSeparator=${
    253    defaultParagraphSeparator
    254  })`);
    255 
    256  promise_test(async t => {
    257    editingHost.setAttribute(
    258      "style",
    259      `display:${display};white-space:${whiteSpace}`
    260    );
    261    utils.setupEditingHost("{}<br>");
    262    await utils.sendEnterKey(modifiers);
    263    editingHost.removeAttribute("style");
    264    // In this case, there is a <br> element which makes the new line (last
    265    // line) visible.  Therefore, only a line break should be inserted.
    266    if (!isPreformatted) {
    267      assert_equals(
    268        container.innerHTML,
    269        `<span contenteditable=""><br><br></span>`,
    270        `A <br> should be inserted when ${t.name}`
    271      );
    272    } else {
    273      assert_equals(
    274        container.innerHTML,
    275        `<span contenteditable="">\n<br></span>`,
    276        `A <br> should be inserted when ${t.name}`
    277      );
    278    }
    279  }, `${
    280    testingInsertParagraph ? "insertParagraph" : "insertLineBreak"
    281  } in <span contenteditable style="display:${
    282    display
    283  };white-space:${whiteSpace}">{}<br></span> (defaultParagraphSeparator=${
    284    defaultParagraphSeparator
    285  })`);
    286 
    287  promise_test(async t => {
    288    editingHost.setAttribute(
    289      "style",
    290      `display:${display};white-space:${whiteSpace}`
    291    );
    292    utils.setupEditingHost("[]abcd");
    293    await utils.sendEnterKey(modifiers);
    294    editingHost.removeAttribute("style");
    295    assert_equals(
    296      container.innerHTML,
    297      `<span contenteditable="">${
    298        isPreformatted ? "\n" : "<br>"
    299      }abcd</span>`,
    300      `${
    301        isPreformatted ? "A linefeed" : "A <br>"
    302      } should be inserted when ${t.name}`
    303    );
    304  }, `${
    305    testingInsertParagraph ? "insertParagraph" : "insertLineBreak"
    306  } in <span contenteditable style="display:${
    307    display
    308  };white-space:${whiteSpace}">[]abcd</span> (defaultParagraphSeparator=${
    309    defaultParagraphSeparator
    310  })`);
    311 
    312  promise_test(async t => {
    313    editingHost.setAttribute(
    314      "style",
    315      `display:${display};white-space:${whiteSpace}`
    316    );
    317    utils.setupEditingHost("ab[]cd");
    318    await utils.sendEnterKey(modifiers);
    319    editingHost.removeAttribute("style");
    320    assert_equals(
    321      container.innerHTML,
    322      `<span contenteditable="">ab${
    323        isPreformatted ? "\n" : "<br>"
    324      }cd</span>`,
    325      `${
    326        isPreformatted ? "A linefeed" : "A <br>"
    327      } should be inserted when ${t.name}`
    328    );
    329  }, `${
    330    testingInsertParagraph ? "insertParagraph" : "insertLineBreak"
    331  } in <span contenteditable style="display:${
    332    display
    333  };white-space:${whiteSpace}">ab[]cd</span> (defaultParagraphSeparator=${
    334    defaultParagraphSeparator
    335  })`);
    336 
    337  promise_test(async t => {
    338    editingHost.setAttribute(
    339      "style",
    340      `display:${display};white-space:${whiteSpace}`
    341    );
    342    utils.setupEditingHost("abcd[]");
    343    await utils.sendEnterKey(modifiers);
    344    editingHost.removeAttribute("style");
    345    // In this case, the inserting line break is the last visible thing in the
    346    // block.  Therefore, additional line break is also required to make the
    347    // new line visible.
    348    if (!isPreformatted) {
    349      assert_equals(
    350        container.innerHTML,
    351        `<span contenteditable="">abcd<br><br></span>`,
    352        `A <br> and additional <br> should be inserted when ${t.name}`
    353      );
    354    } else {
    355      assert_in_array(
    356        container.innerHTML,
    357        [
    358          `<span contenteditable="">abcd\n<br></span>`,
    359          `<span contenteditable="">abcd\n\n</span>`,
    360        ],
    361        `A linefeed and additional line break should be inserted when ${t.name}`
    362      );
    363    }
    364  }, `${
    365    testingInsertParagraph ? "insertParagraph" : "insertLineBreak"
    366  } in <span contenteditable style="display:${
    367    display
    368  };white-space:${whiteSpace}">abcd[]</span> (defaultParagraphSeparator=${
    369    defaultParagraphSeparator
    370  })`);
    371 
    372  promise_test(async t => {
    373    editingHost.setAttribute(
    374      "style",
    375      `display:${display};white-space:${whiteSpace}`
    376    );
    377    const brElement = document.createElement("br");
    378    try {
    379      container.appendChild(brElement);
    380      utils.setupEditingHost("abcd[]");
    381      await utils.sendEnterKey(modifiers);
    382      editingHost.removeAttribute("style");
    383      // Even if the <span> element is followed by an invisible <br>, it does
    384      // not make the new line in the <span> element visible.  Therefore,
    385      // inserting additional line break is required in this case too.
    386      if (!isPreformatted) {
    387        assert_equals(
    388          container.innerHTML,
    389          '<span contenteditable="">abcd<br><br></span><br>',
    390          `A <br> and additional <br> should be inserted when ${t.name}`
    391        );
    392      } else {
    393        assert_in_array(
    394          container.innerHTML,
    395          [
    396            `<span contenteditable="">abcd\n<br></span><br>`,
    397            `<span contenteditable="">abcd\n\n</span><br>`,
    398          ],
    399          `A linefeed and additional line break should be inserted when ${t.name}`
    400        );
    401      }
    402    } finally {
    403      brElement.remove();
    404    }
    405  }, `${
    406    testingInsertParagraph ? "insertParagraph" : "insertLineBreak"
    407  } in <span contenteditable style="display:${
    408    display
    409  };white-space:${
    410    whiteSpace
    411  }">abcd[]</span> followed by a <br> element (defaultParagraphSeparator=${
    412    defaultParagraphSeparator
    413  })`);
    414 
    415  promise_test(async t => {
    416    editingHost.setAttribute(
    417      "style",
    418      `display:${display};white-space:${whiteSpace}`
    419    );
    420    const divElement = document.createElement("div");
    421    divElement.textContent = "efg";
    422    try {
    423      container.appendChild(divElement);
    424      utils.setupEditingHost("abcd[]");
    425      await utils.sendEnterKey(modifiers);
    426      editingHost.removeAttribute("style");
    427      // When the <span> element is followed by a <div>, making empty last
    428      // line visible requires an invisible <br> after a line break.
    429      if (!isPreformatted) {
    430        assert_equals(
    431          container.innerHTML,
    432          '<span contenteditable="">abcd<br><br></span><div>efg</div>',
    433          `A <br> and additional <br> should be inserted when ${t.name}`
    434        );
    435      } else {
    436        assert_in_array(
    437          container.innerHTML,
    438          [
    439            `<span contenteditable="">abcd\n<br></span><div>efg</div>`,
    440            `<span contenteditable="">abcd\n\n</span><div>efg</div>`,
    441          ],
    442          `A linefeed and additional line break should be inserted when ${t.name}`
    443        );
    444      }
    445    } finally {
    446      divElement.remove();
    447    }
    448  }, `${
    449    testingInsertParagraph ? "insertParagraph" : "insertLineBreak"
    450  } in <span contenteditable style="display:${
    451    display
    452  };white-space:${
    453    whiteSpace
    454  }">abcd[]</span> followed by a <div> element (defaultParagraphSeparator=${
    455    defaultParagraphSeparator
    456  })`);
    457 
    458  promise_test(async t => {
    459    editingHost.setAttribute(
    460      "style",
    461      `display:${display};white-space:${whiteSpace}`
    462    );
    463    const text = document.createTextNode("efg");
    464    try {
    465      container.appendChild(text);
    466      utils.setupEditingHost("abcd[]");
    467      await utils.sendEnterKey(modifiers);
    468      editingHost.removeAttribute("style");
    469      // Even if the <span> element is followed by visible text, it does
    470      // not make the new line in the <span> element visible.  Therefore,
    471      // inserting additional line break is required in this case too.
    472      if (!isPreformatted) {
    473        assert_equals(
    474          container.innerHTML,
    475          '<span contenteditable="">abcd<br><br></span>efg',
    476          `A <br> and additional <br> should be inserted when ${t.name}`
    477        );
    478      } else {
    479        assert_in_array(
    480          container.innerHTML,
    481          [
    482            `<span contenteditable="">abcd\n<br></span>efg`,
    483            `<span contenteditable="">abcd\n\n</span>efg`,
    484          ],
    485          `A linefeed and additional line break should be inserted when ${t.name}`
    486        );
    487      }
    488    } finally {
    489      text.remove();
    490    }
    491  }, `${
    492    testingInsertParagraph ? "insertParagraph" : "insertLineBreak"
    493  } in <span contenteditable style="display:${
    494    display
    495  };white-space:${
    496    whiteSpace
    497  }">abcd[]</span> followed by text (defaultParagraphSeparator=${
    498    defaultParagraphSeparator
    499  })`);
    500 }
    501 
    502 </script>