tor-browser

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

browser_textleafpoint.js (13738B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 /* import-globals-from ../../mochitest/text.js */
      8 
      9 addAccessibleTask(
     10  `
     11  <p id="p" style="white-space: pre-line;">A bug
     12 h<a href="#">id i</a>n
     13 the <strong>big</strong> rug.</p>
     14 `,
     15  function (browser, docAcc) {
     16    const container = findAccessibleChildByID(docAcc, "p");
     17    const firstPoint = createTextLeafPoint(container, 0);
     18    const lastPoint = createTextLeafPoint(container, kTextEndOffset);
     19 
     20    let charSequence = [
     21      ...textBoundaryGenerator(firstPoint, BOUNDARY_CHAR, DIRECTION_NEXT),
     22    ];
     23 
     24    testPointEqual(
     25      firstPoint,
     26      charSequence[0],
     27      "Point constructed via container and offset 0 is first character point."
     28    );
     29    testPointEqual(
     30      lastPoint,
     31      charSequence[charSequence.length - 1],
     32      "Point constructed via container and kTextEndOffset is last character point."
     33    );
     34 
     35    const expectedCharSequence = [
     36      ["A bug\nh", 0],
     37      ["A bug\nh", 1],
     38      ["A bug\nh", 2],
     39      ["A bug\nh", 3],
     40      ["A bug\nh", 4],
     41      ["A bug\nh", 5],
     42      ["A bug\nh", 6],
     43      ["id i", 0],
     44      ["id i", 1],
     45      ["id i", 2],
     46      ["id i", 3],
     47      ["n\nthe ", 0],
     48      ["n\nthe ", 1],
     49      ["n\nthe ", 2],
     50      ["n\nthe ", 3],
     51      ["n\nthe ", 4],
     52      ["n\nthe ", 5],
     53      ["big", 0],
     54      ["big", 1],
     55      ["big", 2],
     56      [" rug.", 0],
     57      [" rug.", 1],
     58      [" rug.", 2],
     59      [" rug.", 3],
     60      [" rug.", 4],
     61      [" rug.", 5],
     62    ];
     63 
     64    testBoundarySequence(
     65      firstPoint,
     66      BOUNDARY_CHAR,
     67      DIRECTION_NEXT,
     68      expectedCharSequence,
     69      "Forward BOUNDARY_CHAR sequence is correct"
     70    );
     71 
     72    testBoundarySequence(
     73      lastPoint,
     74      BOUNDARY_CHAR,
     75      DIRECTION_PREVIOUS,
     76      [...expectedCharSequence].reverse(),
     77      "Backward BOUNDARY_CHAR sequence is correct"
     78    );
     79 
     80    const expectedWordStartSequence = [
     81      ["A bug\nh", 0],
     82      ["A bug\nh", 2],
     83      ["A bug\nh", 6],
     84      ["id i", 3],
     85      ["n\nthe ", 2],
     86      ["big", 0],
     87      [" rug.", 1],
     88    ];
     89    testBoundarySequence(
     90      firstPoint,
     91      BOUNDARY_WORD_START,
     92      DIRECTION_NEXT,
     93      // Add last point in doc
     94      [...expectedWordStartSequence, readablePoint(lastPoint)],
     95      "Forward BOUNDARY_WORD_START sequence is correct"
     96    );
     97 
     98    testBoundarySequence(
     99      lastPoint,
    100      BOUNDARY_WORD_START,
    101      DIRECTION_PREVIOUS,
    102      [...expectedWordStartSequence].reverse(),
    103      "Backward BOUNDARY_WORD_START sequence is correct"
    104    );
    105 
    106    const expectedWordEndSequence = [
    107      ["A bug\nh", 1],
    108      ["A bug\nh", 5],
    109      ["id i", 2],
    110      ["n\nthe ", 1],
    111      ["n\nthe ", 5],
    112      [" rug.", 0],
    113      [" rug.", 5],
    114    ];
    115    testBoundarySequence(
    116      firstPoint,
    117      BOUNDARY_WORD_END,
    118      DIRECTION_NEXT,
    119      expectedWordEndSequence,
    120      "Forward BOUNDARY_WORD_END sequence is correct"
    121    );
    122 
    123    testBoundarySequence(
    124      lastPoint,
    125      BOUNDARY_WORD_END,
    126      DIRECTION_PREVIOUS,
    127      [readablePoint(firstPoint), ...expectedWordEndSequence].reverse(),
    128      "Backward BOUNDARY_WORD_END sequence is correct"
    129    );
    130 
    131    const expectedLineStartSequence = [
    132      ["A bug\nh", 0],
    133      ["A bug\nh", 6],
    134      ["n\nthe ", 2],
    135    ];
    136    testBoundarySequence(
    137      firstPoint,
    138      BOUNDARY_LINE_START,
    139      DIRECTION_NEXT,
    140      // Add last point in doc
    141      [...expectedLineStartSequence, readablePoint(lastPoint)],
    142      "Forward BOUNDARY_LINE_START sequence is correct"
    143    );
    144 
    145    testBoundarySequence(
    146      lastPoint,
    147      BOUNDARY_LINE_START,
    148      DIRECTION_PREVIOUS,
    149      [...expectedLineStartSequence].reverse(),
    150      "Backward BOUNDARY_LINE_START sequence is correct"
    151    );
    152 
    153    const expectedLineEndSequence = [
    154      ["A bug\nh", 5],
    155      ["n\nthe ", 1],
    156    ];
    157    testBoundarySequence(
    158      firstPoint,
    159      BOUNDARY_LINE_END,
    160      DIRECTION_NEXT,
    161      // Add last point in doc
    162      [...expectedLineEndSequence, readablePoint(lastPoint)],
    163      "Forward BOUNDARY_LINE_END sequence is correct",
    164      { todo: true }
    165    );
    166 
    167    testBoundarySequence(
    168      lastPoint,
    169      BOUNDARY_LINE_END,
    170      DIRECTION_PREVIOUS,
    171      [readablePoint(firstPoint), ...expectedLineEndSequence].reverse(),
    172      "Backward BOUNDARY_LINE_END sequence is correct"
    173    );
    174  },
    175  { chrome: true, topLevel: true, iframe: false, remoteIframe: false }
    176 );
    177 
    178 addAccessibleTask(
    179  `<p id="p">
    180    Rob ca<input id="i1" value="n m">op up.
    181  </p>`,
    182  function (browser, docAcc) {
    183    const container = findAccessibleChildByID(docAcc, "p");
    184    const firstPoint = createTextLeafPoint(container, 0);
    185    const lastPoint = createTextLeafPoint(container, kTextEndOffset);
    186 
    187    testBoundarySequence(
    188      firstPoint,
    189      BOUNDARY_CHAR,
    190      DIRECTION_NEXT,
    191      [
    192        ["Rob ca", 0],
    193        ["Rob ca", 1],
    194        ["Rob ca", 2],
    195        ["Rob ca", 3],
    196        ["Rob ca", 4],
    197        ["Rob ca", 5],
    198        ["n m", 0],
    199        ["n m", 1],
    200        ["n m", 2],
    201        ["n m", 3],
    202      ],
    203      "Forward BOUNDARY_CHAR sequence when stopping in editable is correct",
    204      { flags: BOUNDARY_FLAG_STOP_IN_EDITABLE }
    205    );
    206 
    207    testBoundarySequence(
    208      lastPoint,
    209      BOUNDARY_CHAR,
    210      DIRECTION_PREVIOUS,
    211      [
    212        ["op up. ", 7],
    213        ["op up. ", 6],
    214        ["op up. ", 5],
    215        ["op up. ", 4],
    216        ["op up. ", 3],
    217        ["op up. ", 2],
    218        ["op up. ", 1],
    219        ["op up. ", 0],
    220        ["n m", 2],
    221        ["n m", 1],
    222        ["n m", 0],
    223      ],
    224      "Backward BOUNDARY_CHAR sequence when stopping in editable is correct",
    225      { flags: BOUNDARY_FLAG_STOP_IN_EDITABLE }
    226    );
    227 
    228    testBoundarySequence(
    229      firstPoint,
    230      BOUNDARY_WORD_START,
    231      DIRECTION_NEXT,
    232      [
    233        ["Rob ca", 0],
    234        ["Rob ca", 4],
    235        ["n m", 2],
    236      ],
    237      "Forward BOUNDARY_WORD_START sequence when stopping in editable is correct",
    238      {
    239        flags: BOUNDARY_FLAG_STOP_IN_EDITABLE,
    240        todo: true, //  Shouldn't consider end of input a word start
    241      }
    242    );
    243  },
    244  { chrome: true, topLevel: true, iframe: false, remoteIframe: false }
    245 );
    246 
    247 addAccessibleTask(
    248  `
    249  <p id="p" style="white-space: pre-line;">A bug
    250 on a <span style="display: block;">rug</span></p>
    251  <p id="p2">
    252    Numbers:
    253  </p>
    254  <ul>
    255    <li>One</li>
    256    <li>Two</li>
    257    <li>Three</li>
    258  </ul>`,
    259  function (browser, docAcc) {
    260    const firstPoint = createTextLeafPoint(docAcc, 0);
    261    const lastPoint = createTextLeafPoint(docAcc, kTextEndOffset);
    262 
    263    const expectedParagraphStart = [
    264      ["A bug\non a ", 0],
    265      ["A bug\non a ", 6],
    266      ["rug", 0],
    267      ["Numbers: ", 0],
    268      ["• ", 0],
    269      ["• ", 0],
    270      ["• ", 0],
    271    ];
    272    testBoundarySequence(
    273      firstPoint,
    274      BOUNDARY_PARAGRAPH,
    275      DIRECTION_NEXT,
    276      [...expectedParagraphStart, readablePoint(lastPoint)],
    277      "Forward BOUNDARY_PARAGRAPH sequence is correct"
    278    );
    279 
    280    const paragraphStart = createTextLeafPoint(
    281      findAccessibleChildByID(docAcc, "p2").firstChild,
    282      0
    283    );
    284    const wordEnd = paragraphStart.findBoundary(
    285      BOUNDARY_WORD_END,
    286      DIRECTION_NEXT,
    287      BOUNDARY_FLAG_INCLUDE_ORIGIN
    288    );
    289    testPointEqual(
    290      wordEnd,
    291      paragraphStart,
    292      "The word end from the previous block is the first point in this block"
    293    );
    294  },
    295  { chrome: true, topLevel: true, iframe: false, remoteIframe: false }
    296 );
    297 
    298 // Test for skipping list item bullets.
    299 addAccessibleTask(
    300  `<ul>
    301    <li>One</li>
    302    <li>Two</li>
    303    <li style="white-space: pre-line;">Three
    304 Four</li>
    305  </ul>`,
    306  function (browser, docAcc) {
    307    const firstPoint = createTextLeafPoint(docAcc, 0);
    308    const lastPoint = createTextLeafPoint(docAcc, kTextEndOffset);
    309 
    310    const firstNonMarkerPoint = firstPoint.findBoundary(
    311      BOUNDARY_CHAR,
    312      DIRECTION_NEXT,
    313      BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER | BOUNDARY_FLAG_INCLUDE_ORIGIN
    314    );
    315    Assert.deepEqual(
    316      readablePoint(firstNonMarkerPoint),
    317      ["One", 0],
    318      "First non-marker point is correct"
    319    );
    320 
    321    const expectedParagraphStart = [
    322      ["One", 0],
    323      ["Two", 0],
    324      ["Three\nFour", 0],
    325      ["Three\nFour", 6],
    326    ];
    327 
    328    testBoundarySequence(
    329      firstPoint,
    330      BOUNDARY_PARAGRAPH,
    331      DIRECTION_NEXT,
    332      [...expectedParagraphStart, readablePoint(lastPoint)],
    333      "Forward BOUNDARY_PARAGRAPH skipping list item markers sequence is correct",
    334      { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER }
    335    );
    336 
    337    testBoundarySequence(
    338      lastPoint,
    339      BOUNDARY_PARAGRAPH,
    340      DIRECTION_PREVIOUS,
    341      [...expectedParagraphStart].reverse(),
    342      "Backward BOUNDARY_PARAGRAPH skipping list item markers sequence is correct",
    343      { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER }
    344    );
    345 
    346    const expectedCharSequence = [
    347      ["One", 0],
    348      ["One", 1],
    349      ["One", 2],
    350      ["Two", 0],
    351      ["Two", 1],
    352      ["Two", 2],
    353      ["Three\nFour", 0],
    354      ["Three\nFour", 1],
    355      ["Three\nFour", 2],
    356      ["Three\nFour", 3],
    357      ["Three\nFour", 4],
    358      ["Three\nFour", 5],
    359      ["Three\nFour", 6],
    360      ["Three\nFour", 7],
    361      ["Three\nFour", 8],
    362      ["Three\nFour", 9],
    363      ["Three\nFour", 10],
    364    ];
    365    testBoundarySequence(
    366      firstPoint,
    367      BOUNDARY_CHAR,
    368      DIRECTION_NEXT,
    369      expectedCharSequence,
    370      "Forward BOUNDARY_CHAR skipping list item markers sequence is correct",
    371      { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER }
    372    );
    373 
    374    testBoundarySequence(
    375      lastPoint,
    376      BOUNDARY_CHAR,
    377      DIRECTION_PREVIOUS,
    378      [...expectedCharSequence].reverse(),
    379      "Backward BOUNDARY_CHAR skipping list item markers sequence is correct",
    380      { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER }
    381    );
    382 
    383    const expectedWordStartSequence = [
    384      ["One", 0],
    385      ["Two", 0],
    386      ["Three\nFour", 0],
    387      ["Three\nFour", 6],
    388    ];
    389    testBoundarySequence(
    390      firstPoint,
    391      BOUNDARY_WORD_START,
    392      DIRECTION_NEXT,
    393      [...expectedWordStartSequence, readablePoint(lastPoint)],
    394      "Forward BOUNDARY_WORD_START skipping list item markers sequence is correct",
    395      { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER }
    396    );
    397 
    398    testBoundarySequence(
    399      lastPoint,
    400      BOUNDARY_WORD_START,
    401      DIRECTION_PREVIOUS,
    402      [...expectedWordStartSequence].reverse(),
    403      "Backward BOUNDARY_WORD_START skipping list item markers sequence is correct",
    404      { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER }
    405    );
    406 
    407    const expectedWordEndSequence = [
    408      ["Two", 0],
    409      ["Three\nFour", 0],
    410      ["Three\nFour", 5],
    411      ["Three\nFour", 10],
    412    ];
    413    testBoundarySequence(
    414      firstPoint,
    415      BOUNDARY_WORD_END,
    416      DIRECTION_NEXT,
    417      expectedWordEndSequence,
    418      "Forward BOUNDARY_WORD_END skipping list item markers sequence is correct",
    419      { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER }
    420    );
    421 
    422    testBoundarySequence(
    423      lastPoint,
    424      BOUNDARY_WORD_END,
    425      DIRECTION_PREVIOUS,
    426      [
    427        readablePoint(firstNonMarkerPoint),
    428        ...expectedWordEndSequence,
    429      ].reverse(),
    430      "Backward BOUNDARY_WORD_END skipping list item markers sequence is correct",
    431      { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER }
    432    );
    433 
    434    const expectedLineStartSequence = [
    435      ["One", 0],
    436      ["Two", 0],
    437      ["Three\nFour", 0],
    438      ["Three\nFour", 6],
    439    ];
    440    testBoundarySequence(
    441      firstPoint,
    442      BOUNDARY_LINE_START,
    443      DIRECTION_NEXT,
    444      // Add last point in doc
    445      [...expectedLineStartSequence, readablePoint(lastPoint)],
    446      "Forward BOUNDARY_LINE_START skipping list item markers sequence is correct",
    447      { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER }
    448    );
    449 
    450    testBoundarySequence(
    451      lastPoint,
    452      BOUNDARY_LINE_START,
    453      DIRECTION_PREVIOUS,
    454      // Add last point in doc
    455      [...expectedLineStartSequence].reverse(),
    456      "Backward BOUNDARY_LINE_START skipping list item markers sequence is correct",
    457      { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER }
    458    );
    459  },
    460  { chrome: true, topLevel: true, iframe: false, remoteIframe: false }
    461 );
    462 
    463 /**
    464 * Test the paragraph boundary on tables.
    465 */
    466 addAccessibleTask(
    467  `
    468 <table id="table">
    469  <tr><th>a</th><td>b</td></tr>
    470  <tr><td>c</td><td>d</td></tr>
    471 </table>
    472  `,
    473  async function (browser, docAcc) {
    474    const firstPoint = createTextLeafPoint(docAcc, 0);
    475    const lastPoint = createTextLeafPoint(docAcc, kTextEndOffset);
    476    testBoundarySequence(
    477      firstPoint,
    478      BOUNDARY_PARAGRAPH,
    479      DIRECTION_NEXT,
    480      [["a", 0], ["b", 0], ["c", 0], ["d", 0], readablePoint(lastPoint)],
    481      "Forward BOUNDARY_PARAGRAPH sequence is correct"
    482    );
    483  },
    484  { chrome: true, topLevel: true, iframe: false, remoteIframe: false }
    485 );
    486 
    487 /*
    488 * Test the word boundary with punctuation character
    489 */
    490 addAccessibleTask(
    491  `
    492 <p>ab'cd</p>
    493  `,
    494  async function (browser, docAcc) {
    495    const firstPoint = createTextLeafPoint(docAcc, 0);
    496    const lastPoint = createTextLeafPoint(docAcc, kTextEndOffset);
    497 
    498    const expectedWordStartSequence = [
    499      ["ab'cd", 0],
    500      ["ab'cd", 3],
    501      ["ab'cd", 5],
    502    ];
    503    testBoundarySequence(
    504      firstPoint,
    505      BOUNDARY_WORD_START,
    506      DIRECTION_NEXT,
    507      expectedWordStartSequence,
    508      "Forward BOUNDARY_WORD_START sequence is correct"
    509    );
    510    const expectedWordEndSequence = [
    511      ["ab'cd", 5],
    512      ["ab'cd", 3],
    513      ["ab'cd", 0],
    514    ];
    515    testBoundarySequence(
    516      lastPoint,
    517      BOUNDARY_WORD_END,
    518      DIRECTION_PREVIOUS,
    519      expectedWordEndSequence,
    520      "Backward BOUNDARY_WORD_END sequence is correct"
    521    );
    522  },
    523  { chrome: true, topLevel: true, iframe: false, remoteIframe: false }
    524 );