mirror of
https://github.com/servo/servo.git
synced 2025-06-24 17:14:33 +01:00
Update web-platform-tests to revision 8dea22c604b5c77f4b244e54373749ac50846947
This commit is contained in:
parent
c7f4eba3db
commit
edbe492dc8
53 changed files with 2798 additions and 111 deletions
|
@ -4,7 +4,7 @@
|
|||
expected: TIMEOUT
|
||||
|
||||
[Opening a blob URL in a new window immediately before revoking it works.]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
[Fetching a blob URL immediately before revoking it works in an iframe.]
|
||||
expected: FAIL
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[hit-test-floats-002.html]
|
||||
[Hit test float]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
[hit-test-floats-004.html]
|
||||
[hit-test-floats-003.html]
|
||||
[Miss float below something else]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[hit-test-floats-005.html]
|
||||
[Miss clipped float]
|
||||
expected: FAIL
|
||||
|
|
@ -2,6 +2,3 @@
|
|||
[Hit test intersecting scaled box]
|
||||
expected: FAIL
|
||||
|
||||
[Hit test within unscaled box]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[CaretPosition-001.html]
|
||||
[Element at (400, 100)]
|
||||
expected: FAIL
|
||||
|
|
@ -17,3 +17,6 @@
|
|||
[test the top of layer]
|
||||
expected: FAIL
|
||||
|
||||
[test some point of the element: top left corner]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[elementsFromPoint-invalid-cases.html]
|
||||
[The root element is the last element returned for otherwise empty queries within the viewport]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[matchMedia-display-none-iframe.html]
|
||||
expected: ERROR
|
|
@ -312,27 +312,24 @@
|
|||
[Response: combined response Content-Type: text/html;" \\" text/plain ";charset=GBK]
|
||||
expected: NOTRUN
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html;x=" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;" \\" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html */*]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/plain */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html */*]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html;" \\" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;charset=gbk text/plain text/html]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html;" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -53,12 +53,3 @@
|
|||
[combined text/javascript ]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript x/x]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript error]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript ]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[traverse_the_history_1.html]
|
||||
[Multiple history traversals from the same task]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[traverse_the_history_5.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
[embedded-opener-remove-frame.html]
|
||||
expected: CRASH
|
||||
[opener of discarded nested browsing context]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[supported-elements.html]
|
||||
expected: TIMEOUT
|
||||
[Contenteditable element should support autofocus]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -9,7 +10,7 @@
|
|||
expected: FAIL
|
||||
|
||||
[Area element should support autofocus]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
[Host element with delegatesFocus should support autofocus]
|
||||
expected: FAIL
|
||||
|
|
|
@ -171,3 +171,6 @@
|
|||
[XHTML img usemap="#hash-id"]
|
||||
expected: FAIL
|
||||
|
||||
[HTML (standards) IMG usemap="no-hash-name"]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[iframe_sandbox_popups_escaping-3.html]
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
|
||||
expected: TIMEOUT
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[iframe_sandbox_popups_nonescaping-1.html]
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe do not escape the sandbox]
|
||||
expected: NOTRUN
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[iframe_sandbox_popups_nonescaping-3.html]
|
||||
expected: CRASH
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe do not escape the sandbox]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[form-double-submit.html]
|
||||
[default submit action should supersede onclick submit()]
|
||||
expected: FAIL
|
||||
|
|
@ -3,3 +3,6 @@
|
|||
[The incumbent settings object while executing the compiled callback via Web IDL's invoke must be that of the node document]
|
||||
expected: TIMEOUT
|
||||
|
||||
[The entry settings object while executing the compiled callback via Web IDL's invoke must be that of the node document]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -275,3 +275,9 @@
|
|||
[X Stitched sine-wave buffers at sample rate 43800 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...\] with an element-wise tolerance of {"absoluteThreshold":0.0038986,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[28696\]\t-4.5381180933959784e-25\t9.3139332532882690e-1\t9.3139332532882690e-1\t1.0000000000000000e+0\t3.8985999999999999e-3\n\t[28697\]\t7.0477002859115601e-1\t9.0675884485244751e-1\t2.0198881626129150e-1\t2.2275913536212616e-1\t3.8985999999999999e-3\n\tMax AbsError of 9.3139332532882690e-1 at index of 28696.\n\tMax RelError of 1.0000000000000000e+0 at index of 28696.\n]
|
||||
expected: FAIL
|
||||
|
||||
[X SNR (43.8240408822966 dB) is not greater than or equal to 65.737. Got 43.8240408822966.]
|
||||
expected: FAIL
|
||||
|
||||
[X Stitched sine-wave buffers at sample rate 43800 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...\] with an element-wise tolerance of {"absoluteThreshold":0.0038986,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[28696\]\t1.9543942710671582e-15\t9.3139332532882690e-1\t9.3139332532882491e-1\t9.9999999999999789e-1\t3.8985999999999999e-3\n\t[28697\]\t7.0477002859115601e-1\t9.0675884485244751e-1\t2.0198881626129150e-1\t2.2275913536212616e-1\t3.8985999999999999e-3\n\tMax AbsError of 9.3139332532882491e-1 at index of 28696.\n\tMax RelError of 9.9999999999999789e-1 at index of 28696.\n]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[018.html]
|
||||
expected: TIMEOUT
|
||||
[origin of the script that invoked the method, javascript:]
|
||||
expected: TIMEOUT
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
[shared-worker-in-data-url-context.window.html]
|
||||
expected: TIMEOUT
|
||||
[Create a shared worker in a data url frame]
|
||||
expected: FAIL
|
||||
|
||||
[Create a data url shared worker in a data url frame]
|
||||
expected: TIMEOUT
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
expected: FAIL
|
||||
|
||||
[Opening a blob URL in a new window immediately before revoking it works.]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
[Opening a blob URL in a noopener about:blank window immediately before revoking it works.]
|
||||
expected: TIMEOUT
|
||||
|
|
|
@ -349654,7 +349654,7 @@
|
|||
[]
|
||||
],
|
||||
"input-events-get-target-ranges.js": [
|
||||
"6b922cdf03930ace471c9df2ddb58f74b1b24850",
|
||||
"f9404e07a5564c64a2863a1329728517fedd5ca7",
|
||||
[]
|
||||
]
|
||||
},
|
||||
|
@ -494457,6 +494457,37 @@
|
|||
}
|
||||
]
|
||||
],
|
||||
"input-events-get-target-ranges-deleting-in-list-items.tentative.html": [
|
||||
"2671fefa7cfc975cfc53de6859e394c445cb11f3",
|
||||
[
|
||||
"input-events/input-events-get-target-ranges-deleting-in-list-items.tentative.html?Backspace,ol",
|
||||
{
|
||||
"testdriver": true,
|
||||
"timeout": "long"
|
||||
}
|
||||
],
|
||||
[
|
||||
"input-events/input-events-get-target-ranges-deleting-in-list-items.tentative.html?Backspace,ul",
|
||||
{
|
||||
"testdriver": true,
|
||||
"timeout": "long"
|
||||
}
|
||||
],
|
||||
[
|
||||
"input-events/input-events-get-target-ranges-deleting-in-list-items.tentative.html?Delete,ol",
|
||||
{
|
||||
"testdriver": true,
|
||||
"timeout": "long"
|
||||
}
|
||||
],
|
||||
[
|
||||
"input-events/input-events-get-target-ranges-deleting-in-list-items.tentative.html?Delete,ul",
|
||||
{
|
||||
"testdriver": true,
|
||||
"timeout": "long"
|
||||
}
|
||||
]
|
||||
],
|
||||
"input-events-get-target-ranges-during-and-after-dispatch.tentative.html": [
|
||||
"be4656d04a84fada7f8b318a1df97ea062c39a95",
|
||||
[
|
||||
|
@ -494476,6 +494507,40 @@
|
|||
}
|
||||
]
|
||||
],
|
||||
"input-events-get-target-ranges-joining-dl-element-and-another-list.tentative.html": [
|
||||
"cebddac4c5b38d7575f42607f7b4128f0d0bc139",
|
||||
[
|
||||
"input-events/input-events-get-target-ranges-joining-dl-element-and-another-list.tentative.html?Backspace",
|
||||
{
|
||||
"testdriver": true,
|
||||
"timeout": "long"
|
||||
}
|
||||
],
|
||||
[
|
||||
"input-events/input-events-get-target-ranges-joining-dl-element-and-another-list.tentative.html?Delete",
|
||||
{
|
||||
"testdriver": true,
|
||||
"timeout": "long"
|
||||
}
|
||||
]
|
||||
],
|
||||
"input-events-get-target-ranges-joining-dl-elements.tentative.html": [
|
||||
"3e51dab7755e3bca9f3a29ab71b8f3a9922ce049",
|
||||
[
|
||||
"input-events/input-events-get-target-ranges-joining-dl-elements.tentative.html?Backspace",
|
||||
{
|
||||
"testdriver": true,
|
||||
"timeout": "long"
|
||||
}
|
||||
],
|
||||
[
|
||||
"input-events/input-events-get-target-ranges-joining-dl-elements.tentative.html?Delete",
|
||||
{
|
||||
"testdriver": true,
|
||||
"timeout": "long"
|
||||
}
|
||||
]
|
||||
],
|
||||
"input-events-get-target-ranges-non-collapsed-selection.tentative.html": [
|
||||
"b8732327dad4a8ee8570ca03400f9376112c53c7",
|
||||
[
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[hit-test-floats-002.html]
|
||||
[Hit test float]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
[hit-test-floats-004.html]
|
||||
[hit-test-floats-003.html]
|
||||
[Miss float below something else]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[hit-test-floats-005.html]
|
||||
[Miss clipped float]
|
||||
expected: FAIL
|
||||
|
|
@ -2,6 +2,3 @@
|
|||
[Hit test intersecting scaled box]
|
||||
expected: FAIL
|
||||
|
||||
[Hit test within unscaled box]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[CaretPosition-001.html]
|
||||
[Element at (400, 100)]
|
||||
expected: FAIL
|
||||
|
|
@ -21,3 +21,6 @@
|
|||
[test the top of layer]
|
||||
expected: FAIL
|
||||
|
||||
[test some point of the element: top left corner]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[elementsFromPoint-invalid-cases.html]
|
||||
[The root element is the last element returned for otherwise empty queries within the viewport]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[matchMedia-display-none-iframe.html]
|
||||
expected: ERROR
|
|
@ -312,27 +312,24 @@
|
|||
[fetch(): separate response Content-Type: text/plain ]
|
||||
expected: NOTRUN
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html;x=" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;" \\" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html */*]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/plain */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html */*]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html;" \\" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;charset=gbk text/plain text/html]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html;" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -53,12 +53,3 @@
|
|||
[combined text/javascript ]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript x/x]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript error]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript ]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[traverse_the_history_1.html]
|
||||
[Multiple history traversals from the same task]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[traverse_the_history_5.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
[embedded-opener-remove-frame.html]
|
||||
expected: CRASH
|
||||
[opener and "removed" embedded documents]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[supported-elements.html]
|
||||
expected: TIMEOUT
|
||||
[Contenteditable element should support autofocus]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -9,7 +10,7 @@
|
|||
expected: FAIL
|
||||
|
||||
[Area element should support autofocus]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
[Host element with delegatesFocus should support autofocus]
|
||||
expected: FAIL
|
||||
|
|
|
@ -172,3 +172,6 @@
|
|||
[XHTML img usemap="http://example.org/#garbage-before-hash-id"]
|
||||
expected: FAIL
|
||||
|
||||
[HTML (standards) IMG usemap="no-hash-name"]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
[iframe_sandbox_popups_escaping-3.html]
|
||||
type: testharness
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
|
||||
expected: TIMEOUT
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
[iframe_sandbox_popups_nonescaping-1.html]
|
||||
type: testharness
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe do not escape the sandbox]
|
||||
expected: NOTRUN
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[iframe_sandbox_popups_nonescaping-3.html]
|
||||
type: testharness
|
||||
expected: CRASH
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe do not escape the sandbox]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[form-double-submit.html]
|
||||
[default submit action should supersede onclick submit()]
|
||||
expected: FAIL
|
||||
|
|
@ -4,3 +4,6 @@
|
|||
[The incumbent settings object while executing the compiled callback via Web IDL's invoke must be that of the node document]
|
||||
expected: TIMEOUT
|
||||
|
||||
[The entry settings object while executing the compiled callback via Web IDL's invoke must be that of the node document]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -503,3 +503,9 @@
|
|||
[X Stitched sine-wave buffers at sample rate 43800 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...\] with an element-wise tolerance of {"absoluteThreshold":0.0038986,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[28696\]\t-4.5381180933959784e-25\t9.3139332532882690e-1\t9.3139332532882690e-1\t1.0000000000000000e+0\t3.8985999999999999e-3\n\t[28697\]\t7.0477002859115601e-1\t9.0675884485244751e-1\t2.0198881626129150e-1\t2.2275913536212616e-1\t3.8985999999999999e-3\n\tMax AbsError of 9.3139332532882690e-1 at index of 28696.\n\tMax RelError of 1.0000000000000000e+0 at index of 28696.\n]
|
||||
expected: FAIL
|
||||
|
||||
[X SNR (43.8240408822966 dB) is not greater than or equal to 65.737. Got 43.8240408822966.]
|
||||
expected: FAIL
|
||||
|
||||
[X Stitched sine-wave buffers at sample rate 43800 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...\] with an element-wise tolerance of {"absoluteThreshold":0.0038986,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[28696\]\t1.9543942710671582e-15\t9.3139332532882690e-1\t9.3139332532882491e-1\t9.9999999999999789e-1\t3.8985999999999999e-3\n\t[28697\]\t7.0477002859115601e-1\t9.0675884485244751e-1\t2.0198881626129150e-1\t2.2275913536212616e-1\t3.8985999999999999e-3\n\tMax AbsError of 9.3139332532882491e-1 at index of 28696.\n\tMax RelError of 9.9999999999999789e-1 at index of 28696.\n]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[018.html]
|
||||
expected: TIMEOUT
|
||||
[origin of the script that invoked the method, javascript:]
|
||||
expected: TIMEOUT
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
[shared-worker-in-data-url-context.window.html]
|
||||
expected: TIMEOUT
|
||||
[Create a shared worker in a data url frame]
|
||||
expected: FAIL
|
||||
|
||||
[Create a data url shared worker in a data url frame]
|
||||
expected: TIMEOUT
|
||||
expected: FAIL
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,285 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<meta name="timeout" content="long">
|
||||
<meta name="variant" content="?Backspace">
|
||||
<meta name="variant" content="?Delete">
|
||||
<title>InputEvent.getTargetRanges() at joining dl element and ol or ul element</title>
|
||||
<div contenteditable></div>
|
||||
<script src="input-events-get-target-ranges.js"></script>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/resources/testdriver-actions.js"></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
const action = location.search.substring(1);
|
||||
function run() {
|
||||
switch (action) {
|
||||
case "Backspace":
|
||||
return sendBackspaceKey();
|
||||
case "Delete":
|
||||
return sendDeleteKey();
|
||||
default:
|
||||
throw "Unhandled variant";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param innerHTML Initial `innerHTML` value of the editor.
|
||||
* @param data
|
||||
* expectedInnerHTML
|
||||
* Expected `innerHTML` of the editor after calling
|
||||
* `run()`. This can be array of string if there are
|
||||
* some acceptable differences like whether there is
|
||||
* an invisible `<br>` element at end of list item.
|
||||
* expectedTargetRanges
|
||||
* `null` or `unspecified` if `beforeinput` event shouldn't
|
||||
* be fired.
|
||||
* Otherwise, function returning an array of objects
|
||||
* which have `startContainer`, `startOffset`,
|
||||
* `endContainer`, `endOffset`. This will be called
|
||||
* before calling `run()` and compared with
|
||||
* `getTargetRanges()` after that.
|
||||
* expectInputEvent:
|
||||
* `true` if it should cause an `input` event.
|
||||
*/
|
||||
function addPromiseTest(innerHTML, data) {
|
||||
promise_test(async (t) => {
|
||||
initializeTest(innerHTML);
|
||||
let expectedTargetRanges =
|
||||
typeof data.expectedTargetRanges === "function"
|
||||
? data.expectedTargetRanges()
|
||||
: null;
|
||||
await run();
|
||||
checkEditorContentResultAsSubTest(data.expectedInnerHTML, t.name);
|
||||
if (expectedTargetRanges !== null) {
|
||||
checkGetTargetRangesOfBeforeinputOnDeleteSomething(expectedTargetRanges);
|
||||
if (data.expectInputEvent) {
|
||||
checkGetTargetRangesOfInputOnDeleteSomething();
|
||||
} else {
|
||||
checkGetTargetRangesOfInputOnDoNothing();
|
||||
}
|
||||
} else {
|
||||
checkBeforeinputAndInputEventsOnNOOP();
|
||||
}
|
||||
}, `${action} at "${innerHTML}"`);
|
||||
}
|
||||
|
||||
// TODO: This file does not have tests for the cases joining dl elements and
|
||||
// parent or child ul/ol elements. They should be added, but perhaps,
|
||||
// they are edge cases.
|
||||
|
||||
// Joining dl with ul/ol list element
|
||||
for (let otherList of ["ul", "ol"]) {
|
||||
for (let firstItem of ["dt", "dd"]) {
|
||||
addPromiseTest(
|
||||
action === "Backspace"
|
||||
? `<${otherList}><li>list-item1</li></${otherList}><dl><${firstItem}>[]list-item2</${firstItem}></dl>`
|
||||
: `<${otherList}><li>list-item1[]</li></${otherList}><dl><${firstItem}>list-item2</${firstItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: `<${otherList}><li>list-item1list-item2</li></${otherList}>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector("li").firstChild,
|
||||
startOffset: gEditor.querySelector("li").firstChild.length,
|
||||
endContainer: gEditor.querySelector(firstItem).firstChild,
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
for (let secondItem of ["dt", "dd"]) {
|
||||
addPromiseTest(
|
||||
action === "Backspace"
|
||||
? `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}}>list-item2</${secondItem}></dl><${otherList}><li>[]list-item3</li></${otherList}>`
|
||||
: `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item2[]</${secondItem}></dl><${otherList}><li>list-item3</li></${otherList}>`,
|
||||
{
|
||||
expectedInnerHTML: `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item2list-item3</${secondItem}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${firstItem} + ${secondItem}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${firstItem} + ${secondItem}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector("li").firstChild,
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>[list-item2</${secondItem}></dl><${otherList}><li>}list-item3</li></${otherList}>`,
|
||||
{
|
||||
expectedInnerHTML:
|
||||
secondItem === "dt"
|
||||
? [
|
||||
`<dl><${firstItem}>list-item1</${firstItem}></dl><${otherList}><li>list-item3</li></${otherList}>`,
|
||||
`<dl><${firstItem}>list-item1</${firstItem}></dl><${otherList}><li>list-item3<br></li></${otherList}>`,
|
||||
]
|
||||
: [
|
||||
`<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`,
|
||||
`<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item3<br></${secondItem}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${firstItem} + ${secondItem}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector("li"),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>[list-item2</${secondItem}></dl><${otherList}><li>list-item3]</li></${otherList}>`,
|
||||
{
|
||||
expectedInnerHTML: `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}><br></${secondItem}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(secondItem).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector("li").firstChild,
|
||||
endOffset: gEditor.querySelector("li").firstChild.length,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${firstItem}>[list-item1</${firstItem}><${secondItem}>list-item2</${secondItem}></dl><${otherList}><li>list-item3]</li></${otherList}>`,
|
||||
{
|
||||
expectedInnerHTML: `<dl><${firstItem}><br></${firstItem}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(firstItem).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector("li").firstChild,
|
||||
endOffset: gEditor.querySelector("li").firstChild.length,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
action === "Backspace"
|
||||
? `<${otherList}><li>list-item1</li></${otherList}><dl><${firstItem}>[]list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`
|
||||
: `<${otherList}><li>list-item1[]</li></${otherList}><dl><${firstItem}>list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: `<${otherList}><li>list-item1list-item2</li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector("li").firstChild,
|
||||
startOffset: gEditor.querySelector("li").firstChild.length,
|
||||
endContainer: gEditor.querySelector(firstItem).firstChild,
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<${otherList}><li>[list-item1</li></${otherList}><dl><${firstItem}>}list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<${otherList}><li>list-item2</li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`,
|
||||
`<${otherList}><li>list-item2<br></li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector("li").firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(firstItem),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<${otherList}><li>[list-item1</li></${otherList}><dl><${firstItem}>list-item2]</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: `<${otherList}><li><br></li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector("li").firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(firstItem).firstChild,
|
||||
endOffset: gEditor.querySelector(firstItem).firstChild.length,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<${otherList}><li>list-item1[</li></${otherList}><dl><${firstItem}>}list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<${otherList}><li>list-item1list-item2</li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`,
|
||||
`<${otherList}><li>list-item1list-item2<br></li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector("li").firstChild,
|
||||
startOffset: gEditor.querySelector("li").firstChild.length,
|
||||
endContainer: gEditor.querySelector(firstItem),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<${otherList}><li>list-item1[</li></${otherList}><dl><${firstItem}>list-item2</${firstItem}><${secondItem}>}list-item3</${secondItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<${otherList}><li>list-item1list-item3</li></${otherList}>`,
|
||||
`<${otherList}><li>list-item1list-item3<br></li></${otherList}>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector("li").firstChild,
|
||||
startOffset: gEditor.querySelector("li").firstChild.length,
|
||||
endContainer: gEditor.querySelector(secondItem),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
|
@ -0,0 +1,605 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<meta name="timeout" content="long">
|
||||
<meta name="variant" content="?Backspace">
|
||||
<meta name="variant" content="?Delete">
|
||||
<title>InputEvent.getTargetRanges() at deleting in/around/across list item elements</title>
|
||||
<div contenteditable></div>
|
||||
<script src="input-events-get-target-ranges.js"></script>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/resources/testdriver-actions.js"></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
const action = location.search.substring(1);
|
||||
function run() {
|
||||
switch (action) {
|
||||
case "Backspace":
|
||||
return sendBackspaceKey();
|
||||
case "Delete":
|
||||
return sendDeleteKey();
|
||||
default:
|
||||
throw "Unhandled variant";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param innerHTML Initial `innerHTML` value of the editor.
|
||||
* @param data
|
||||
* expectedInnerHTML
|
||||
* Expected `innerHTML` of the editor after calling
|
||||
* `run()`. This can be array of string if there are
|
||||
* some acceptable differences like whether there is
|
||||
* an invisible `<br>` element at end of list item.
|
||||
* expectedTargetRanges
|
||||
* `null` or `unspecified` if `beforeinput` event shouldn't
|
||||
* be fired.
|
||||
* Otherwise, function returning an array of objects
|
||||
* which have `startContainer`, `startOffset`,
|
||||
* `endContainer`, `endOffset`. This will be called
|
||||
* before calling `run()` and compared with
|
||||
* `getTargetRanges()` after that.
|
||||
* expectInputEvent:
|
||||
* `true` if it should cause an `input` event.
|
||||
*/
|
||||
function addPromiseTest(innerHTML, data) {
|
||||
promise_test(async (t) => {
|
||||
initializeTest(innerHTML);
|
||||
let expectedTargetRanges =
|
||||
typeof data.expectedTargetRanges === "function"
|
||||
? data.expectedTargetRanges()
|
||||
: null;
|
||||
await run();
|
||||
checkEditorContentResultAsSubTest(data.expectedInnerHTML, t.name);
|
||||
if (expectedTargetRanges !== null) {
|
||||
checkGetTargetRangesOfBeforeinputOnDeleteSomething(expectedTargetRanges);
|
||||
if (data.expectInputEvent) {
|
||||
checkGetTargetRangesOfInputOnDeleteSomething();
|
||||
} else {
|
||||
checkGetTargetRangesOfInputOnDoNothing();
|
||||
}
|
||||
} else {
|
||||
checkBeforeinputAndInputEventsOnNOOP();
|
||||
}
|
||||
}, `${action} at "${innerHTML}"`);
|
||||
}
|
||||
|
||||
// Join left list element and right list element, both have one item.
|
||||
function test_join_1_1(leftItem, rightItem) {
|
||||
addPromiseTest(
|
||||
action === "Backspace"
|
||||
? `<dl><${leftItem}>list-item1</${leftItem}></dl><dl><${rightItem}>[]list-item2</${rightItem}></dl>`
|
||||
: `<dl><${leftItem}>list-item1[]</${leftItem}></dl><dl><${rightItem}>list-item2</${rightItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<dl><${leftItem}>list-item1list-item2</${leftItem}></dl>`,
|
||||
`<dl><${leftItem}>list-item1list-item2<br></${leftItem}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${leftItem}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild,
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItem}>list-item1[</${leftItem}></dl><dl><${rightItem}>}list-item2</${rightItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<dl><${leftItem}>list-item1list-item2</${leftItem}></dl>`,
|
||||
`<dl><${leftItem}>list-item1list-item2<br></${leftItem}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${leftItem}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItem}>[list-item1</${leftItem}></dl><dl><${rightItem}>}list-item2</${rightItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML:
|
||||
leftItem === "dt" && rightItem === "dd"
|
||||
? [
|
||||
`<dl><${rightItem}>list-item2</${rightItem}></dl>`,
|
||||
`<dl><${rightItem}>list-item2<br></${rightItem}></dl>`,
|
||||
]
|
||||
: [
|
||||
`<dl><${leftItem}>list-item2</${leftItem}></dl>`,
|
||||
`<dl><${leftItem}>list-item2<br></${leftItem}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItem}>list-item1[</${leftItem}></dl><dl><${rightItem}>list-item2]</${rightItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<dl><${leftItem}>list-item1</${leftItem}></dl>`,
|
||||
`<dl><${leftItem}>list-item1<br></${leftItem}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild,
|
||||
endOffset: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild.length,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItem}>[list-item1</${leftItem}></dl><dl><${rightItem}>list-item2]</${rightItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: `<dl><${leftItem}><br></${leftItem}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild,
|
||||
endOffset: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild.length,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Join left list element which has 2 items and right list element which has one item.
|
||||
function test_join_2_1(leftItems, rightItem) {
|
||||
addPromiseTest(
|
||||
action === "Backspace"
|
||||
? `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItem}>[]list-item3</${rightItem}></dl>`
|
||||
: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[]</${leftItems[1]}></dl><dl><${rightItem}>list-item3</${rightItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3</${leftItems[1]}></dl>`,
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3<br></${leftItems[1]}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild,
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[</${leftItems[1]}></dl><dl><${rightItem}>}list-item3</${rightItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3</${leftItems[1]}></dl>`,
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3<br></${leftItems[1]}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>[list-item2</${leftItems[1]}></dl><dl><${rightItem}>}list-item3</${rightItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML:
|
||||
leftItems[1] === "dt" && rightItem === "dd"
|
||||
? [
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}></dl><dl><${rightItem}>list-item3</${rightItem}></dl>`,
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}></dl><dl><${rightItem}>list-item3<br></${rightItem}></dl>`,
|
||||
]
|
||||
: [
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item3</${leftItems[1]}></dl>`,
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item3<br></${leftItems[1]}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItems[0]}>[list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItem}>}list-item3</${rightItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML:
|
||||
leftItems[0] === "dt" && rightItem === "dd"
|
||||
? [
|
||||
`<dl><${rightItem}>list-item3</${rightItem}></dl>`,
|
||||
`<dl><${rightItem}>list-item3<br></${rightItem}></dl>`,
|
||||
]
|
||||
: [
|
||||
`<dl><${leftItems[0]}>list-item3</${leftItems[0]}></dl>`,
|
||||
`<dl><${leftItems[0]}>list-item3<br></${leftItems[0]}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[</${leftItems[1]}></dl><dl><${rightItem}>list-item3]</${rightItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>[list-item2</${leftItems[1]}></dl><dl><${rightItem}>list-item3]</${rightItem}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}><br></${leftItems[1]}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild,
|
||||
endOffset: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild.length,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Join left list element which has one item and right list element which has 2 items.
|
||||
function test_join_1_2(leftItem, rightItems) {
|
||||
addPromiseTest(
|
||||
action === "Backspace"
|
||||
? `<dl><${leftItem}>list-item1</${leftItem}></dl><dl><${rightItems[0]}>[]list-item2</${rightItems[0]}><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`
|
||||
: `<dl><${leftItem}>list-item1[]</${leftItem}></dl><dl><${rightItems[0]}>list-item2</${rightItems[0]}><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<dl><${leftItem}>list-item1list-item2</${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
|
||||
`<dl><${leftItem}>list-item1list-item2<br></${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${leftItem}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItem}>list-item1[</${leftItem}></dl><dl><${rightItems[0]}>}list-item2</${rightItems[0]}><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<dl><${leftItem}>list-item1list-item2</${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
|
||||
`<dl><${leftItem}>list-item1list-item2<br></${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${leftItem}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItem}>list-item1[</${leftItem}></dl><dl><${rightItems[0]}>list-item2]</${rightItems[0]}><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<dl><${leftItem}>list-item1</${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
|
||||
`<dl><${leftItem}>list-item1<br></${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}</dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${leftItem}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
|
||||
endOffset: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild.length,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItem}>[list-item1</${leftItem}></dl><dl><${rightItems[0]}>list-item2]</${rightItems[0]}><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: `<dl><${leftItem}><br></${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
|
||||
endOffset: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild.length,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItem}>[list-item1</${leftItem}></dl><dl><${rightItems[0]}>list-item2</${rightItems[0]}><${rightItems[1]}>}list-item3</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML:
|
||||
leftItem === "dt" && rightItems[1] === "dd"
|
||||
? [
|
||||
`<dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
|
||||
`<dl><${rightItems[1]}>list-item3<br></${rightItems[1]}></dl>`,
|
||||
]
|
||||
: [
|
||||
`<dl><${leftItem}>list-item3</${leftItem}></dl>`,
|
||||
`<dl><${leftItem}>list-item3<br></${leftItem}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]} + ${rightItems[1]}`),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Join left list element and right list element, both have 2 items.
|
||||
function test_join_2_2(leftItems, rightItems) {
|
||||
addPromiseTest(
|
||||
action === "Backspace"
|
||||
? `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItems[0]}>[]list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`
|
||||
: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[]</${leftItems[1]}></dl><dl><${rightItems[0]}>list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3</${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3<br></${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[</${leftItems[1]}></dl><dl><${rightItems[0]}>}list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: [
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3</${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3<br></${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
// XXX This and next one's expectation come from Blink's behavior.
|
||||
// I'm not sure whether this is intentional complicated handling
|
||||
// or not.
|
||||
addPromiseTest(
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>[list-item2</${leftItems[1]}></dl><dl><${rightItems[0]}>}list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML:
|
||||
leftItems[1] === "dt" && rightItems[0] === "dd"
|
||||
? [
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}></dl><dl><${rightItems[0]}>list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}></dl><dl><${rightItems[0]}>list-item3<br></${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
]
|
||||
: [
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item3</${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item3<br></${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItems[0]}>[list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItems[0]}>}list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML:
|
||||
leftItems[0] === "dt" && rightItems[0] === "dd"
|
||||
? [
|
||||
`<dl><${rightItems[0]}>list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
`<dl><${rightItems[0]}>list-item3<br></${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
]
|
||||
: [
|
||||
`<dl><${leftItems[0]}>list-item3</${leftItems[0]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
`<dl><${leftItems[0]}>list-item3<br></${leftItems[0]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
],
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`),
|
||||
endOffset: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[</${leftItems[1]}></dl><dl><${rightItems[0]}>list-item3]</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
|
||||
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
|
||||
endOffset: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild.length,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>[list-item2</${leftItems[1]}></dl><dl><${rightItems[0]}>list-item3]</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}><br></${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
|
||||
endOffset: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild.length,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
|
||||
addPromiseTest(
|
||||
`<dl><${leftItems[0]}>[list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItems[0]}>list-item3</${rightItems[0]}><${rightItems[1]}>list-item4]</${rightItems[1]}></dl>`,
|
||||
{
|
||||
expectedInnerHTML: `<dl><${leftItems[0]}><br></${leftItems[0]}></dl>`,
|
||||
expectedTargetRanges: () => {
|
||||
return [
|
||||
{
|
||||
startContainer: gEditor.querySelector(`${leftItems[0]}`).firstChild,
|
||||
startOffset: 0,
|
||||
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]} + ${rightItems[1]}`).firstChild,
|
||||
endOffset: gEditor.querySelector(`dl + dl > ${rightItems[0]} + ${rightItems[1]}`).firstChild.length,
|
||||
},
|
||||
];
|
||||
},
|
||||
expectInputEvent: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Joining dl elements
|
||||
for (let listItem1 of ["dt", "dd"]) {
|
||||
for (let listItem2 of ["dt", "dd"]) {
|
||||
test_join_1_1(listItem1, listItem2);
|
||||
for (let listItem3 of ["dt", "dd"]) {
|
||||
test_join_2_1([listItem1, listItem2], listItem3);
|
||||
test_join_1_2(listItem1, [listItem2, listItem3]);
|
||||
for (let listItem4 of ["dt", "dd"]) {
|
||||
test_join_2_2([listItem1, listItem2], [listItem3, listItem4]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
|
@ -46,8 +46,7 @@ function initializeTest(aInnerHTML) {
|
|||
gEditor.addEventListener("input", onInput);
|
||||
}
|
||||
|
||||
gEditor.innerHTML = aInnerHTML;
|
||||
gEditor.focus();
|
||||
setupEditor(aInnerHTML);
|
||||
gBeforeinput = [];
|
||||
gInput = [];
|
||||
}
|
||||
|
@ -251,3 +250,267 @@ function checkEditorContentResultAsSubTest(
|
|||
}
|
||||
}, `${description} - comparing innerHTML`);
|
||||
}
|
||||
|
||||
// Similar to `setupDiv` in editing/include/tests.js, this method sets
|
||||
// innerHTML value of gEditor, and sets multiple selection ranges specified
|
||||
// with the markers.
|
||||
// - `[` specifies start boundary in a text node
|
||||
// - `{` specifies start boundary before a node
|
||||
// - `]` specifies end boundary in a text node
|
||||
// - `}` specifies end boundary after a node
|
||||
function setupEditor(innerHTMLWithRangeMarkers) {
|
||||
const startBoundaries = innerHTMLWithRangeMarkers.match(/\{|\[/g) || [];
|
||||
const endBoundaries = innerHTMLWithRangeMarkers.match(/\}|\]/g) || [];
|
||||
if (startBoundaries.length !== endBoundaries.length) {
|
||||
throw "Should match number of open/close markers";
|
||||
}
|
||||
|
||||
gEditor.innerHTML = innerHTMLWithRangeMarkers;
|
||||
gEditor.focus();
|
||||
|
||||
if (startBoundaries.length === 0) {
|
||||
// Don't remove the range for now since some tests may assume that
|
||||
// setting innerHTML does not remove all selection ranges.
|
||||
return;
|
||||
}
|
||||
|
||||
function getNextRangeAndDeleteMarker(startNode) {
|
||||
function getNextLeafNode(node) {
|
||||
function inclusiveDeepestFirstChildNode(container) {
|
||||
while (container.firstChild) {
|
||||
container = container.firstChild;
|
||||
}
|
||||
return container;
|
||||
}
|
||||
if (node.hasChildNodes()) {
|
||||
return inclusiveDeepestFirstChildNode(node);
|
||||
}
|
||||
if (node.nextSibling) {
|
||||
return inclusiveDeepestFirstChildNode(node.nextSibling);
|
||||
}
|
||||
let nextSibling = (function nextSiblingOfAncestorElement(child) {
|
||||
for (
|
||||
let parent = child.parentElement;
|
||||
parent && parent != gEditor;
|
||||
parent = parent.parentElement
|
||||
) {
|
||||
if (parent.nextSibling) {
|
||||
return parent.nextSibling;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})(node);
|
||||
if (!nextSibling) {
|
||||
return null;
|
||||
}
|
||||
return inclusiveDeepestFirstChildNode(nextSibling);
|
||||
}
|
||||
function scanMarkerInTextNode(textNode, offset) {
|
||||
return /[\{\[\]\}]/.exec(textNode.data.substr(offset));
|
||||
}
|
||||
let startMarker = (function scanNextStartMaker(
|
||||
startContainer,
|
||||
startOffset
|
||||
) {
|
||||
function scanStartMakerInTextNode(textNode, offset) {
|
||||
let scanResult = scanMarkerInTextNode(textNode, offset);
|
||||
if (scanResult === null) {
|
||||
return null;
|
||||
}
|
||||
if (scanResult[0] === "}" || scanResult[0] === "]") {
|
||||
throw "An end marker is found before a start marker";
|
||||
}
|
||||
return {
|
||||
marker: scanResult[0],
|
||||
container: textNode,
|
||||
offset: scanResult.index + offset,
|
||||
};
|
||||
}
|
||||
if (startContainer.nodeType === Node.TEXT_NODE) {
|
||||
let scanResult = scanStartMakerInTextNode(startContainer, startOffset);
|
||||
if (scanResult !== null) {
|
||||
return scanResult;
|
||||
}
|
||||
}
|
||||
let nextNode = startContainer;
|
||||
while ((nextNode = getNextLeafNode(nextNode))) {
|
||||
if (nextNode.nodeType === Node.TEXT_NODE) {
|
||||
let scanResult = scanStartMakerInTextNode(nextNode, 0);
|
||||
if (scanResult !== null) {
|
||||
return scanResult;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})(startNode, 0);
|
||||
if (startMarker === null) {
|
||||
return null;
|
||||
}
|
||||
let endMarker = (function scanNextEndMarker(startContainer, startOffset) {
|
||||
function scanEndMarkerInTextNode(textNode, offset) {
|
||||
let scanResult = scanMarkerInTextNode(textNode, offset);
|
||||
if (scanResult === null) {
|
||||
return null;
|
||||
}
|
||||
if (scanResult[0] === "{" || scanResult[0] === "[") {
|
||||
throw "A start marker is found before an end marker";
|
||||
}
|
||||
return {
|
||||
marker: scanResult[0],
|
||||
container: textNode,
|
||||
offset: scanResult.index + offset,
|
||||
};
|
||||
}
|
||||
if (startContainer.nodeType === Node.TEXT_NODE) {
|
||||
let scanResult = scanEndMarkerInTextNode(startContainer, startOffset);
|
||||
if (scanResult !== null) {
|
||||
return scanResult;
|
||||
}
|
||||
}
|
||||
let nextNode = startContainer;
|
||||
while ((nextNode = getNextLeafNode(nextNode))) {
|
||||
if (nextNode.nodeType === Node.TEXT_NODE) {
|
||||
let scanResult = scanEndMarkerInTextNode(nextNode, 0);
|
||||
if (scanResult !== null) {
|
||||
return scanResult;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})(startMarker.container, startMarker.offset + 1);
|
||||
if (endMarker === null) {
|
||||
throw "Found an open marker, but not found corresponding close marker";
|
||||
}
|
||||
function indexOfContainer(container, child) {
|
||||
let offset = 0;
|
||||
for (let node = container.firstChild; node; node = node.nextSibling) {
|
||||
if (node == child) {
|
||||
return offset;
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
throw "child must be a child node of container";
|
||||
}
|
||||
(function deleteFoundMarkers() {
|
||||
function removeNode(node) {
|
||||
let container = node.parentElement;
|
||||
let offset = indexOfContainer(container, node);
|
||||
node.remove();
|
||||
return { container, offset };
|
||||
}
|
||||
if (startMarker.container == endMarker.container) {
|
||||
// If the text node becomes empty, remove it and set collapsed range
|
||||
// to the position where there is the text node.
|
||||
if (startMarker.container.length === 2) {
|
||||
if (!/[\[\{][\]\}]/.test(startMarker.container.data)) {
|
||||
throw `Unexpected text node (data: "${startMarker.container.data}")`;
|
||||
}
|
||||
let { container, offset } = removeNode(startMarker.container);
|
||||
startMarker.container = endMarker.container = container;
|
||||
startMarker.offset = endMarker.offset = offset;
|
||||
startMarker.marker = endMarker.marker = "";
|
||||
return;
|
||||
}
|
||||
startMarker.container.data = `${startMarker.container.data.substring(
|
||||
0,
|
||||
startMarker.offset
|
||||
)}${startMarker.container.data.substring(
|
||||
startMarker.offset + 1,
|
||||
endMarker.offset
|
||||
)}${startMarker.container.data.substring(endMarker.offset + 1)}`;
|
||||
if (startMarker.offset >= startMarker.container.length) {
|
||||
startMarker.offset = endMarker.offset = startMarker.container.length;
|
||||
return;
|
||||
}
|
||||
endMarker.offset--; // remove the start marker's length
|
||||
if (endMarker.offset > endMarker.container.length) {
|
||||
endMarker.offset = endMarker.container.length;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (startMarker.container.length === 1) {
|
||||
let { container, offset } = removeNode(startMarker.container);
|
||||
startMarker.container = container;
|
||||
startMarker.offset = offset;
|
||||
startMarker.marker = "";
|
||||
} else {
|
||||
startMarker.container.data = `${startMarker.container.data.substring(
|
||||
0,
|
||||
startMarker.offset
|
||||
)}${startMarker.container.data.substring(startMarker.offset + 1)}`;
|
||||
}
|
||||
if (endMarker.container.length === 1) {
|
||||
let { container, offset } = removeNode(endMarker.container);
|
||||
endMarker.container = container;
|
||||
endMarker.offset = offset;
|
||||
endMarker.marker = "";
|
||||
} else {
|
||||
endMarker.container.data = `${endMarker.container.data.substring(
|
||||
0,
|
||||
endMarker.offset
|
||||
)}${endMarker.container.data.substring(endMarker.offset + 1)}`;
|
||||
}
|
||||
})();
|
||||
(function handleNodeSelectMarker() {
|
||||
if (startMarker.marker === "{") {
|
||||
if (startMarker.offset === 0) {
|
||||
// The range start with the text node.
|
||||
let container = startMarker.container.parentElement;
|
||||
startMarker.offset = indexOfContainer(
|
||||
container,
|
||||
startMarker.container
|
||||
);
|
||||
startMarker.container = container;
|
||||
} else if (startMarker.offset === startMarker.container.data.length) {
|
||||
// The range start after the text node.
|
||||
let container = startMarker.container.parentElement;
|
||||
startMarker.offset =
|
||||
indexOfContainer(container, startMarker.container) + 1;
|
||||
startMarker.container = container;
|
||||
} else {
|
||||
throw 'Start marker "{" is allowed start or end of a text node';
|
||||
}
|
||||
}
|
||||
if (endMarker.marker === "}") {
|
||||
if (endMarker.offset === 0) {
|
||||
// The range ends before the text node.
|
||||
let container = endMarker.container.parentElement;
|
||||
endMarker.offset = indexOfContainer(container, endMarker.container);
|
||||
endMarker.container = container;
|
||||
} else if (endMarker.offset === endMarker.container.data.length) {
|
||||
// The range ends with the text node.
|
||||
let container = endMarker.container.parentElement;
|
||||
endMarker.offset =
|
||||
indexOfContainer(container, endMarker.container) + 1;
|
||||
endMarker.container = container;
|
||||
} else {
|
||||
throw 'End marker "}" is allowed start or end of a text node';
|
||||
}
|
||||
}
|
||||
})();
|
||||
let range = document.createRange();
|
||||
range.setStart(startMarker.container, startMarker.offset);
|
||||
range.setEnd(endMarker.container, endMarker.offset);
|
||||
return range;
|
||||
}
|
||||
|
||||
let ranges = [];
|
||||
for (
|
||||
let range = getNextRangeAndDeleteMarker(gEditor.firstChild);
|
||||
range;
|
||||
range = getNextRangeAndDeleteMarker(range.endContainer)
|
||||
) {
|
||||
ranges.push(range);
|
||||
}
|
||||
|
||||
gSelection.removeAllRanges();
|
||||
for (let range of ranges) {
|
||||
gSelection.addRange(range);
|
||||
}
|
||||
|
||||
if (gSelection.rangeCount != ranges.length) {
|
||||
throw `Failed to set selection to the given ranges whose length is ${ranges.length}, but only ${gSelection.rangeCount} ranges are added`;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue