From 2aa4a82499d4becd2284cdb482213d541b8804dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 16:29:10 +0200 Subject: Adding upstream version 86.0.1. Signed-off-by: Daniel Baumann --- editor/libeditor/CSSEditUtils.cpp | 1293 +++ editor/libeditor/CSSEditUtils.h | 469 + editor/libeditor/ChangeAttributeTransaction.cpp | 112 + editor/libeditor/ChangeAttributeTransaction.h | 88 + editor/libeditor/ChangeStyleTransaction.cpp | 311 + editor/libeditor/ChangeStyleTransaction.h | 138 + editor/libeditor/CompositionTransaction.cpp | 390 + editor/libeditor/CompositionTransaction.h | 99 + editor/libeditor/CreateElementTransaction.cpp | 208 + editor/libeditor/CreateElementTransaction.h | 84 + editor/libeditor/DeleteNodeTransaction.cpp | 140 + editor/libeditor/DeleteNodeTransaction.h | 74 + editor/libeditor/DeleteRangeTransaction.cpp | 270 + editor/libeditor/DeleteRangeTransaction.h | 116 + editor/libeditor/DeleteTextTransaction.cpp | 154 + editor/libeditor/DeleteTextTransaction.h | 94 + editor/libeditor/EditAction.h | 784 ++ editor/libeditor/EditActionListener.h | 14 + editor/libeditor/EditAggregateTransaction.cpp | 101 + editor/libeditor/EditAggregateTransaction.h | 71 + editor/libeditor/EditTransactionBase.cpp | 78 + editor/libeditor/EditTransactionBase.h | 94 + editor/libeditor/EditorBase.cpp | 5757 ++++++++++++ editor/libeditor/EditorBase.h | 2691 ++++++ editor/libeditor/EditorCommands.cpp | 970 ++ editor/libeditor/EditorCommands.h | 920 ++ editor/libeditor/EditorController.cpp | 140 + editor/libeditor/EditorController.h | 30 + editor/libeditor/EditorDOMPoint.h | 1245 +++ editor/libeditor/EditorEventListener.cpp | 1272 +++ editor/libeditor/EditorEventListener.h | 132 + editor/libeditor/EditorUtils.cpp | 522 ++ editor/libeditor/EditorUtils.h | 1197 +++ editor/libeditor/HTMLAbsPositionEditor.cpp | 953 ++ editor/libeditor/HTMLAnonymousNodeEditor.cpp | 600 ++ editor/libeditor/HTMLEditSubActionHandler.cpp | 9603 ++++++++++++++++++++ editor/libeditor/HTMLEditUtils.cpp | 1057 +++ editor/libeditor/HTMLEditUtils.h | 1063 +++ editor/libeditor/HTMLEditor.cpp | 6471 +++++++++++++ editor/libeditor/HTMLEditor.h | 4945 ++++++++++ editor/libeditor/HTMLEditorCommands.cpp | 1350 +++ editor/libeditor/HTMLEditorController.cpp | 140 + editor/libeditor/HTMLEditorController.h | 26 + editor/libeditor/HTMLEditorDataTransfer.cpp | 3850 ++++++++ editor/libeditor/HTMLEditorDeleteHandler.cpp | 5308 +++++++++++ editor/libeditor/HTMLEditorDocumentCommands.cpp | 412 + editor/libeditor/HTMLEditorEventListener.cpp | 453 + editor/libeditor/HTMLEditorEventListener.h | 99 + editor/libeditor/HTMLEditorObjectResizer.cpp | 1479 +++ editor/libeditor/HTMLEditorState.cpp | 603 ++ editor/libeditor/HTMLInlineTableEditor.cpp | 485 + editor/libeditor/HTMLStyleEditor.cpp | 2689 ++++++ editor/libeditor/HTMLTableEditor.cpp | 4382 +++++++++ editor/libeditor/InsertNodeTransaction.cpp | 171 + editor/libeditor/InsertNodeTransaction.h | 71 + editor/libeditor/InsertTextTransaction.cpp | 137 + editor/libeditor/InsertTextTransaction.h | 82 + editor/libeditor/InternetCiter.cpp | 305 + editor/libeditor/InternetCiter.h | 29 + editor/libeditor/JoinNodeTransaction.cpp | 142 + editor/libeditor/JoinNodeTransaction.h | 78 + editor/libeditor/ManualNAC.h | 118 + editor/libeditor/PlaceholderTransaction.cpp | 257 + editor/libeditor/PlaceholderTransaction.h | 101 + editor/libeditor/ReplaceTextTransaction.cpp | 175 + editor/libeditor/ReplaceTextTransaction.h | 84 + editor/libeditor/SelectionState.cpp | 589 ++ editor/libeditor/SelectionState.h | 449 + editor/libeditor/SplitNodeTransaction.cpp | 199 + editor/libeditor/SplitNodeTransaction.h | 77 + editor/libeditor/TextEditSubActionHandler.cpp | 1043 +++ editor/libeditor/TextEditor.cpp | 1979 ++++ editor/libeditor/TextEditor.h | 825 ++ editor/libeditor/TextEditorDataTransfer.cpp | 751 ++ editor/libeditor/TypeInState.cpp | 537 ++ editor/libeditor/TypeInState.h | 182 + editor/libeditor/WSRunObject.cpp | 3647 ++++++++ editor/libeditor/WSRunObject.h | 1522 ++++ editor/libeditor/crashtests/1057677.html | 9 + editor/libeditor/crashtests/1128787.html | 17 + editor/libeditor/crashtests/1134545.html | 22 + editor/libeditor/crashtests/1158452.html | 10 + editor/libeditor/crashtests/1158651.html | 18 + editor/libeditor/crashtests/1244894.xhtml | 21 + editor/libeditor/crashtests/1264921.html | 1 + editor/libeditor/crashtests/1272490.html | 20 + editor/libeditor/crashtests/1274050.html | 11 + editor/libeditor/crashtests/1317704.html | 36 + editor/libeditor/crashtests/1317718.html | 14 + editor/libeditor/crashtests/1324505.html | 24 + editor/libeditor/crashtests/1343918.html | 21 + editor/libeditor/crashtests/1344097.html | 20 + editor/libeditor/crashtests/1345015.html | 28 + editor/libeditor/crashtests/1348851.html | 19 + editor/libeditor/crashtests/1350772.html | 16 + editor/libeditor/crashtests/1364133.html | 42 + editor/libeditor/crashtests/1366176.html | 30 + editor/libeditor/crashtests/1375131.html | 33 + editor/libeditor/crashtests/1381541.html | 20 + editor/libeditor/crashtests/1383747.html | 15 + editor/libeditor/crashtests/1383755.html | 26 + editor/libeditor/crashtests/1383763.html | 17 + editor/libeditor/crashtests/1384161.html | 17 + editor/libeditor/crashtests/1388075.html | 23 + editor/libeditor/crashtests/1393171.html | 10 + editor/libeditor/crashtests/1402196.html | 21 + editor/libeditor/crashtests/1402469.html | 16 + editor/libeditor/crashtests/1402526.html | 14 + editor/libeditor/crashtests/1402904.html | 31 + editor/libeditor/crashtests/1405747.html | 23 + editor/libeditor/crashtests/1405897.html | 16 + editor/libeditor/crashtests/1408170.html | 20 + editor/libeditor/crashtests/1414581.html | 31 + editor/libeditor/crashtests/1415231.html | 17 + editor/libeditor/crashtests/1423767.html | 13 + editor/libeditor/crashtests/1423776.html | 15 + editor/libeditor/crashtests/1424450.html | 29 + editor/libeditor/crashtests/1425091.html | 15 + editor/libeditor/crashtests/1426709.html | 17 + editor/libeditor/crashtests/1441619.html | 12 + editor/libeditor/crashtests/1443664.html | 10 + editor/libeditor/crashtests/1444630.html | 27 + editor/libeditor/crashtests/1446451.html | 8 + editor/libeditor/crashtests/1464251.html | 21 + editor/libeditor/crashtests/1470926.html | 9 + editor/libeditor/crashtests/1474978.html | 14 + editor/libeditor/crashtests/1525481.html | 19 + editor/libeditor/crashtests/1533913.html | 14 + editor/libeditor/crashtests/1534394.html | 29 + editor/libeditor/crashtests/1547897.html | 17 + editor/libeditor/crashtests/1547898.html | 16 + editor/libeditor/crashtests/1556799.html | 11 + editor/libeditor/crashtests/1574544.html | 12 + editor/libeditor/crashtests/1578916.html | 15 + editor/libeditor/crashtests/1579934.html | 19 + editor/libeditor/crashtests/1581246.html | 11 + editor/libeditor/crashtests/1596516.html | 18 + editor/libeditor/crashtests/1605741.html | 9 + editor/libeditor/crashtests/1613521.html | 16 + editor/libeditor/crashtests/1618906.html | 17 + editor/libeditor/crashtests/1623913.html | 30 + editor/libeditor/crashtests/1624005.html | 14 + editor/libeditor/crashtests/1624007.html | 19 + editor/libeditor/crashtests/1624011.html | 12 + editor/libeditor/crashtests/1644903.html | 14 + editor/libeditor/crashtests/1645983-1.html | 8 + editor/libeditor/crashtests/1645983-2.html | 7 + editor/libeditor/crashtests/1648564.html | 19 + editor/libeditor/crashtests/1659717.html | 14 + editor/libeditor/crashtests/1663725.html | 13 + editor/libeditor/crashtests/1666556.html | 19 + editor/libeditor/crashtests/336081-1.xhtml | 52 + editor/libeditor/crashtests/336104.html | 37 + editor/libeditor/crashtests/382527-1.html | 58 + editor/libeditor/crashtests/382778-1.html | 53 + editor/libeditor/crashtests/402172-1.html | 23 + editor/libeditor/crashtests/403965-1.xhtml | 7 + editor/libeditor/crashtests/407074-1.html | 7 + editor/libeditor/crashtests/407079-1.html | 15 + editor/libeditor/crashtests/407256-1.html | 23 + editor/libeditor/crashtests/407277-1.html | 7 + editor/libeditor/crashtests/414178-1.html | 22 + editor/libeditor/crashtests/418923-1.html | 19 + editor/libeditor/crashtests/420439.html | 30 + editor/libeditor/crashtests/428489-1.html | 8 + editor/libeditor/crashtests/429586-1.html | 8 + editor/libeditor/crashtests/430624-1.html | 14 + editor/libeditor/crashtests/431086-1.xhtml | 22 + editor/libeditor/crashtests/448329-1.html | 72 + editor/libeditor/crashtests/448329-2.html | 21 + editor/libeditor/crashtests/448329-3.html | 112 + editor/libeditor/crashtests/456727-1.html | 8 + editor/libeditor/crashtests/456727-2.html | 8 + editor/libeditor/crashtests/459613-iframe.html | 1 + editor/libeditor/crashtests/459613.html | 17 + editor/libeditor/crashtests/467647-1.html | 19 + editor/libeditor/crashtests/475132-1.xhtml | 20 + editor/libeditor/crashtests/499844-1.html | 15 + editor/libeditor/crashtests/503709-1.xhtml | 11 + editor/libeditor/crashtests/513375-1.xhtml | 19 + editor/libeditor/crashtests/535632-1.xhtml | 1 + editor/libeditor/crashtests/574558-1.xhtml | 15 + editor/libeditor/crashtests/580151-1.xhtml | 26 + editor/libeditor/crashtests/582138-1.xhtml | 10 + editor/libeditor/crashtests/612565-1.html | 17 + editor/libeditor/crashtests/615015-1.html | 17 + editor/libeditor/crashtests/615450-1.html | 17 + editor/libeditor/crashtests/633709.xhtml | 36 + editor/libeditor/crashtests/636074-1.html | 18 + editor/libeditor/crashtests/639736-1.xhtml | 14 + editor/libeditor/crashtests/643786-1.html | 18 + editor/libeditor/crashtests/650572-1.html | 18 + editor/libeditor/crashtests/667321-1.html | 15 + editor/libeditor/crashtests/682650-1.html | 30 + editor/libeditor/crashtests/713427-1.html | 9 + editor/libeditor/crashtests/713427-2.xhtml | 28 + editor/libeditor/crashtests/716456-1.html | 29 + editor/libeditor/crashtests/745494.html | 17 + editor/libeditor/crashtests/759748.html | 58 + editor/libeditor/crashtests/761861.html | 15 + editor/libeditor/crashtests/762183.html | 6 + editor/libeditor/crashtests/766305.html | 21 + editor/libeditor/crashtests/766360.html | 18 + editor/libeditor/crashtests/766387.html | 20 + editor/libeditor/crashtests/766413.html | 42 + editor/libeditor/crashtests/766795.html | 21 + editor/libeditor/crashtests/766845.xhtml | 27 + editor/libeditor/crashtests/767169.html | 23 + editor/libeditor/crashtests/768748.html | 16 + editor/libeditor/crashtests/768765.html | 36 + editor/libeditor/crashtests/769008-1.html | 23 + editor/libeditor/crashtests/769967.xhtml | 16 + editor/libeditor/crashtests/771749.html | 21 + editor/libeditor/crashtests/772282.html | 27 + editor/libeditor/crashtests/776323.html | 18 + editor/libeditor/crashtests/793866.html | 21 + editor/libeditor/crashtests/848644.html | 2 + editor/libeditor/crashtests/crashtests.list | 138 + editor/libeditor/moz.build | 99 + editor/libeditor/tests/.eslintrc.js | 11 + editor/libeditor/tests/browser.ini | 7 + editor/libeditor/tests/browser_bug527935.js | 85 + .../tests/browserscope/lib/richtext/LICENSE | 202 + .../tests/browserscope/lib/richtext/README | 58 + .../tests/browserscope/lib/richtext/README.Mozilla | 17 + .../browserscope/lib/richtext/currentStatus.js | 46 + .../browserscope/lib/richtext/current_revision | 1 + .../lib/richtext/richtext/editable.html | 11 + .../browserscope/lib/richtext/richtext/js/range.js | 1069 +++ .../lib/richtext/richtext/richtext.html | 1081 +++ .../browserscope/lib/richtext/update_from_upstream | 16 + .../tests/browserscope/lib/richtext2/LICENSE | 202 + .../tests/browserscope/lib/richtext2/README | 58 + .../browserscope/lib/richtext2/README.Mozilla | 27 + .../browserscope/lib/richtext2/currentStatus.js | 1843 ++++ .../browserscope/lib/richtext2/current_revision | 1 + .../browserscope/lib/richtext2/platformFailures.js | 28 + .../lib/richtext2/richtext2/__init__.py | 0 .../browserscope/lib/richtext2/richtext2/common.py | 25 + .../lib/richtext2/richtext2/handlers.py | 107 + .../lib/richtext2/richtext2/static/common.css | 116 + .../richtext2/richtext2/static/editable-body.html | 11 + .../richtext2/richtext2/static/editable-dM.html | 17 + .../richtext2/richtext2/static/editable-div.html | 11 + .../lib/richtext2/richtext2/static/editable.css | 66 + .../richtext2/richtext2/static/js/canonicalize.js | 436 + .../lib/richtext2/richtext2/static/js/compare.js | 489 + .../lib/richtext2/richtext2/static/js/output.js | 456 + .../lib/richtext2/richtext2/static/js/pad.js | 269 + .../richtext2/static/js/range-bootstrap.js | 5 + .../lib/richtext2/richtext2/static/js/range.js | 6184 +++++++++++++ .../lib/richtext2/richtext2/static/js/run.js | 383 + .../lib/richtext2/richtext2/static/js/units.js | 416 + .../lib/richtext2/richtext2/static/js/variables.js | 227 + .../lib/richtext2/richtext2/templates/output.html | 138 + .../richtext2/richtext2/templates/richtext2.html | 107 + .../lib/richtext2/richtext2/tests/__init__.py | 17 + .../lib/richtext2/richtext2/tests/apply.py | 364 + .../lib/richtext2/richtext2/tests/applyCSS.py | 244 + .../lib/richtext2/richtext2/tests/change.py | 273 + .../lib/richtext2/richtext2/tests/changeCSS.py | 210 + .../lib/richtext2/richtext2/tests/delete.py | 330 + .../lib/richtext2/richtext2/tests/forwarddelete.py | 315 + .../lib/richtext2/richtext2/tests/insert.py | 285 + .../lib/richtext2/richtext2/tests/queryEnabled.py | 215 + .../lib/richtext2/richtext2/tests/queryIndeterm.py | 214 + .../lib/richtext2/richtext2/tests/queryState.py | 575 ++ .../richtext2/richtext2/tests/querySupported.py | 226 + .../lib/richtext2/richtext2/tests/queryValue.py | 429 + .../lib/richtext2/richtext2/tests/selection.py | 801 ++ .../lib/richtext2/richtext2/tests/unapply.py | 462 + .../lib/richtext2/richtext2/tests/unapplyCSS.py | 226 + .../lib/richtext2/richtext2/unittestexample.html | 103 + .../lib/richtext2/update_from_upstream | 19 + editor/libeditor/tests/browserscope/mochitest.ini | 59 + .../tests/browserscope/test_richtext.html | 48 + .../tests/browserscope/test_richtext2.html | 238 + editor/libeditor/tests/bug527935.html | 11 + editor/libeditor/tests/bug527935_2.html | 1 + editor/libeditor/tests/chrome.ini | 19 + editor/libeditor/tests/data/cfhtml-chromium.txt | Bin 0 -> 856 bytes editor/libeditor/tests/data/cfhtml-firefox.txt | Bin 0 -> 266 bytes editor/libeditor/tests/data/cfhtml-ie.txt | Bin 0 -> 1080 bytes editor/libeditor/tests/data/cfhtml-nocontext.txt | 18 + editor/libeditor/tests/data/cfhtml-ooo.txt | Bin 0 -> 649 bytes editor/libeditor/tests/file_bug289384-1.html | 1 + editor/libeditor/tests/file_bug289384-2.html | 1 + editor/libeditor/tests/file_bug549262.html | 8 + editor/libeditor/tests/file_bug586662.html | 7 + editor/libeditor/tests/file_bug611182.html | 1 + editor/libeditor/tests/file_bug611182.sjs | 240 + editor/libeditor/tests/file_bug635636.xhtml | 3 + editor/libeditor/tests/file_bug635636_2.html | 1 + editor/libeditor/tests/file_bug674770-1.html | 5 + editor/libeditor/tests/file_bug795418-2.sjs | 8 + editor/libeditor/tests/file_bug915962.html | 13 + editor/libeditor/tests/file_bug966155.html | 1 + editor/libeditor/tests/file_bug966552.html | 1 + editor/libeditor/tests/file_sanitizer_on_paste.sjs | 16 + .../tests/file_select_all_without_body.html | 38 + editor/libeditor/tests/green.png | Bin 0 -> 334 bytes editor/libeditor/tests/mochitest.ini | 318 + editor/libeditor/tests/spellcheck.js | 36 + editor/libeditor/tests/test_CF_HTML_clipboard.html | 149 + .../tests/test_abs_positioner_appearance.html | 177 + ...test_abs_positioner_hidden_during_dragging.html | 102 + .../test_abs_positioner_positioning_elements.html | 200 + editor/libeditor/tests/test_backspace_vs.html | 128 + editor/libeditor/tests/test_bug1026397.html | 101 + editor/libeditor/tests/test_bug1053048.html | 69 + editor/libeditor/tests/test_bug1068979.html | 72 + editor/libeditor/tests/test_bug1094000.html | 137 + editor/libeditor/tests/test_bug1100966.html | 72 + editor/libeditor/tests/test_bug1102906.html | 51 + editor/libeditor/tests/test_bug1109465.html | 65 + editor/libeditor/tests/test_bug1130651.html | 17 + editor/libeditor/tests/test_bug1140105.html | 64 + editor/libeditor/tests/test_bug1140617.html | 37 + editor/libeditor/tests/test_bug1151186.html | 69 + editor/libeditor/tests/test_bug1153237.html | 48 + editor/libeditor/tests/test_bug1154791.html | 72 + editor/libeditor/tests/test_bug1162952.html | 43 + editor/libeditor/tests/test_bug1181130-1.html | 50 + editor/libeditor/tests/test_bug1181130-2.html | 44 + editor/libeditor/tests/test_bug1186799.html | 78 + editor/libeditor/tests/test_bug1230473.html | 103 + editor/libeditor/tests/test_bug1247483.html | 61 + editor/libeditor/tests/test_bug1248128.html | 52 + editor/libeditor/tests/test_bug1248185.html | 56 + editor/libeditor/tests/test_bug1250010.html | 90 + editor/libeditor/tests/test_bug1257363.html | 180 + editor/libeditor/tests/test_bug1258085.html | 67 + editor/libeditor/tests/test_bug1268736.html | 60 + editor/libeditor/tests/test_bug1270235.html | 46 + editor/libeditor/tests/test_bug1306532.html | 68 + editor/libeditor/tests/test_bug1310912.html | 121 + editor/libeditor/tests/test_bug1314790.html | 57 + editor/libeditor/tests/test_bug1315065.html | 145 + editor/libeditor/tests/test_bug1316302.html | 50 + editor/libeditor/tests/test_bug1318312.html | 108 + editor/libeditor/tests/test_bug1328023.html | 61 + editor/libeditor/tests/test_bug1330796.html | 95 + editor/libeditor/tests/test_bug1332876.html | 57 + editor/libeditor/tests/test_bug1352799.html | 84 + editor/libeditor/tests/test_bug1355792.html | 17 + editor/libeditor/tests/test_bug1358025.html | 98 + editor/libeditor/tests/test_bug1361008.html | 61 + editor/libeditor/tests/test_bug1361052.html | 50 + editor/libeditor/tests/test_bug1368544.html | 90 + editor/libeditor/tests/test_bug1385905.html | 51 + editor/libeditor/tests/test_bug1386222.xhtml | 31 + editor/libeditor/tests/test_bug1390562.html | 67 + editor/libeditor/tests/test_bug1394758.html | 60 + editor/libeditor/tests/test_bug1397412.xhtml | 65 + editor/libeditor/tests/test_bug1399722.html | 38 + editor/libeditor/tests/test_bug1406726.html | 126 + editor/libeditor/tests/test_bug1409520.html | 45 + editor/libeditor/tests/test_bug1425997.html | 63 + editor/libeditor/tests/test_bug1497480.html | 93 + editor/libeditor/tests/test_bug1543312.html | 68 + editor/libeditor/tests/test_bug1568996.html | 67 + editor/libeditor/tests/test_bug1574596.html | 64 + editor/libeditor/tests/test_bug1581337.html | 33 + editor/libeditor/tests/test_bug1619852.html | 34 + editor/libeditor/tests/test_bug1620778.html | 27 + editor/libeditor/tests/test_bug1649005.html | 45 + editor/libeditor/tests/test_bug1659276.html | 78 + editor/libeditor/tests/test_bug200416.html | 15 + editor/libeditor/tests/test_bug289384.html | 48 + editor/libeditor/tests/test_bug290026.html | 52 + editor/libeditor/tests/test_bug291780.html | 49 + editor/libeditor/tests/test_bug309731.html | 58 + editor/libeditor/tests/test_bug316447.html | 16 + editor/libeditor/tests/test_bug318065.html | 82 + editor/libeditor/tests/test_bug332636.html | 75 + .../libeditor/tests/test_bug332636.html^headers^ | 1 + editor/libeditor/tests/test_bug358033.html | 41 + editor/libeditor/tests/test_bug366682.html | 64 + editor/libeditor/tests/test_bug372345.html | 58 + editor/libeditor/tests/test_bug404320.html | 87 + editor/libeditor/tests/test_bug408231.html | 249 + editor/libeditor/tests/test_bug410986.html | 80 + editor/libeditor/tests/test_bug414526.html | 234 + editor/libeditor/tests/test_bug417418.html | 78 + editor/libeditor/tests/test_bug426246.html | 71 + editor/libeditor/tests/test_bug430392.html | 181 + editor/libeditor/tests/test_bug432225.html | 70 + editor/libeditor/tests/test_bug439808.html | 37 + editor/libeditor/tests/test_bug442186.html | 103 + editor/libeditor/tests/test_bug449243.html | 146 + editor/libeditor/tests/test_bug455992.html | 96 + editor/libeditor/tests/test_bug456244.html | 69 + editor/libeditor/tests/test_bug460740.html | 124 + editor/libeditor/tests/test_bug46555.html | 47 + editor/libeditor/tests/test_bug471319.html | 77 + editor/libeditor/tests/test_bug471722.html | 79 + editor/libeditor/tests/test_bug478725.html | 130 + editor/libeditor/tests/test_bug480647.html | 110 + editor/libeditor/tests/test_bug480972.html | 97 + editor/libeditor/tests/test_bug483651.html | 52 + editor/libeditor/tests/test_bug484181.html | 72 + editor/libeditor/tests/test_bug489202.xhtml | 73 + editor/libeditor/tests/test_bug490879.html | 45 + editor/libeditor/tests/test_bug502673.html | 97 + editor/libeditor/tests/test_bug514156.html | 46 + editor/libeditor/tests/test_bug520189.html | 621 ++ editor/libeditor/tests/test_bug525389.html | 207 + editor/libeditor/tests/test_bug537046.html | 49 + editor/libeditor/tests/test_bug549262.html | 160 + editor/libeditor/tests/test_bug550434.html | 42 + editor/libeditor/tests/test_bug551704.html | 126 + editor/libeditor/tests/test_bug552782.html | 46 + editor/libeditor/tests/test_bug567213.html | 58 + editor/libeditor/tests/test_bug569988.html | 104 + editor/libeditor/tests/test_bug570144.html | 123 + editor/libeditor/tests/test_bug578771.html | 63 + editor/libeditor/tests/test_bug586662.html | 62 + editor/libeditor/tests/test_bug587461.html | 16 + editor/libeditor/tests/test_bug590554.html | 36 + editor/libeditor/tests/test_bug592592.html | 72 + editor/libeditor/tests/test_bug596001.html | 57 + editor/libeditor/tests/test_bug596333.html | 138 + editor/libeditor/tests/test_bug596506.html | 55 + editor/libeditor/tests/test_bug597331.html | 73 + editor/libeditor/tests/test_bug597784.html | 37 + editor/libeditor/tests/test_bug599322.html | 58 + editor/libeditor/tests/test_bug599983.html | 16 + editor/libeditor/tests/test_bug599983.xhtml | 67 + editor/libeditor/tests/test_bug600570.html | 81 + editor/libeditor/tests/test_bug602130.html | 44 + editor/libeditor/tests/test_bug603556.html | 53 + editor/libeditor/tests/test_bug604532.html | 42 + editor/libeditor/tests/test_bug607584.html | 41 + editor/libeditor/tests/test_bug607584.xhtml | 112 + editor/libeditor/tests/test_bug611182.html | 105 + editor/libeditor/tests/test_bug612128.html | 42 + editor/libeditor/tests/test_bug612447.html | 74 + editor/libeditor/tests/test_bug616590.xhtml | 101 + editor/libeditor/tests/test_bug620906.html | 50 + editor/libeditor/tests/test_bug622371.html | 44 + editor/libeditor/tests/test_bug625452.html | 66 + editor/libeditor/tests/test_bug629172.html | 106 + editor/libeditor/tests/test_bug629845.html | 58 + editor/libeditor/tests/test_bug635636.html | 63 + editor/libeditor/tests/test_bug636465.html | 53 + editor/libeditor/tests/test_bug638596.html | 34 + editor/libeditor/tests/test_bug641466.html | 48 + editor/libeditor/tests/test_bug645914.html | 63 + editor/libeditor/tests/test_bug646194.html | 36 + editor/libeditor/tests/test_bug668599.html | 73 + editor/libeditor/tests/test_bug674770-1.html | 85 + editor/libeditor/tests/test_bug674770-2.html | 378 + editor/libeditor/tests/test_bug674861.html | 194 + editor/libeditor/tests/test_bug676401.html | 126 + editor/libeditor/tests/test_bug677752.html | 107 + editor/libeditor/tests/test_bug681229.html | 50 + editor/libeditor/tests/test_bug686203.html | 50 + editor/libeditor/tests/test_bug692520.html | 41 + editor/libeditor/tests/test_bug697842.html | 114 + editor/libeditor/tests/test_bug725069.html | 34 + editor/libeditor/tests/test_bug735059.html | 22 + editor/libeditor/tests/test_bug738366.html | 24 + editor/libeditor/tests/test_bug740784.html | 46 + editor/libeditor/tests/test_bug742261.html | 14 + editor/libeditor/tests/test_bug757371.html | 26 + editor/libeditor/tests/test_bug757771.html | 31 + editor/libeditor/tests/test_bug767684.html | 15 + editor/libeditor/tests/test_bug772796.html | 218 + editor/libeditor/tests/test_bug773262.html | 63 + editor/libeditor/tests/test_bug780035.html | 23 + editor/libeditor/tests/test_bug780908.xhtml | 110 + editor/libeditor/tests/test_bug787432.html | 17 + editor/libeditor/tests/test_bug790475.html | 90 + editor/libeditor/tests/test_bug795418-2.html | 90 + editor/libeditor/tests/test_bug795418-3.html | 89 + editor/libeditor/tests/test_bug795418-4.html | 70 + editor/libeditor/tests/test_bug795418-5.html | 69 + editor/libeditor/tests/test_bug795418-6.html | 69 + editor/libeditor/tests/test_bug795418.html | 70 + editor/libeditor/tests/test_bug795785.html | 146 + editor/libeditor/tests/test_bug796839.html | 17 + editor/libeditor/tests/test_bug830600.html | 97 + editor/libeditor/tests/test_bug832025.html | 43 + editor/libeditor/tests/test_bug850043.html | 59 + editor/libeditor/tests/test_bug857487.html | 68 + editor/libeditor/tests/test_bug858918.html | 16 + editor/libeditor/tests/test_bug915962.html | 120 + editor/libeditor/tests/test_bug966155.html | 54 + editor/libeditor/tests/test_bug966552.html | 42 + editor/libeditor/tests/test_bug974309.html | 74 + editor/libeditor/tests/test_bug998188.html | 51 + .../libeditor/tests/test_cmd_fontFace_with_tt.html | 73 + .../test_composition_event_created_in_chrome.html | 76 + .../tests/test_contenteditable_focus.html | 190 + .../test_contenteditable_text_input_handling.html | 314 + .../test_cut_copy_delete_command_enabled.html | 71 + .../test_cut_copy_delete_command_enabled.xhtml | 215 + editor/libeditor/tests/test_cut_copy_password.html | 92 + .../libeditor/tests/test_documentCharacterSet.html | 59 + .../tests/test_dom_input_event_on_htmleditor.html | 1716 ++++ .../tests/test_dom_input_event_on_texteditor.html | 942 ++ editor/libeditor/tests/test_dragdrop.html | 2641 ++++++ .../tests/test_execCommandPaste_noTarget.html | 45 + editor/libeditor/tests/test_handle_new_lines.html | 129 + .../tests/test_htmleditor_keyevent_handling.html | 655 ++ .../libeditor/tests/test_inlineTableEditing.html | 45 + .../libeditor/tests/test_inline_style_cache.html | 227 + ...est_insertParagraph_in_inline_editing_host.html | 67 + .../tests/test_keypress_untrusted_event.html | 93 + .../tests/test_label_contenteditable.html | 18 + .../libeditor/tests/test_middle_click_paste.html | 667 ++ ...sIEditorMailSupport_insertAsCitedQuotation.html | 175 + .../tests/test_nsIEditor_insertLineBreak.html | 420 + ..._nsIHTMLEditor_getElementOrParentByTagName.html | 449 + .../test_nsIHTMLEditor_getParagraphState.html | 156 + .../test_nsIHTMLEditor_getSelectedElement.html | 816 ++ .../test_nsIHTMLEditor_removeInlineProperty.html | 424 + .../tests/test_nsIHTMLEditor_selectElement.html | 131 + .../test_nsIHTMLEditor_setBackgroundColor.html | 187 + .../test_nsIHTMLEditor_setCaretAfterElement.html | 149 + .../test_nsIHTMLObjectResizer_hideResizers.html | 54 + .../tests/test_nsITableEditor_deleteTableCell.html | 722 ++ ...est_nsITableEditor_deleteTableCellContents.html | 301 + .../test_nsITableEditor_deleteTableColumn.html | 525 ++ .../tests/test_nsITableEditor_deleteTableRow.html | 532 ++ .../tests/test_nsITableEditor_getCellAt.html | 139 + .../tests/test_nsITableEditor_getCellDataAt.html | 756 ++ .../tests/test_nsITableEditor_getCellIndexes.html | 92 + .../tests/test_nsITableEditor_getFirstRow.html | 105 + ...nsITableEditor_getFirstSelectedCellInTable.html | 201 + .../test_nsITableEditor_getSelectedCells.html | 295 + .../test_nsITableEditor_getSelectedCellsType.html | 274 + ...ableEditor_getSelectedOrParentTableElement.html | 283 + .../tests/test_nsITableEditor_getTableSize.html | 95 + .../tests/test_nsITableEditor_insertTableCell.html | 400 + .../test_nsITableEditor_insertTableColumn.html | 287 + .../tests/test_nsITableEditor_insertTableRow.html | 307 + .../test_password_input_with_unmasked_range.html | 417 + editor/libeditor/tests/test_password_paste.html | 65 + .../tests/test_password_per_word_operation.html | 148 + .../libeditor/tests/test_password_unmask_API.html | 164 + editor/libeditor/tests/test_pasteImgTextarea.html | 19 + editor/libeditor/tests/test_pasteImgTextarea.xhtml | 26 + .../libeditor/tests/test_pasting_table_rows.html | 532 ++ .../test_pasting_text_longer_than_maxlength.html | 53 + .../libeditor/tests/test_resizers_appearance.html | 109 + .../tests/test_resizers_resizing_elements.html | 312 + .../tests/test_root_element_replacement.html | 140 + .../libeditor/tests/test_sanitizer_on_paste.html | 48 + .../tests/test_select_all_without_body.html | 26 + .../tests/test_selection_move_commands.html | 225 + ...ue_longer_than_maxlength_with_setUserInput.html | 75 + editor/libeditor/tests/test_spellcheck_pref.html | 22 + .../tests/test_state_change_on_reframe.html | 29 + .../tests/test_textarea_value_not_include_cr.html | 93 + .../tests/test_texteditor_keyevent_handling.html | 376 + .../tests/test_typing_at_edge_of_anchor.html | 476 + ...test_undo_after_spellchecker_replaces_word.html | 179 + .../test_undo_redo_stack_after_setting_value.html | 166 + .../libeditor/tests/test_undo_with_editingui.html | 160 + 560 files changed, 138397 insertions(+) create mode 100644 editor/libeditor/CSSEditUtils.cpp create mode 100644 editor/libeditor/CSSEditUtils.h create mode 100644 editor/libeditor/ChangeAttributeTransaction.cpp create mode 100644 editor/libeditor/ChangeAttributeTransaction.h create mode 100644 editor/libeditor/ChangeStyleTransaction.cpp create mode 100644 editor/libeditor/ChangeStyleTransaction.h create mode 100644 editor/libeditor/CompositionTransaction.cpp create mode 100644 editor/libeditor/CompositionTransaction.h create mode 100644 editor/libeditor/CreateElementTransaction.cpp create mode 100644 editor/libeditor/CreateElementTransaction.h create mode 100644 editor/libeditor/DeleteNodeTransaction.cpp create mode 100644 editor/libeditor/DeleteNodeTransaction.h create mode 100644 editor/libeditor/DeleteRangeTransaction.cpp create mode 100644 editor/libeditor/DeleteRangeTransaction.h create mode 100644 editor/libeditor/DeleteTextTransaction.cpp create mode 100644 editor/libeditor/DeleteTextTransaction.h create mode 100644 editor/libeditor/EditAction.h create mode 100644 editor/libeditor/EditActionListener.h create mode 100644 editor/libeditor/EditAggregateTransaction.cpp create mode 100644 editor/libeditor/EditAggregateTransaction.h create mode 100644 editor/libeditor/EditTransactionBase.cpp create mode 100644 editor/libeditor/EditTransactionBase.h create mode 100644 editor/libeditor/EditorBase.cpp create mode 100644 editor/libeditor/EditorBase.h create mode 100644 editor/libeditor/EditorCommands.cpp create mode 100644 editor/libeditor/EditorCommands.h create mode 100644 editor/libeditor/EditorController.cpp create mode 100644 editor/libeditor/EditorController.h create mode 100644 editor/libeditor/EditorDOMPoint.h create mode 100644 editor/libeditor/EditorEventListener.cpp create mode 100644 editor/libeditor/EditorEventListener.h create mode 100644 editor/libeditor/EditorUtils.cpp create mode 100644 editor/libeditor/EditorUtils.h create mode 100644 editor/libeditor/HTMLAbsPositionEditor.cpp create mode 100644 editor/libeditor/HTMLAnonymousNodeEditor.cpp create mode 100644 editor/libeditor/HTMLEditSubActionHandler.cpp create mode 100644 editor/libeditor/HTMLEditUtils.cpp create mode 100644 editor/libeditor/HTMLEditUtils.h create mode 100644 editor/libeditor/HTMLEditor.cpp create mode 100644 editor/libeditor/HTMLEditor.h create mode 100644 editor/libeditor/HTMLEditorCommands.cpp create mode 100644 editor/libeditor/HTMLEditorController.cpp create mode 100644 editor/libeditor/HTMLEditorController.h create mode 100644 editor/libeditor/HTMLEditorDataTransfer.cpp create mode 100644 editor/libeditor/HTMLEditorDeleteHandler.cpp create mode 100644 editor/libeditor/HTMLEditorDocumentCommands.cpp create mode 100644 editor/libeditor/HTMLEditorEventListener.cpp create mode 100644 editor/libeditor/HTMLEditorEventListener.h create mode 100644 editor/libeditor/HTMLEditorObjectResizer.cpp create mode 100644 editor/libeditor/HTMLEditorState.cpp create mode 100644 editor/libeditor/HTMLInlineTableEditor.cpp create mode 100644 editor/libeditor/HTMLStyleEditor.cpp create mode 100644 editor/libeditor/HTMLTableEditor.cpp create mode 100644 editor/libeditor/InsertNodeTransaction.cpp create mode 100644 editor/libeditor/InsertNodeTransaction.h create mode 100644 editor/libeditor/InsertTextTransaction.cpp create mode 100644 editor/libeditor/InsertTextTransaction.h create mode 100644 editor/libeditor/InternetCiter.cpp create mode 100644 editor/libeditor/InternetCiter.h create mode 100644 editor/libeditor/JoinNodeTransaction.cpp create mode 100644 editor/libeditor/JoinNodeTransaction.h create mode 100644 editor/libeditor/ManualNAC.h create mode 100644 editor/libeditor/PlaceholderTransaction.cpp create mode 100644 editor/libeditor/PlaceholderTransaction.h create mode 100644 editor/libeditor/ReplaceTextTransaction.cpp create mode 100644 editor/libeditor/ReplaceTextTransaction.h create mode 100644 editor/libeditor/SelectionState.cpp create mode 100644 editor/libeditor/SelectionState.h create mode 100644 editor/libeditor/SplitNodeTransaction.cpp create mode 100644 editor/libeditor/SplitNodeTransaction.h create mode 100644 editor/libeditor/TextEditSubActionHandler.cpp create mode 100644 editor/libeditor/TextEditor.cpp create mode 100644 editor/libeditor/TextEditor.h create mode 100644 editor/libeditor/TextEditorDataTransfer.cpp create mode 100644 editor/libeditor/TypeInState.cpp create mode 100644 editor/libeditor/TypeInState.h create mode 100644 editor/libeditor/WSRunObject.cpp create mode 100644 editor/libeditor/WSRunObject.h create mode 100644 editor/libeditor/crashtests/1057677.html create mode 100644 editor/libeditor/crashtests/1128787.html create mode 100644 editor/libeditor/crashtests/1134545.html create mode 100644 editor/libeditor/crashtests/1158452.html create mode 100644 editor/libeditor/crashtests/1158651.html create mode 100644 editor/libeditor/crashtests/1244894.xhtml create mode 100644 editor/libeditor/crashtests/1264921.html create mode 100644 editor/libeditor/crashtests/1272490.html create mode 100644 editor/libeditor/crashtests/1274050.html create mode 100644 editor/libeditor/crashtests/1317704.html create mode 100644 editor/libeditor/crashtests/1317718.html create mode 100644 editor/libeditor/crashtests/1324505.html create mode 100644 editor/libeditor/crashtests/1343918.html create mode 100644 editor/libeditor/crashtests/1344097.html create mode 100644 editor/libeditor/crashtests/1345015.html create mode 100644 editor/libeditor/crashtests/1348851.html create mode 100644 editor/libeditor/crashtests/1350772.html create mode 100644 editor/libeditor/crashtests/1364133.html create mode 100644 editor/libeditor/crashtests/1366176.html create mode 100644 editor/libeditor/crashtests/1375131.html create mode 100644 editor/libeditor/crashtests/1381541.html create mode 100644 editor/libeditor/crashtests/1383747.html create mode 100644 editor/libeditor/crashtests/1383755.html create mode 100644 editor/libeditor/crashtests/1383763.html create mode 100644 editor/libeditor/crashtests/1384161.html create mode 100644 editor/libeditor/crashtests/1388075.html create mode 100644 editor/libeditor/crashtests/1393171.html create mode 100644 editor/libeditor/crashtests/1402196.html create mode 100644 editor/libeditor/crashtests/1402469.html create mode 100644 editor/libeditor/crashtests/1402526.html create mode 100644 editor/libeditor/crashtests/1402904.html create mode 100644 editor/libeditor/crashtests/1405747.html create mode 100644 editor/libeditor/crashtests/1405897.html create mode 100644 editor/libeditor/crashtests/1408170.html create mode 100644 editor/libeditor/crashtests/1414581.html create mode 100644 editor/libeditor/crashtests/1415231.html create mode 100644 editor/libeditor/crashtests/1423767.html create mode 100644 editor/libeditor/crashtests/1423776.html create mode 100644 editor/libeditor/crashtests/1424450.html create mode 100644 editor/libeditor/crashtests/1425091.html create mode 100644 editor/libeditor/crashtests/1426709.html create mode 100644 editor/libeditor/crashtests/1441619.html create mode 100644 editor/libeditor/crashtests/1443664.html create mode 100644 editor/libeditor/crashtests/1444630.html create mode 100644 editor/libeditor/crashtests/1446451.html create mode 100644 editor/libeditor/crashtests/1464251.html create mode 100644 editor/libeditor/crashtests/1470926.html create mode 100644 editor/libeditor/crashtests/1474978.html create mode 100644 editor/libeditor/crashtests/1525481.html create mode 100644 editor/libeditor/crashtests/1533913.html create mode 100644 editor/libeditor/crashtests/1534394.html create mode 100644 editor/libeditor/crashtests/1547897.html create mode 100644 editor/libeditor/crashtests/1547898.html create mode 100644 editor/libeditor/crashtests/1556799.html create mode 100644 editor/libeditor/crashtests/1574544.html create mode 100644 editor/libeditor/crashtests/1578916.html create mode 100644 editor/libeditor/crashtests/1579934.html create mode 100644 editor/libeditor/crashtests/1581246.html create mode 100644 editor/libeditor/crashtests/1596516.html create mode 100644 editor/libeditor/crashtests/1605741.html create mode 100644 editor/libeditor/crashtests/1613521.html create mode 100644 editor/libeditor/crashtests/1618906.html create mode 100644 editor/libeditor/crashtests/1623913.html create mode 100644 editor/libeditor/crashtests/1624005.html create mode 100644 editor/libeditor/crashtests/1624007.html create mode 100644 editor/libeditor/crashtests/1624011.html create mode 100644 editor/libeditor/crashtests/1644903.html create mode 100644 editor/libeditor/crashtests/1645983-1.html create mode 100644 editor/libeditor/crashtests/1645983-2.html create mode 100644 editor/libeditor/crashtests/1648564.html create mode 100644 editor/libeditor/crashtests/1659717.html create mode 100644 editor/libeditor/crashtests/1663725.html create mode 100644 editor/libeditor/crashtests/1666556.html create mode 100644 editor/libeditor/crashtests/336081-1.xhtml create mode 100644 editor/libeditor/crashtests/336104.html create mode 100644 editor/libeditor/crashtests/382527-1.html create mode 100644 editor/libeditor/crashtests/382778-1.html create mode 100644 editor/libeditor/crashtests/402172-1.html create mode 100644 editor/libeditor/crashtests/403965-1.xhtml create mode 100644 editor/libeditor/crashtests/407074-1.html create mode 100644 editor/libeditor/crashtests/407079-1.html create mode 100644 editor/libeditor/crashtests/407256-1.html create mode 100644 editor/libeditor/crashtests/407277-1.html create mode 100644 editor/libeditor/crashtests/414178-1.html create mode 100644 editor/libeditor/crashtests/418923-1.html create mode 100644 editor/libeditor/crashtests/420439.html create mode 100644 editor/libeditor/crashtests/428489-1.html create mode 100644 editor/libeditor/crashtests/429586-1.html create mode 100644 editor/libeditor/crashtests/430624-1.html create mode 100644 editor/libeditor/crashtests/431086-1.xhtml create mode 100644 editor/libeditor/crashtests/448329-1.html create mode 100644 editor/libeditor/crashtests/448329-2.html create mode 100644 editor/libeditor/crashtests/448329-3.html create mode 100644 editor/libeditor/crashtests/456727-1.html create mode 100644 editor/libeditor/crashtests/456727-2.html create mode 100644 editor/libeditor/crashtests/459613-iframe.html create mode 100644 editor/libeditor/crashtests/459613.html create mode 100644 editor/libeditor/crashtests/467647-1.html create mode 100644 editor/libeditor/crashtests/475132-1.xhtml create mode 100644 editor/libeditor/crashtests/499844-1.html create mode 100644 editor/libeditor/crashtests/503709-1.xhtml create mode 100644 editor/libeditor/crashtests/513375-1.xhtml create mode 100644 editor/libeditor/crashtests/535632-1.xhtml create mode 100644 editor/libeditor/crashtests/574558-1.xhtml create mode 100644 editor/libeditor/crashtests/580151-1.xhtml create mode 100644 editor/libeditor/crashtests/582138-1.xhtml create mode 100644 editor/libeditor/crashtests/612565-1.html create mode 100644 editor/libeditor/crashtests/615015-1.html create mode 100644 editor/libeditor/crashtests/615450-1.html create mode 100644 editor/libeditor/crashtests/633709.xhtml create mode 100644 editor/libeditor/crashtests/636074-1.html create mode 100644 editor/libeditor/crashtests/639736-1.xhtml create mode 100644 editor/libeditor/crashtests/643786-1.html create mode 100644 editor/libeditor/crashtests/650572-1.html create mode 100644 editor/libeditor/crashtests/667321-1.html create mode 100644 editor/libeditor/crashtests/682650-1.html create mode 100644 editor/libeditor/crashtests/713427-1.html create mode 100644 editor/libeditor/crashtests/713427-2.xhtml create mode 100644 editor/libeditor/crashtests/716456-1.html create mode 100644 editor/libeditor/crashtests/745494.html create mode 100644 editor/libeditor/crashtests/759748.html create mode 100644 editor/libeditor/crashtests/761861.html create mode 100644 editor/libeditor/crashtests/762183.html create mode 100644 editor/libeditor/crashtests/766305.html create mode 100644 editor/libeditor/crashtests/766360.html create mode 100644 editor/libeditor/crashtests/766387.html create mode 100644 editor/libeditor/crashtests/766413.html create mode 100644 editor/libeditor/crashtests/766795.html create mode 100644 editor/libeditor/crashtests/766845.xhtml create mode 100644 editor/libeditor/crashtests/767169.html create mode 100644 editor/libeditor/crashtests/768748.html create mode 100644 editor/libeditor/crashtests/768765.html create mode 100644 editor/libeditor/crashtests/769008-1.html create mode 100644 editor/libeditor/crashtests/769967.xhtml create mode 100644 editor/libeditor/crashtests/771749.html create mode 100644 editor/libeditor/crashtests/772282.html create mode 100644 editor/libeditor/crashtests/776323.html create mode 100644 editor/libeditor/crashtests/793866.html create mode 100644 editor/libeditor/crashtests/848644.html create mode 100644 editor/libeditor/crashtests/crashtests.list create mode 100644 editor/libeditor/moz.build create mode 100644 editor/libeditor/tests/.eslintrc.js create mode 100644 editor/libeditor/tests/browser.ini create mode 100644 editor/libeditor/tests/browser_bug527935.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext/LICENSE create mode 100644 editor/libeditor/tests/browserscope/lib/richtext/README create mode 100644 editor/libeditor/tests/browserscope/lib/richtext/README.Mozilla create mode 100644 editor/libeditor/tests/browserscope/lib/richtext/currentStatus.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext/current_revision create mode 100644 editor/libeditor/tests/browserscope/lib/richtext/richtext/editable.html create mode 100644 editor/libeditor/tests/browserscope/lib/richtext/richtext/js/range.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext/richtext/richtext.html create mode 100644 editor/libeditor/tests/browserscope/lib/richtext/update_from_upstream create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/LICENSE create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/README create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/README.Mozilla create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/current_revision create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/platformFailures.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/__init__.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/common.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/handlers.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/common.css create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-body.html create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-dM.html create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-div.html create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable.css create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/canonicalize.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/compare.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/output.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/pad.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range-bootstrap.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/run.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/units.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/variables.js create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/templates/output.html create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/templates/richtext2.html create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/__init__.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/apply.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/applyCSS.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/change.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/changeCSS.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/delete.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/forwarddelete.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/insert.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryEnabled.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryIndeterm.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryState.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/querySupported.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryValue.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/selection.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapply.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapplyCSS.py create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/richtext2/unittestexample.html create mode 100644 editor/libeditor/tests/browserscope/lib/richtext2/update_from_upstream create mode 100644 editor/libeditor/tests/browserscope/mochitest.ini create mode 100644 editor/libeditor/tests/browserscope/test_richtext.html create mode 100644 editor/libeditor/tests/browserscope/test_richtext2.html create mode 100644 editor/libeditor/tests/bug527935.html create mode 100644 editor/libeditor/tests/bug527935_2.html create mode 100644 editor/libeditor/tests/chrome.ini create mode 100644 editor/libeditor/tests/data/cfhtml-chromium.txt create mode 100644 editor/libeditor/tests/data/cfhtml-firefox.txt create mode 100644 editor/libeditor/tests/data/cfhtml-ie.txt create mode 100644 editor/libeditor/tests/data/cfhtml-nocontext.txt create mode 100644 editor/libeditor/tests/data/cfhtml-ooo.txt create mode 100644 editor/libeditor/tests/file_bug289384-1.html create mode 100644 editor/libeditor/tests/file_bug289384-2.html create mode 100644 editor/libeditor/tests/file_bug549262.html create mode 100644 editor/libeditor/tests/file_bug586662.html create mode 100644 editor/libeditor/tests/file_bug611182.html create mode 100644 editor/libeditor/tests/file_bug611182.sjs create mode 100644 editor/libeditor/tests/file_bug635636.xhtml create mode 100644 editor/libeditor/tests/file_bug635636_2.html create mode 100644 editor/libeditor/tests/file_bug674770-1.html create mode 100644 editor/libeditor/tests/file_bug795418-2.sjs create mode 100644 editor/libeditor/tests/file_bug915962.html create mode 100644 editor/libeditor/tests/file_bug966155.html create mode 100644 editor/libeditor/tests/file_bug966552.html create mode 100644 editor/libeditor/tests/file_sanitizer_on_paste.sjs create mode 100644 editor/libeditor/tests/file_select_all_without_body.html create mode 100644 editor/libeditor/tests/green.png create mode 100644 editor/libeditor/tests/mochitest.ini create mode 100644 editor/libeditor/tests/spellcheck.js create mode 100644 editor/libeditor/tests/test_CF_HTML_clipboard.html create mode 100644 editor/libeditor/tests/test_abs_positioner_appearance.html create mode 100644 editor/libeditor/tests/test_abs_positioner_hidden_during_dragging.html create mode 100644 editor/libeditor/tests/test_abs_positioner_positioning_elements.html create mode 100644 editor/libeditor/tests/test_backspace_vs.html create mode 100644 editor/libeditor/tests/test_bug1026397.html create mode 100644 editor/libeditor/tests/test_bug1053048.html create mode 100644 editor/libeditor/tests/test_bug1068979.html create mode 100644 editor/libeditor/tests/test_bug1094000.html create mode 100644 editor/libeditor/tests/test_bug1100966.html create mode 100644 editor/libeditor/tests/test_bug1102906.html create mode 100644 editor/libeditor/tests/test_bug1109465.html create mode 100644 editor/libeditor/tests/test_bug1130651.html create mode 100644 editor/libeditor/tests/test_bug1140105.html create mode 100644 editor/libeditor/tests/test_bug1140617.html create mode 100644 editor/libeditor/tests/test_bug1151186.html create mode 100644 editor/libeditor/tests/test_bug1153237.html create mode 100644 editor/libeditor/tests/test_bug1154791.html create mode 100644 editor/libeditor/tests/test_bug1162952.html create mode 100644 editor/libeditor/tests/test_bug1181130-1.html create mode 100644 editor/libeditor/tests/test_bug1181130-2.html create mode 100644 editor/libeditor/tests/test_bug1186799.html create mode 100644 editor/libeditor/tests/test_bug1230473.html create mode 100644 editor/libeditor/tests/test_bug1247483.html create mode 100644 editor/libeditor/tests/test_bug1248128.html create mode 100644 editor/libeditor/tests/test_bug1248185.html create mode 100644 editor/libeditor/tests/test_bug1250010.html create mode 100644 editor/libeditor/tests/test_bug1257363.html create mode 100644 editor/libeditor/tests/test_bug1258085.html create mode 100644 editor/libeditor/tests/test_bug1268736.html create mode 100644 editor/libeditor/tests/test_bug1270235.html create mode 100644 editor/libeditor/tests/test_bug1306532.html create mode 100644 editor/libeditor/tests/test_bug1310912.html create mode 100644 editor/libeditor/tests/test_bug1314790.html create mode 100644 editor/libeditor/tests/test_bug1315065.html create mode 100644 editor/libeditor/tests/test_bug1316302.html create mode 100644 editor/libeditor/tests/test_bug1318312.html create mode 100644 editor/libeditor/tests/test_bug1328023.html create mode 100644 editor/libeditor/tests/test_bug1330796.html create mode 100644 editor/libeditor/tests/test_bug1332876.html create mode 100644 editor/libeditor/tests/test_bug1352799.html create mode 100644 editor/libeditor/tests/test_bug1355792.html create mode 100644 editor/libeditor/tests/test_bug1358025.html create mode 100644 editor/libeditor/tests/test_bug1361008.html create mode 100644 editor/libeditor/tests/test_bug1361052.html create mode 100644 editor/libeditor/tests/test_bug1368544.html create mode 100644 editor/libeditor/tests/test_bug1385905.html create mode 100644 editor/libeditor/tests/test_bug1386222.xhtml create mode 100644 editor/libeditor/tests/test_bug1390562.html create mode 100644 editor/libeditor/tests/test_bug1394758.html create mode 100644 editor/libeditor/tests/test_bug1397412.xhtml create mode 100644 editor/libeditor/tests/test_bug1399722.html create mode 100644 editor/libeditor/tests/test_bug1406726.html create mode 100644 editor/libeditor/tests/test_bug1409520.html create mode 100644 editor/libeditor/tests/test_bug1425997.html create mode 100644 editor/libeditor/tests/test_bug1497480.html create mode 100644 editor/libeditor/tests/test_bug1543312.html create mode 100644 editor/libeditor/tests/test_bug1568996.html create mode 100644 editor/libeditor/tests/test_bug1574596.html create mode 100644 editor/libeditor/tests/test_bug1581337.html create mode 100644 editor/libeditor/tests/test_bug1619852.html create mode 100644 editor/libeditor/tests/test_bug1620778.html create mode 100644 editor/libeditor/tests/test_bug1649005.html create mode 100644 editor/libeditor/tests/test_bug1659276.html create mode 100644 editor/libeditor/tests/test_bug200416.html create mode 100644 editor/libeditor/tests/test_bug289384.html create mode 100644 editor/libeditor/tests/test_bug290026.html create mode 100644 editor/libeditor/tests/test_bug291780.html create mode 100644 editor/libeditor/tests/test_bug309731.html create mode 100644 editor/libeditor/tests/test_bug316447.html create mode 100644 editor/libeditor/tests/test_bug318065.html create mode 100644 editor/libeditor/tests/test_bug332636.html create mode 100644 editor/libeditor/tests/test_bug332636.html^headers^ create mode 100644 editor/libeditor/tests/test_bug358033.html create mode 100644 editor/libeditor/tests/test_bug366682.html create mode 100644 editor/libeditor/tests/test_bug372345.html create mode 100644 editor/libeditor/tests/test_bug404320.html create mode 100644 editor/libeditor/tests/test_bug408231.html create mode 100644 editor/libeditor/tests/test_bug410986.html create mode 100644 editor/libeditor/tests/test_bug414526.html create mode 100644 editor/libeditor/tests/test_bug417418.html create mode 100644 editor/libeditor/tests/test_bug426246.html create mode 100644 editor/libeditor/tests/test_bug430392.html create mode 100644 editor/libeditor/tests/test_bug432225.html create mode 100644 editor/libeditor/tests/test_bug439808.html create mode 100644 editor/libeditor/tests/test_bug442186.html create mode 100644 editor/libeditor/tests/test_bug449243.html create mode 100644 editor/libeditor/tests/test_bug455992.html create mode 100644 editor/libeditor/tests/test_bug456244.html create mode 100644 editor/libeditor/tests/test_bug460740.html create mode 100644 editor/libeditor/tests/test_bug46555.html create mode 100644 editor/libeditor/tests/test_bug471319.html create mode 100644 editor/libeditor/tests/test_bug471722.html create mode 100644 editor/libeditor/tests/test_bug478725.html create mode 100644 editor/libeditor/tests/test_bug480647.html create mode 100644 editor/libeditor/tests/test_bug480972.html create mode 100644 editor/libeditor/tests/test_bug483651.html create mode 100644 editor/libeditor/tests/test_bug484181.html create mode 100644 editor/libeditor/tests/test_bug489202.xhtml create mode 100644 editor/libeditor/tests/test_bug490879.html create mode 100644 editor/libeditor/tests/test_bug502673.html create mode 100644 editor/libeditor/tests/test_bug514156.html create mode 100644 editor/libeditor/tests/test_bug520189.html create mode 100644 editor/libeditor/tests/test_bug525389.html create mode 100644 editor/libeditor/tests/test_bug537046.html create mode 100644 editor/libeditor/tests/test_bug549262.html create mode 100644 editor/libeditor/tests/test_bug550434.html create mode 100644 editor/libeditor/tests/test_bug551704.html create mode 100644 editor/libeditor/tests/test_bug552782.html create mode 100644 editor/libeditor/tests/test_bug567213.html create mode 100644 editor/libeditor/tests/test_bug569988.html create mode 100644 editor/libeditor/tests/test_bug570144.html create mode 100644 editor/libeditor/tests/test_bug578771.html create mode 100644 editor/libeditor/tests/test_bug586662.html create mode 100644 editor/libeditor/tests/test_bug587461.html create mode 100644 editor/libeditor/tests/test_bug590554.html create mode 100644 editor/libeditor/tests/test_bug592592.html create mode 100644 editor/libeditor/tests/test_bug596001.html create mode 100644 editor/libeditor/tests/test_bug596333.html create mode 100644 editor/libeditor/tests/test_bug596506.html create mode 100644 editor/libeditor/tests/test_bug597331.html create mode 100644 editor/libeditor/tests/test_bug597784.html create mode 100644 editor/libeditor/tests/test_bug599322.html create mode 100644 editor/libeditor/tests/test_bug599983.html create mode 100644 editor/libeditor/tests/test_bug599983.xhtml create mode 100644 editor/libeditor/tests/test_bug600570.html create mode 100644 editor/libeditor/tests/test_bug602130.html create mode 100644 editor/libeditor/tests/test_bug603556.html create mode 100644 editor/libeditor/tests/test_bug604532.html create mode 100644 editor/libeditor/tests/test_bug607584.html create mode 100644 editor/libeditor/tests/test_bug607584.xhtml create mode 100644 editor/libeditor/tests/test_bug611182.html create mode 100644 editor/libeditor/tests/test_bug612128.html create mode 100644 editor/libeditor/tests/test_bug612447.html create mode 100644 editor/libeditor/tests/test_bug616590.xhtml create mode 100644 editor/libeditor/tests/test_bug620906.html create mode 100644 editor/libeditor/tests/test_bug622371.html create mode 100644 editor/libeditor/tests/test_bug625452.html create mode 100644 editor/libeditor/tests/test_bug629172.html create mode 100644 editor/libeditor/tests/test_bug629845.html create mode 100644 editor/libeditor/tests/test_bug635636.html create mode 100644 editor/libeditor/tests/test_bug636465.html create mode 100644 editor/libeditor/tests/test_bug638596.html create mode 100644 editor/libeditor/tests/test_bug641466.html create mode 100644 editor/libeditor/tests/test_bug645914.html create mode 100644 editor/libeditor/tests/test_bug646194.html create mode 100644 editor/libeditor/tests/test_bug668599.html create mode 100644 editor/libeditor/tests/test_bug674770-1.html create mode 100644 editor/libeditor/tests/test_bug674770-2.html create mode 100644 editor/libeditor/tests/test_bug674861.html create mode 100644 editor/libeditor/tests/test_bug676401.html create mode 100644 editor/libeditor/tests/test_bug677752.html create mode 100644 editor/libeditor/tests/test_bug681229.html create mode 100644 editor/libeditor/tests/test_bug686203.html create mode 100644 editor/libeditor/tests/test_bug692520.html create mode 100644 editor/libeditor/tests/test_bug697842.html create mode 100644 editor/libeditor/tests/test_bug725069.html create mode 100644 editor/libeditor/tests/test_bug735059.html create mode 100644 editor/libeditor/tests/test_bug738366.html create mode 100644 editor/libeditor/tests/test_bug740784.html create mode 100644 editor/libeditor/tests/test_bug742261.html create mode 100644 editor/libeditor/tests/test_bug757371.html create mode 100644 editor/libeditor/tests/test_bug757771.html create mode 100644 editor/libeditor/tests/test_bug767684.html create mode 100644 editor/libeditor/tests/test_bug772796.html create mode 100644 editor/libeditor/tests/test_bug773262.html create mode 100644 editor/libeditor/tests/test_bug780035.html create mode 100644 editor/libeditor/tests/test_bug780908.xhtml create mode 100644 editor/libeditor/tests/test_bug787432.html create mode 100644 editor/libeditor/tests/test_bug790475.html create mode 100644 editor/libeditor/tests/test_bug795418-2.html create mode 100644 editor/libeditor/tests/test_bug795418-3.html create mode 100644 editor/libeditor/tests/test_bug795418-4.html create mode 100644 editor/libeditor/tests/test_bug795418-5.html create mode 100644 editor/libeditor/tests/test_bug795418-6.html create mode 100644 editor/libeditor/tests/test_bug795418.html create mode 100644 editor/libeditor/tests/test_bug795785.html create mode 100644 editor/libeditor/tests/test_bug796839.html create mode 100644 editor/libeditor/tests/test_bug830600.html create mode 100644 editor/libeditor/tests/test_bug832025.html create mode 100644 editor/libeditor/tests/test_bug850043.html create mode 100644 editor/libeditor/tests/test_bug857487.html create mode 100644 editor/libeditor/tests/test_bug858918.html create mode 100644 editor/libeditor/tests/test_bug915962.html create mode 100644 editor/libeditor/tests/test_bug966155.html create mode 100644 editor/libeditor/tests/test_bug966552.html create mode 100644 editor/libeditor/tests/test_bug974309.html create mode 100644 editor/libeditor/tests/test_bug998188.html create mode 100644 editor/libeditor/tests/test_cmd_fontFace_with_tt.html create mode 100644 editor/libeditor/tests/test_composition_event_created_in_chrome.html create mode 100644 editor/libeditor/tests/test_contenteditable_focus.html create mode 100644 editor/libeditor/tests/test_contenteditable_text_input_handling.html create mode 100644 editor/libeditor/tests/test_cut_copy_delete_command_enabled.html create mode 100644 editor/libeditor/tests/test_cut_copy_delete_command_enabled.xhtml create mode 100644 editor/libeditor/tests/test_cut_copy_password.html create mode 100644 editor/libeditor/tests/test_documentCharacterSet.html create mode 100644 editor/libeditor/tests/test_dom_input_event_on_htmleditor.html create mode 100644 editor/libeditor/tests/test_dom_input_event_on_texteditor.html create mode 100644 editor/libeditor/tests/test_dragdrop.html create mode 100644 editor/libeditor/tests/test_execCommandPaste_noTarget.html create mode 100644 editor/libeditor/tests/test_handle_new_lines.html create mode 100644 editor/libeditor/tests/test_htmleditor_keyevent_handling.html create mode 100644 editor/libeditor/tests/test_inlineTableEditing.html create mode 100644 editor/libeditor/tests/test_inline_style_cache.html create mode 100644 editor/libeditor/tests/test_insertParagraph_in_inline_editing_host.html create mode 100644 editor/libeditor/tests/test_keypress_untrusted_event.html create mode 100644 editor/libeditor/tests/test_label_contenteditable.html create mode 100644 editor/libeditor/tests/test_middle_click_paste.html create mode 100644 editor/libeditor/tests/test_nsIEditorMailSupport_insertAsCitedQuotation.html create mode 100644 editor/libeditor/tests/test_nsIEditor_insertLineBreak.html create mode 100644 editor/libeditor/tests/test_nsIHTMLEditor_getElementOrParentByTagName.html create mode 100644 editor/libeditor/tests/test_nsIHTMLEditor_getParagraphState.html create mode 100644 editor/libeditor/tests/test_nsIHTMLEditor_getSelectedElement.html create mode 100644 editor/libeditor/tests/test_nsIHTMLEditor_removeInlineProperty.html create mode 100644 editor/libeditor/tests/test_nsIHTMLEditor_selectElement.html create mode 100644 editor/libeditor/tests/test_nsIHTMLEditor_setBackgroundColor.html create mode 100644 editor/libeditor/tests/test_nsIHTMLEditor_setCaretAfterElement.html create mode 100644 editor/libeditor/tests/test_nsIHTMLObjectResizer_hideResizers.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_deleteTableCell.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_deleteTableCellContents.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_deleteTableColumn.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_deleteTableRow.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_getCellAt.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_getCellDataAt.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_getCellIndexes.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_getFirstRow.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_getFirstSelectedCellInTable.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_getSelectedCells.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_getSelectedCellsType.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_getSelectedOrParentTableElement.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_getTableSize.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_insertTableCell.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_insertTableColumn.html create mode 100644 editor/libeditor/tests/test_nsITableEditor_insertTableRow.html create mode 100644 editor/libeditor/tests/test_password_input_with_unmasked_range.html create mode 100644 editor/libeditor/tests/test_password_paste.html create mode 100644 editor/libeditor/tests/test_password_per_word_operation.html create mode 100644 editor/libeditor/tests/test_password_unmask_API.html create mode 100644 editor/libeditor/tests/test_pasteImgTextarea.html create mode 100644 editor/libeditor/tests/test_pasteImgTextarea.xhtml create mode 100644 editor/libeditor/tests/test_pasting_table_rows.html create mode 100644 editor/libeditor/tests/test_pasting_text_longer_than_maxlength.html create mode 100644 editor/libeditor/tests/test_resizers_appearance.html create mode 100644 editor/libeditor/tests/test_resizers_resizing_elements.html create mode 100644 editor/libeditor/tests/test_root_element_replacement.html create mode 100644 editor/libeditor/tests/test_sanitizer_on_paste.html create mode 100644 editor/libeditor/tests/test_select_all_without_body.html create mode 100644 editor/libeditor/tests/test_selection_move_commands.html create mode 100644 editor/libeditor/tests/test_setting_value_longer_than_maxlength_with_setUserInput.html create mode 100644 editor/libeditor/tests/test_spellcheck_pref.html create mode 100644 editor/libeditor/tests/test_state_change_on_reframe.html create mode 100644 editor/libeditor/tests/test_textarea_value_not_include_cr.html create mode 100644 editor/libeditor/tests/test_texteditor_keyevent_handling.html create mode 100644 editor/libeditor/tests/test_typing_at_edge_of_anchor.html create mode 100644 editor/libeditor/tests/test_undo_after_spellchecker_replaces_word.html create mode 100644 editor/libeditor/tests/test_undo_redo_stack_after_setting_value.html create mode 100644 editor/libeditor/tests/test_undo_with_editingui.html (limited to 'editor/libeditor') diff --git a/editor/libeditor/CSSEditUtils.cpp b/editor/libeditor/CSSEditUtils.cpp new file mode 100644 index 0000000000..20bd8f9980 --- /dev/null +++ b/editor/libeditor/CSSEditUtils.cpp @@ -0,0 +1,1293 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/CSSEditUtils.h" + +#include "mozilla/Assertions.h" +#include "mozilla/ChangeStyleTransaction.h" +#include "mozilla/HTMLEditor.h" +#include "mozilla/Preferences.h" +#include "mozilla/DeclarationBlock.h" +#include "mozilla/dom/Element.h" +#include "mozilla/mozalloc.h" +#include "nsAString.h" +#include "nsCOMPtr.h" +#include "nsCSSProps.h" +#include "nsColor.h" +#include "nsComputedDOMStyle.h" +#include "nsDebug.h" +#include "nsDependentSubstring.h" +#include "nsError.h" +#include "nsGkAtoms.h" +#include "nsAtom.h" +#include "nsIContent.h" +#include "nsICSSDeclaration.h" +#include "mozilla/dom/Document.h" +#include "nsINode.h" +#include "nsISupportsImpl.h" +#include "nsISupportsUtils.h" +#include "nsLiteralString.h" +#include "nsPIDOMWindow.h" +#include "nsReadableUtils.h" +#include "nsString.h" +#include "nsStringFwd.h" +#include "nsStringIterator.h" +#include "nsStyledElement.h" +#include "nsUnicharUtils.h" + +namespace mozilla { + +using namespace dom; + +static void ProcessBValue(const nsAString* aInputString, + nsAString& aOutputString, + const char* aDefaultValueString, + const char* aPrependString, + const char* aAppendString) { + if (aInputString && aInputString->EqualsLiteral("-moz-editor-invert-value")) { + aOutputString.AssignLiteral("normal"); + } else { + aOutputString.AssignLiteral("bold"); + } +} + +static void ProcessDefaultValue(const nsAString* aInputString, + nsAString& aOutputString, + const char* aDefaultValueString, + const char* aPrependString, + const char* aAppendString) { + CopyASCIItoUTF16(MakeStringSpan(aDefaultValueString), aOutputString); +} + +static void ProcessSameValue(const nsAString* aInputString, + nsAString& aOutputString, + const char* aDefaultValueString, + const char* aPrependString, + const char* aAppendString) { + if (aInputString) { + aOutputString.Assign(*aInputString); + } else + aOutputString.Truncate(); +} + +static void ProcessExtendedValue(const nsAString* aInputString, + nsAString& aOutputString, + const char* aDefaultValueString, + const char* aPrependString, + const char* aAppendString) { + aOutputString.Truncate(); + if (aInputString) { + if (aPrependString) { + AppendASCIItoUTF16(MakeStringSpan(aPrependString), aOutputString); + } + aOutputString.Append(*aInputString); + if (aAppendString) { + AppendASCIItoUTF16(MakeStringSpan(aAppendString), aOutputString); + } + } +} + +static void ProcessLengthValue(const nsAString* aInputString, + nsAString& aOutputString, + const char* aDefaultValueString, + const char* aPrependString, + const char* aAppendString) { + aOutputString.Truncate(); + if (aInputString) { + aOutputString.Append(*aInputString); + if (-1 == aOutputString.FindChar(char16_t('%'))) { + aOutputString.AppendLiteral("px"); + } + } +} + +static void ProcessListStyleTypeValue(const nsAString* aInputString, + nsAString& aOutputString, + const char* aDefaultValueString, + const char* aPrependString, + const char* aAppendString) { + aOutputString.Truncate(); + if (aInputString) { + if (aInputString->EqualsLiteral("1")) { + aOutputString.AppendLiteral("decimal"); + } else if (aInputString->EqualsLiteral("a")) { + aOutputString.AppendLiteral("lower-alpha"); + } else if (aInputString->EqualsLiteral("A")) { + aOutputString.AppendLiteral("upper-alpha"); + } else if (aInputString->EqualsLiteral("i")) { + aOutputString.AppendLiteral("lower-roman"); + } else if (aInputString->EqualsLiteral("I")) { + aOutputString.AppendLiteral("upper-roman"); + } else if (aInputString->EqualsLiteral("square") || + aInputString->EqualsLiteral("circle") || + aInputString->EqualsLiteral("disc")) { + aOutputString.Append(*aInputString); + } + } +} + +static void ProcessMarginLeftValue(const nsAString* aInputString, + nsAString& aOutputString, + const char* aDefaultValueString, + const char* aPrependString, + const char* aAppendString) { + aOutputString.Truncate(); + if (aInputString) { + if (aInputString->EqualsLiteral("center") || + aInputString->EqualsLiteral("-moz-center")) { + aOutputString.AppendLiteral("auto"); + } else if (aInputString->EqualsLiteral("right") || + aInputString->EqualsLiteral("-moz-right")) { + aOutputString.AppendLiteral("auto"); + } else { + aOutputString.AppendLiteral("0px"); + } + } +} + +static void ProcessMarginRightValue(const nsAString* aInputString, + nsAString& aOutputString, + const char* aDefaultValueString, + const char* aPrependString, + const char* aAppendString) { + aOutputString.Truncate(); + if (aInputString) { + if (aInputString->EqualsLiteral("center") || + aInputString->EqualsLiteral("-moz-center")) { + aOutputString.AppendLiteral("auto"); + } else if (aInputString->EqualsLiteral("left") || + aInputString->EqualsLiteral("-moz-left")) { + aOutputString.AppendLiteral("auto"); + } else { + aOutputString.AppendLiteral("0px"); + } + } +} + +#define CSS_EQUIV_TABLE_NONE \ + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } + +const CSSEditUtils::CSSEquivTable boldEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_font_weight, true, false, ProcessBValue, + nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable italicEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_font_style, true, false, + ProcessDefaultValue, "italic", nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable underlineEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_text_decoration, true, false, + ProcessDefaultValue, "underline", nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable strikeEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_text_decoration, true, false, + ProcessDefaultValue, "line-through", nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable ttEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_font_family, true, false, + ProcessDefaultValue, "monospace", nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable fontColorEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_color, true, false, ProcessSameValue, + nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable fontFaceEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_font_family, true, false, + ProcessSameValue, nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable bgcolorEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_background_color, true, false, + ProcessSameValue, nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable backgroundImageEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_background_image, true, true, + ProcessExtendedValue, nullptr, "url(", ")"}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable textColorEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_color, true, false, ProcessSameValue, + nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable borderEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_border, true, false, + ProcessExtendedValue, nullptr, nullptr, "px solid"}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable textAlignEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_text_align, true, false, + ProcessSameValue, nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable captionAlignEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_caption_side, true, false, + ProcessSameValue, nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable verticalAlignEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_vertical_align, true, false, + ProcessSameValue, nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable nowrapEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_whitespace, true, false, + ProcessDefaultValue, "nowrap", nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable widthEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_width, true, false, ProcessLengthValue, + nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable heightEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_height, true, false, ProcessLengthValue, + nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable listStyleTypeEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_list_style_type, true, true, + ProcessListStyleTypeValue, nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable tableAlignEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_text_align, false, false, + ProcessDefaultValue, "left", nullptr, nullptr}, + {CSSEditUtils::eCSSEditableProperty_margin_left, true, false, + ProcessMarginLeftValue, nullptr, nullptr, nullptr}, + {CSSEditUtils::eCSSEditableProperty_margin_right, true, false, + ProcessMarginRightValue, nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +const CSSEditUtils::CSSEquivTable hrAlignEquivTable[] = { + {CSSEditUtils::eCSSEditableProperty_margin_left, true, false, + ProcessMarginLeftValue, nullptr, nullptr, nullptr}, + {CSSEditUtils::eCSSEditableProperty_margin_right, true, false, + ProcessMarginRightValue, nullptr, nullptr, nullptr}, + CSS_EQUIV_TABLE_NONE}; + +#undef CSS_EQUIV_TABLE_NONE + +CSSEditUtils::CSSEditUtils(HTMLEditor* aHTMLEditor) + : mHTMLEditor(aHTMLEditor), mIsCSSPrefChecked(true) { + // let's retrieve the value of the "CSS editing" pref + mIsCSSPrefChecked = Preferences::GetBool("editor.use_css", mIsCSSPrefChecked); +} + +// Answers true if we have some CSS equivalence for the HTML style defined +// by aProperty and/or aAttribute for the node aNode + +// static +bool CSSEditUtils::IsCSSEditableProperty(nsINode* aNode, nsAtom* aProperty, + nsAtom* aAttribute) { + MOZ_ASSERT(aNode); + + Element* element = aNode->GetAsElementOrParentElement(); + if (NS_WARN_IF(!element)) { + return false; + } + + // html inline styles B I TT U STRIKE and COLOR/FACE on FONT + if (nsGkAtoms::b == aProperty || nsGkAtoms::i == aProperty || + nsGkAtoms::tt == aProperty || nsGkAtoms::u == aProperty || + nsGkAtoms::strike == aProperty || + (nsGkAtoms::font == aProperty && aAttribute && + (aAttribute == nsGkAtoms::color || aAttribute == nsGkAtoms::face))) { + return true; + } + + // ALIGN attribute on elements supporting it + if (aAttribute == nsGkAtoms::align && + element->IsAnyOfHTMLElements( + nsGkAtoms::div, nsGkAtoms::p, nsGkAtoms::h1, nsGkAtoms::h2, + nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6, + nsGkAtoms::td, nsGkAtoms::th, nsGkAtoms::table, nsGkAtoms::hr, + // For the above, why not use + // HTMLEditUtils::SupportsAlignAttr? + // It also checks for tbody, tfoot, thead. + // Let's add the following elements here even + // if "align" has a different meaning for them + nsGkAtoms::legend, nsGkAtoms::caption)) { + return true; + } + + if (aAttribute == nsGkAtoms::valign && + element->IsAnyOfHTMLElements( + nsGkAtoms::col, nsGkAtoms::colgroup, nsGkAtoms::tbody, nsGkAtoms::td, + nsGkAtoms::th, nsGkAtoms::tfoot, nsGkAtoms::thead, nsGkAtoms::tr)) { + return true; + } + + // attributes TEXT, BACKGROUND and BGCOLOR on BODY + if (element->IsHTMLElement(nsGkAtoms::body) && + (aAttribute == nsGkAtoms::text || aAttribute == nsGkAtoms::background || + aAttribute == nsGkAtoms::bgcolor)) { + return true; + } + + // attribute BGCOLOR on other elements + if (aAttribute == nsGkAtoms::bgcolor) { + return true; + } + + // attributes HEIGHT, WIDTH and NOWRAP on TD and TH + if (element->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th) && + (aAttribute == nsGkAtoms::height || aAttribute == nsGkAtoms::width || + aAttribute == nsGkAtoms::nowrap)) { + return true; + } + + // attributes HEIGHT and WIDTH on TABLE + if (element->IsHTMLElement(nsGkAtoms::table) && + (aAttribute == nsGkAtoms::height || aAttribute == nsGkAtoms::width)) { + return true; + } + + // attributes SIZE and WIDTH on HR + if (element->IsHTMLElement(nsGkAtoms::hr) && + (aAttribute == nsGkAtoms::size || aAttribute == nsGkAtoms::width)) { + return true; + } + + // attribute TYPE on OL UL LI + if (element->IsAnyOfHTMLElements(nsGkAtoms::ol, nsGkAtoms::ul, + nsGkAtoms::li) && + aAttribute == nsGkAtoms::type) { + return true; + } + + if (element->IsHTMLElement(nsGkAtoms::img) && + (aAttribute == nsGkAtoms::border || aAttribute == nsGkAtoms::width || + aAttribute == nsGkAtoms::height)) { + return true; + } + + // other elements that we can align using CSS even if they + // can't carry the html ALIGN attribute + if (aAttribute == nsGkAtoms::align && + element->IsAnyOfHTMLElements(nsGkAtoms::ul, nsGkAtoms::ol, nsGkAtoms::dl, + nsGkAtoms::li, nsGkAtoms::dd, nsGkAtoms::dt, + nsGkAtoms::address, nsGkAtoms::pre)) { + return true; + } + + return false; +} + +// The lowest level above the transaction; adds the CSS declaration +// "aProperty : aValue" to the inline styles carried by aStyledElement +nsresult CSSEditUtils::SetCSSPropertyInternal(nsStyledElement& aStyledElement, + nsAtom& aProperty, + const nsAString& aValue, + bool aSuppressTxn) { + RefPtr transaction = + ChangeStyleTransaction::Create(aStyledElement, aProperty, aValue); + if (aSuppressTxn) { + nsresult rv = transaction->DoTransaction(); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "ChangeStyleTransaction::DoTransaction() failed"); + return rv; + } + if (NS_WARN_IF(!mHTMLEditor)) { + return NS_ERROR_NOT_AVAILABLE; + } + RefPtr htmlEditor(mHTMLEditor); + nsresult rv = htmlEditor->DoTransactionInternal(transaction); + if (NS_WARN_IF(htmlEditor->Destroyed())) { + return NS_ERROR_EDITOR_DESTROYED; + } + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "EditorBase::DoTransactionInternal() failed"); + return rv; +} + +nsresult CSSEditUtils::SetCSSPropertyPixelsWithTransaction( + nsStyledElement& aStyledElement, nsAtom& aProperty, int32_t aIntValue) { + nsAutoString s; + s.AppendInt(aIntValue); + nsresult rv = + SetCSSPropertyWithTransaction(aStyledElement, aProperty, s + u"px"_ns); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "CSSEditUtils::SetCSSPropertyWithTransaction() failed"); + return rv; +} + +nsresult CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction( + nsStyledElement& aStyledElement, const nsAtom& aProperty, + int32_t aIntValue) { + nsCOMPtr cssDecl = aStyledElement.Style(); + + nsAutoCString propertyNameString; + aProperty.ToUTF8String(propertyNameString); + + nsAutoCString s; + s.AppendInt(aIntValue); + s.AppendLiteral("px"); + + ErrorResult error; + cssDecl->SetProperty(propertyNameString, s, EmptyCString(), error); + if (error.Failed()) { + NS_WARNING("nsICSSDeclaration::SetProperty() failed"); + return error.StealNSResult(); + } + + return NS_OK; +} + +// The lowest level above the transaction; removes the value aValue from the +// list of values specified for the CSS property aProperty, or totally remove +// the declaration if this property accepts only one value +nsresult CSSEditUtils::RemoveCSSPropertyInternal( + nsStyledElement& aStyledElement, nsAtom& aProperty, const nsAString& aValue, + bool aSuppressTxn) { + RefPtr transaction = + ChangeStyleTransaction::CreateToRemove(aStyledElement, aProperty, aValue); + if (aSuppressTxn) { + nsresult rv = transaction->DoTransaction(); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "ChangeStyleTransaction::DoTransaction() failed"); + return rv; + } + if (NS_WARN_IF(!mHTMLEditor)) { + return NS_ERROR_NOT_AVAILABLE; + } + RefPtr htmlEditor(mHTMLEditor); + nsresult rv = htmlEditor->DoTransactionInternal(transaction); + if (NS_WARN_IF(htmlEditor->Destroyed())) { + return NS_ERROR_EDITOR_DESTROYED; + } + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "EditorBase::DoTransactionInternal() failed"); + return rv; +} + +// static +nsresult CSSEditUtils::GetSpecifiedProperty(nsIContent& aContent, + nsAtom& aCSSProperty, + nsAString& aValue) { + nsresult rv = + GetSpecifiedCSSInlinePropertyBase(aContent, aCSSProperty, aValue); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rv), + "CSSEditUtils::GeSpecifiedCSSInlinePropertyBase() failed"); + return rv; +} + +// static +nsresult CSSEditUtils::GetComputedProperty(nsIContent& aContent, + nsAtom& aCSSProperty, + nsAString& aValue) { + nsresult rv = + GetComputedCSSInlinePropertyBase(aContent, aCSSProperty, aValue); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rv), + "CSSEditUtils::GetComputedCSSInlinePropertyBase() failed"); + return rv; +} + +// static +nsresult CSSEditUtils::GetComputedCSSInlinePropertyBase(nsIContent& aContent, + nsAtom& aCSSProperty, + nsAString& aValue) { + aValue.Truncate(); + + RefPtr element = aContent.GetAsElementOrParentElement(); + if (NS_WARN_IF(!element)) { + return NS_ERROR_INVALID_ARG; + } + + // Get the all the computed css styles attached to the element node + RefPtr computedDOMStyle = GetComputedStyle(element); + if (NS_WARN_IF(!computedDOMStyle)) { + return NS_ERROR_INVALID_ARG; + } + + // from these declarations, get the one we want and that one only + // + // FIXME(bug 1606994): nsAtomCString copies, we should just keep around the + // property id. + // + // FIXME: Maybe we can avoid copying aValue too, though it's no worse than + // what we used to do. + nsAutoCString value; + MOZ_ALWAYS_SUCCEEDS( + computedDOMStyle->GetPropertyValue(nsAtomCString(&aCSSProperty), value)); + CopyUTF8toUTF16(value, aValue); + return NS_OK; +} + +// static +nsresult CSSEditUtils::GetSpecifiedCSSInlinePropertyBase(nsIContent& aContent, + nsAtom& aCSSProperty, + nsAString& aValue) { + aValue.Truncate(); + + RefPtr element = aContent.GetAsElementOrParentElement(); + if (NS_WARN_IF(!element)) { + return NS_ERROR_INVALID_ARG; + } + + RefPtr decl = element->GetInlineStyleDeclaration(); + if (!decl) { + return NS_OK; + } + + // FIXME: Same comments as above. + nsCSSPropertyID prop = + nsCSSProps::LookupProperty(nsAtomCString(&aCSSProperty)); + MOZ_ASSERT(prop != eCSSProperty_UNKNOWN); + + nsAutoCString value; + decl->GetPropertyValueByID(prop, value); + CopyUTF8toUTF16(value, aValue); + return NS_OK; +} + +// static +already_AddRefed CSSEditUtils::GetComputedStyle( + Element* aElement) { + MOZ_ASSERT(aElement); + + Document* document = aElement->GetComposedDoc(); + if (NS_WARN_IF(!document)) { + return nullptr; + } + + RefPtr computedDOMStyle = + NS_NewComputedDOMStyle(aElement, u""_ns, document); + return computedDOMStyle.forget(); +} + +// remove the CSS style "aProperty : aPropertyValue" and possibly remove the +// whole node if it is a span and if its only attribute is _moz_dirty +nsresult CSSEditUtils::RemoveCSSInlineStyleWithTransaction( + nsStyledElement& aStyledElement, nsAtom* aProperty, + const nsAString& aPropertyValue) { + // remove the property from the style attribute + nsresult rv = RemoveCSSPropertyWithTransaction(aStyledElement, *aProperty, + aPropertyValue); + if (NS_FAILED(rv)) { + NS_WARNING("CSSEditUtils::RemoveCSSPropertyWithTransaction() failed"); + return rv; + } + + if (!aStyledElement.IsHTMLElement(nsGkAtoms::span) || + HTMLEditor::HasAttributes(&aStyledElement)) { + return NS_OK; + } + + OwningNonNull htmlEditor(*mHTMLEditor); + rv = htmlEditor->RemoveContainerWithTransaction(aStyledElement); + if (NS_WARN_IF(htmlEditor->Destroyed())) { + return NS_ERROR_EDITOR_DESTROYED; + } + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "HTMLEditor::RemoveContainerWithTransaction() failed"); + return rv; +} + +// Answers true if the property can be removed by setting a "none" CSS value +// on a node + +// static +bool CSSEditUtils::IsCSSInvertible(nsAtom& aProperty, nsAtom* aAttribute) { + return nsGkAtoms::b == &aProperty; +} + +// Get the default browser background color if we need it for +// GetCSSBackgroundColorState + +// static +void CSSEditUtils::GetDefaultBackgroundColor(nsAString& aColor) { + if (Preferences::GetBool("editor.use_custom_colors", false)) { + nsresult rv = Preferences::GetString("editor.background_color", aColor); + // XXX Why don't you validate the pref value? + if (NS_FAILED(rv)) { + NS_WARNING("failed to get editor.background_color"); + aColor.AssignLiteral("#ffffff"); // Default to white + } + return; + } + + if (Preferences::GetBool("browser.display.use_system_colors", false)) { + return; + } + + nsresult rv = + Preferences::GetString("browser.display.background_color", aColor); + // XXX Why don't you validate the pref value? + if (NS_FAILED(rv)) { + NS_WARNING("failed to get browser.display.background_color"); + aColor.AssignLiteral("#ffffff"); // Default to white + } +} + +// Get the default length unit used for CSS Indent/Outdent + +// static +void CSSEditUtils::GetDefaultLengthUnit(nsAString& aLengthUnit) { + nsresult rv = + Preferences::GetString("editor.css.default_length_unit", aLengthUnit); + // XXX Why don't you validate the pref value? + if (NS_FAILED(rv)) { + aLengthUnit.AssignLiteral("px"); + } +} + +// static +void CSSEditUtils::ParseLength(const nsAString& aString, float* aValue, + nsAtom** aUnit) { + if (aString.IsEmpty()) { + *aValue = 0; + *aUnit = NS_Atomize(aString).take(); + return; + } + + nsAString::const_iterator iter; + aString.BeginReading(iter); + + float a = 10.0f, b = 1.0f, value = 0; + int8_t sign = 1; + int32_t i = 0, j = aString.Length(); + char16_t c; + bool floatingPointFound = false; + c = *iter; + if (char16_t('-') == c) { + sign = -1; + iter++; + i++; + } else if (char16_t('+') == c) { + iter++; + i++; + } + while (i < j) { + c = *iter; + if ((char16_t('0') == c) || (char16_t('1') == c) || (char16_t('2') == c) || + (char16_t('3') == c) || (char16_t('4') == c) || (char16_t('5') == c) || + (char16_t('6') == c) || (char16_t('7') == c) || (char16_t('8') == c) || + (char16_t('9') == c)) { + value = (value * a) + (b * (c - char16_t('0'))); + b = b / 10 * a; + } else if (!floatingPointFound && (char16_t('.') == c)) { + floatingPointFound = true; + a = 1.0f; + b = 0.1f; + } else + break; + iter++; + i++; + } + *aValue = value * sign; + *aUnit = NS_Atomize(StringTail(aString, j - i)).take(); +} + +// static +nsStaticAtom* CSSEditUtils::GetCSSPropertyAtom( + nsCSSEditableProperty aProperty) { + switch (aProperty) { + case eCSSEditableProperty_background_color: + return nsGkAtoms::backgroundColor; + case eCSSEditableProperty_background_image: + return nsGkAtoms::background_image; + case eCSSEditableProperty_border: + return nsGkAtoms::border; + case eCSSEditableProperty_caption_side: + return nsGkAtoms::caption_side; + case eCSSEditableProperty_color: + return nsGkAtoms::color; + case eCSSEditableProperty_float: + return nsGkAtoms::_float; + case eCSSEditableProperty_font_family: + return nsGkAtoms::font_family; + case eCSSEditableProperty_font_size: + return nsGkAtoms::font_size; + case eCSSEditableProperty_font_style: + return nsGkAtoms::font_style; + case eCSSEditableProperty_font_weight: + return nsGkAtoms::fontWeight; + case eCSSEditableProperty_height: + return nsGkAtoms::height; + case eCSSEditableProperty_list_style_type: + return nsGkAtoms::list_style_type; + case eCSSEditableProperty_margin_left: + return nsGkAtoms::marginLeft; + case eCSSEditableProperty_margin_right: + return nsGkAtoms::marginRight; + case eCSSEditableProperty_text_align: + return nsGkAtoms::textAlign; + case eCSSEditableProperty_text_decoration: + return nsGkAtoms::text_decoration; + case eCSSEditableProperty_vertical_align: + return nsGkAtoms::vertical_align; + case eCSSEditableProperty_whitespace: + return nsGkAtoms::white_space; + case eCSSEditableProperty_width: + return nsGkAtoms::width; + case eCSSEditableProperty_NONE: + // intentionally empty + return nullptr; + } + MOZ_ASSERT_UNREACHABLE("Got unknown property"); + return nullptr; +} + +// Populate aOutArrayOfCSSProperty and aOutArrayOfCSSValue with the CSS +// declarations equivalent to the value aValue according to the equivalence +// table aEquivTable + +// static +void CSSEditUtils::BuildCSSDeclarations( + nsTArray& aOutArrayOfCSSProperty, + nsTArray& aOutArrayOfCSSValue, const CSSEquivTable* aEquivTable, + const nsAString* aValue, bool aGetOrRemoveRequest) { + // clear arrays + aOutArrayOfCSSProperty.Clear(); + aOutArrayOfCSSValue.Clear(); + + // if we have an input value, let's use it + nsAutoString value, lowerCasedValue; + if (aValue) { + value.Assign(*aValue); + lowerCasedValue.Assign(*aValue); + ToLowerCase(lowerCasedValue); + } + + int8_t index = 0; + nsCSSEditableProperty cssProperty = aEquivTable[index].cssProperty; + while (cssProperty) { + if (!aGetOrRemoveRequest || aEquivTable[index].gettable) { + nsAutoString cssValue, cssPropertyString; + // find the equivalent css value for the index-th property in + // the equivalence table + (*aEquivTable[index].processValueFunctor)( + (!aGetOrRemoveRequest || aEquivTable[index].caseSensitiveValue) + ? &value + : &lowerCasedValue, + cssValue, aEquivTable[index].defaultValue, + aEquivTable[index].prependValue, aEquivTable[index].appendValue); + aOutArrayOfCSSProperty.AppendElement(GetCSSPropertyAtom(cssProperty)); + aOutArrayOfCSSValue.AppendElement(cssValue); + } + index++; + cssProperty = aEquivTable[index].cssProperty; + } +} + +// Populate aOutArrayOfCSSProperty and aOutArrayOfCSSValue with the declarations +// equivalent to aHTMLProperty/aAttribute/aValue for the node aNode + +// static +void CSSEditUtils::GenerateCSSDeclarationsFromHTMLStyle( + Element& aElement, nsAtom* aHTMLProperty, nsAtom* aAttribute, + const nsAString* aValue, nsTArray& aOutArrayOfCSSProperty, + nsTArray& aOutArrayOfCSSValue, bool aGetOrRemoveRequest) { + const CSSEditUtils::CSSEquivTable* equivTable = nullptr; + + if (nsGkAtoms::b == aHTMLProperty) { + equivTable = boldEquivTable; + } else if (nsGkAtoms::i == aHTMLProperty) { + equivTable = italicEquivTable; + } else if (nsGkAtoms::u == aHTMLProperty) { + equivTable = underlineEquivTable; + } else if (nsGkAtoms::strike == aHTMLProperty) { + equivTable = strikeEquivTable; + } else if (nsGkAtoms::tt == aHTMLProperty) { + equivTable = ttEquivTable; + } else if (aAttribute) { + if (nsGkAtoms::font == aHTMLProperty && aAttribute == nsGkAtoms::color) { + equivTable = fontColorEquivTable; + } else if (nsGkAtoms::font == aHTMLProperty && + aAttribute == nsGkAtoms::face) { + equivTable = fontFaceEquivTable; + } else if (aAttribute == nsGkAtoms::bgcolor) { + equivTable = bgcolorEquivTable; + } else if (aAttribute == nsGkAtoms::background) { + equivTable = backgroundImageEquivTable; + } else if (aAttribute == nsGkAtoms::text) { + equivTable = textColorEquivTable; + } else if (aAttribute == nsGkAtoms::border) { + equivTable = borderEquivTable; + } else if (aAttribute == nsGkAtoms::align) { + if (aElement.IsHTMLElement(nsGkAtoms::table)) { + equivTable = tableAlignEquivTable; + } else if (aElement.IsHTMLElement(nsGkAtoms::hr)) { + equivTable = hrAlignEquivTable; + } else if (aElement.IsAnyOfHTMLElements(nsGkAtoms::legend, + nsGkAtoms::caption)) { + equivTable = captionAlignEquivTable; + } else { + equivTable = textAlignEquivTable; + } + } else if (aAttribute == nsGkAtoms::valign) { + equivTable = verticalAlignEquivTable; + } else if (aAttribute == nsGkAtoms::nowrap) { + equivTable = nowrapEquivTable; + } else if (aAttribute == nsGkAtoms::width) { + equivTable = widthEquivTable; + } else if (aAttribute == nsGkAtoms::height || + (aElement.IsHTMLElement(nsGkAtoms::hr) && + aAttribute == nsGkAtoms::size)) { + equivTable = heightEquivTable; + } else if (aAttribute == nsGkAtoms::type && + aElement.IsAnyOfHTMLElements(nsGkAtoms::ol, nsGkAtoms::ul, + nsGkAtoms::li)) { + equivTable = listStyleTypeEquivTable; + } + } + if (equivTable) { + BuildCSSDeclarations(aOutArrayOfCSSProperty, aOutArrayOfCSSValue, + equivTable, aValue, aGetOrRemoveRequest); + } +} + +// Add to aNode the CSS inline style equivalent to HTMLProperty/aAttribute/ +// aValue for the node, and return in aCount the number of CSS properties set +// by the call. The Element version returns aCount instead. +Result CSSEditUtils::SetCSSEquivalentToHTMLStyleInternal( + nsStyledElement& aStyledElement, nsAtom* aHTMLProperty, nsAtom* aAttribute, + const nsAString* aValue, bool aSuppressTransaction) { + if (!IsCSSEditableProperty(&aStyledElement, aHTMLProperty, aAttribute)) { + return 0; + } + + // we can apply the styles only if the node is an element and if we have + // an equivalence for the requested HTML style in this implementation + + // Find the CSS equivalence to the HTML style + nsTArray cssPropertyArray; + nsTArray cssValueArray; + GenerateCSSDeclarationsFromHTMLStyle(aStyledElement, aHTMLProperty, + aAttribute, aValue, cssPropertyArray, + cssValueArray, false); + + // set the individual CSS inline styles + const size_t count = cssPropertyArray.Length(); + for (size_t index = 0; index < count; index++) { + nsresult rv = SetCSSPropertyInternal( + aStyledElement, MOZ_KnownLive(*cssPropertyArray[index]), + cssValueArray[index], aSuppressTransaction); + if (NS_FAILED(rv)) { + NS_WARNING("CSSEditUtils::SetCSSPropertyInternal() failed"); + return Err(rv); + } + } + return count; +} + +// Remove from aNode the CSS inline style equivalent to +// HTMLProperty/aAttribute/aValue for the node +nsresult CSSEditUtils::RemoveCSSEquivalentToHTMLStyleInternal( + nsStyledElement& aStyledElement, nsAtom* aHTMLProperty, nsAtom* aAttribute, + const nsAString* aValue, bool aSuppressTransaction) { + if (!IsCSSEditableProperty(&aStyledElement, aHTMLProperty, aAttribute)) { + return NS_OK; + } + + // we can apply the styles only if the node is an element and if we have + // an equivalence for the requested HTML style in this implementation + + // Find the CSS equivalence to the HTML style + nsTArray cssPropertyArray; + nsTArray cssValueArray; + GenerateCSSDeclarationsFromHTMLStyle(aStyledElement, aHTMLProperty, + aAttribute, aValue, cssPropertyArray, + cssValueArray, true); + + // remove the individual CSS inline styles + const size_t count = cssPropertyArray.Length(); + if (!count) { + return NS_OK; + } + for (size_t index = 0; index < count; index++) { + nsresult rv = RemoveCSSPropertyInternal( + aStyledElement, MOZ_KnownLive(*cssPropertyArray[index]), + cssValueArray[index], aSuppressTransaction); + if (NS_FAILED(rv)) { + NS_WARNING("CSSEditUtils::RemoveCSSPropertyWithoutTransaction() failed"); + return rv; + } + } + return NS_OK; +} + +// returns in aValue the list of values for the CSS equivalences to +// the HTML style aHTMLProperty/aAttribute/aValue for the node aNode; +// the value of aStyleType controls the styles we retrieve : specified or +// computed. + +// static +nsresult CSSEditUtils::GetCSSEquivalentToHTMLInlineStyleSetInternal( + nsIContent& aContent, nsAtom* aHTMLProperty, nsAtom* aAttribute, + nsAString& aValue, StyleType aStyleType) { + MOZ_ASSERT(aHTMLProperty || aAttribute); + + aValue.Truncate(); + RefPtr theElement = aContent.GetAsElementOrParentElement(); + if (NS_WARN_IF(!theElement)) { + return NS_ERROR_INVALID_ARG; + } + + if (!theElement || + !IsCSSEditableProperty(theElement, aHTMLProperty, aAttribute)) { + return NS_OK; + } + + // Yes, the requested HTML style has a CSS equivalence in this implementation + nsTArray cssPropertyArray; + nsTArray cssValueArray; + // get the CSS equivalence with last param true indicating we want only the + // "gettable" properties + GenerateCSSDeclarationsFromHTMLStyle(*theElement, aHTMLProperty, aAttribute, + nullptr, cssPropertyArray, cssValueArray, + true); + int32_t count = cssPropertyArray.Length(); + for (int32_t index = 0; index < count; index++) { + nsAutoString valueString; + // retrieve the specified/computed value of the property + if (aStyleType == StyleType::Computed) { + nsresult rv = GetComputedCSSInlinePropertyBase( + *theElement, MOZ_KnownLive(*cssPropertyArray[index]), valueString); + if (NS_FAILED(rv)) { + NS_WARNING("CSSEditUtils::GetComputedCSSInlinePropertyBase() failed"); + return rv; + } + } else { + nsresult rv = GetSpecifiedCSSInlinePropertyBase( + *theElement, *cssPropertyArray[index], valueString); + if (NS_FAILED(rv)) { + NS_WARNING("CSSEditUtils::GetSpecifiedCSSInlinePropertyBase() failed"); + return rv; + } + } + // append the value to aValue (possibly with a leading white-space) + if (index) { + aValue.Append(char16_t(' ')); + } + aValue.Append(valueString); + } + return NS_OK; +} + +// Does the node aContent (or its parent, if it's not an element node) have a +// CSS style equivalent to the HTML style +// aHTMLProperty/aAttribute/valueString? The value of aStyleType controls +// the styles we retrieve: specified or computed. The return value aIsSet is +// true if the CSS styles are set. +// +// The nsIContent variant returns aIsSet instead of using an out parameter, and +// does not modify aValue. + +// static +bool CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSetInternal( + nsIContent& aContent, nsAtom* aHTMLProperty, nsAtom* aAttribute, + nsAString& aValue, StyleType aStyleType) { + MOZ_ASSERT(aHTMLProperty || aAttribute); + + nsAutoString htmlValueString(aValue); + bool isSet = false; + // FYI: Cannot use InclusiveAncestorsOfType here because + // GetCSSEquivalentToHTMLInlineStyleSetInternal() may flush pending + // notifications. + for (nsCOMPtr content = &aContent; content; + content = content->GetParentElement()) { + nsCOMPtr parentNode = content->GetParentNode(); + aValue.Assign(htmlValueString); + // get the value of the CSS equivalent styles + nsresult rv = GetCSSEquivalentToHTMLInlineStyleSetInternal( + *content, aHTMLProperty, aAttribute, aValue, aStyleType); + if (NS_FAILED(rv)) { + NS_WARNING( + "CSSEditUtils::GetCSSEquivalentToHTMLInlineStyleSetInternal() " + "failed"); + return false; + } + if (NS_WARN_IF(parentNode != content->GetParentNode())) { + return false; + } + + // early way out if we can + if (aValue.IsEmpty()) { + return isSet; + } + + if (nsGkAtoms::b == aHTMLProperty) { + if (aValue.EqualsLiteral("bold")) { + isSet = true; + } else if (aValue.EqualsLiteral("normal")) { + isSet = false; + } else if (aValue.EqualsLiteral("bolder")) { + isSet = true; + aValue.AssignLiteral("bold"); + } else { + int32_t weight = 0; + nsresult rvIgnored; + nsAutoString value(aValue); + weight = value.ToInteger(&rvIgnored); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored), + "nsAString::ToInteger() failed, but ignored"); + if (400 < weight) { + isSet = true; + aValue.AssignLiteral("bold"); + } else { + isSet = false; + aValue.AssignLiteral("normal"); + } + } + } else if (nsGkAtoms::i == aHTMLProperty) { + if (aValue.EqualsLiteral("italic") || aValue.EqualsLiteral("oblique")) { + isSet = true; + } + } else if (nsGkAtoms::u == aHTMLProperty) { + isSet = ChangeStyleTransaction::ValueIncludes( + NS_ConvertUTF16toUTF8(aValue), "underline"_ns); + } else if (nsGkAtoms::strike == aHTMLProperty) { + isSet = ChangeStyleTransaction::ValueIncludes( + NS_ConvertUTF16toUTF8(aValue), "line-through"_ns); + } else if ((nsGkAtoms::font == aHTMLProperty && + aAttribute == nsGkAtoms::color) || + aAttribute == nsGkAtoms::bgcolor) { + if (htmlValueString.IsEmpty()) { + isSet = true; + } else { + nscolor rgba; + nsAutoString subStr; + htmlValueString.Right(subStr, htmlValueString.Length() - 1); + if (NS_ColorNameToRGB(htmlValueString, &rgba) || + NS_HexToRGBA(subStr, nsHexColorType::NoAlpha, &rgba)) { + nsAutoString htmlColor, tmpStr; + + if (NS_GET_A(rgba) != 255) { + // This should only be hit by the "transparent" keyword, which + // currently serializes to "transparent" (not "rgba(0, 0, 0, 0)"). + MOZ_ASSERT(NS_GET_R(rgba) == 0 && NS_GET_G(rgba) == 0 && + NS_GET_B(rgba) == 0 && NS_GET_A(rgba) == 0); + htmlColor.AppendLiteral("transparent"); + } else { + htmlColor.AppendLiteral("rgb("); + + constexpr auto comma = u", "_ns; + + tmpStr.AppendInt(NS_GET_R(rgba), 10); + htmlColor.Append(tmpStr + comma); + + tmpStr.Truncate(); + tmpStr.AppendInt(NS_GET_G(rgba), 10); + htmlColor.Append(tmpStr + comma); + + tmpStr.Truncate(); + tmpStr.AppendInt(NS_GET_B(rgba), 10); + htmlColor.Append(tmpStr); + + htmlColor.Append(char16_t(')')); + } + + isSet = htmlColor.Equals(aValue, nsCaseInsensitiveStringComparator); + } else { + isSet = + htmlValueString.Equals(aValue, nsCaseInsensitiveStringComparator); + } + } + } else if (nsGkAtoms::tt == aHTMLProperty) { + isSet = StringBeginsWith(aValue, u"monospace"_ns); + } else if (nsGkAtoms::font == aHTMLProperty && aAttribute && + aAttribute == nsGkAtoms::face) { + if (!htmlValueString.IsEmpty()) { + const char16_t commaSpace[] = {char16_t(','), char16_t(' '), 0}; + const char16_t comma[] = {char16_t(','), 0}; + htmlValueString.ReplaceSubstring(commaSpace, comma); + nsAutoString valueStringNorm(aValue); + valueStringNorm.ReplaceSubstring(commaSpace, comma); + isSet = htmlValueString.Equals(valueStringNorm, + nsCaseInsensitiveStringComparator); + } else { + isSet = true; + } + return isSet; + } else if (aAttribute == nsGkAtoms::align) { + isSet = true; + } else { + return false; + } + + if (!htmlValueString.IsEmpty() && + htmlValueString.Equals(aValue, nsCaseInsensitiveStringComparator)) { + isSet = true; + } + + if (htmlValueString.EqualsLiteral("-moz-editor-invert-value")) { + isSet = !isSet; + } + + if (isSet) { + return true; + } + + if (nsGkAtoms::u != aHTMLProperty && nsGkAtoms::strike != aHTMLProperty) { + return isSet; + } + + // Unfortunately, the value of the text-decoration property is not + // inherited. that means that we have to look at ancestors of node to see + // if they are underlined. + } + return isSet; +} + +bool CSSEditUtils::HaveCSSEquivalentStylesInternal(nsIContent& aContent, + nsAtom* aHTMLProperty, + nsAtom* aAttribute, + StyleType aStyleType) { + MOZ_ASSERT(aHTMLProperty || aAttribute); + + // FYI: Unfortunately, we cannot use InclusiveAncestorsOfType here + // because GetCSSEquivalentToHTMLInlineStyleSetInternal() may flush + // pending notifications. + nsAutoString valueString; + for (nsCOMPtr content = &aContent; content; + content = content->GetParentElement()) { + nsCOMPtr parentNode = content->GetParentNode(); + // get the value of the CSS equivalent styles + nsresult rv = GetCSSEquivalentToHTMLInlineStyleSetInternal( + *content, aHTMLProperty, aAttribute, valueString, aStyleType); + if (NS_FAILED(rv)) { + NS_WARNING( + "CSSEditUtils::GetCSSEquivalentToHTMLInlineStyleSetInternal() " + "failed"); + return false; + } + if (NS_WARN_IF(parentNode != content->GetParentNode())) { + return false; + } + + if (!valueString.IsEmpty()) { + return true; + } + + if (nsGkAtoms::u != aHTMLProperty && nsGkAtoms::strike != aHTMLProperty) { + return false; + } + + // 'nfortunately, the value of the text-decoration property is not + // inherited. + // that means that we have to look at ancestors of node to see if they + // are underlined. + } + + return false; +} + +void CSSEditUtils::SetCSSEnabled(bool aIsCSSPrefChecked) { + mIsCSSPrefChecked = aIsCSSPrefChecked; +} + +bool CSSEditUtils::IsCSSPrefChecked() const { return mIsCSSPrefChecked; } + +// ElementsSameStyle compares two elements and checks if they have the same +// specified CSS declarations in the STYLE attribute +// The answer is always negative if at least one of them carries an ID or a +// class + +// static +bool CSSEditUtils::DoStyledElementsHaveSameStyle( + nsStyledElement& aStyledElement, nsStyledElement& aOtherStyledElement) { + if (aStyledElement.HasAttr(kNameSpaceID_None, nsGkAtoms::id) || + aOtherStyledElement.HasAttr(kNameSpaceID_None, nsGkAtoms::id)) { + // at least one of the spans carries an ID ; suspect a CSS rule applies to + // it and refuse to merge the nodes + return false; + } + + nsAutoString firstClass, otherClass; + bool isElementClassSet = + aStyledElement.GetAttr(kNameSpaceID_None, nsGkAtoms::_class, firstClass); + bool isOtherElementClassSet = aOtherStyledElement.GetAttr( + kNameSpaceID_None, nsGkAtoms::_class, otherClass); + if (isElementClassSet && isOtherElementClassSet) { + // both spans carry a class, let's compare them + if (!firstClass.Equals(otherClass)) { + // WARNING : technically, the comparison just above is questionable : + // from a pure HTML/CSS point of view class="a b" is NOT the same than + // class="b a" because a CSS rule could test the exact value of the class + // attribute to be "a b" for instance ; from a user's point of view, a + // wysiwyg editor should probably NOT make any difference. CSS people + // need to discuss this issue before any modification. + return false; + } + } else if (isElementClassSet || isOtherElementClassSet) { + // one span only carries a class, early way out + return false; + } + + // XXX If `GetPropertyValue()` won't run script, we can stop using + // nsCOMPtr here. + nsCOMPtr firstCSSDecl = aStyledElement.Style(); + if (!firstCSSDecl) { + NS_WARNING("nsStyledElement::Style() failed"); + return false; + } + nsCOMPtr otherCSSDecl = aOtherStyledElement.Style(); + if (!otherCSSDecl) { + NS_WARNING("nsStyledElement::Style() failed"); + return false; + } + + const uint32_t firstLength = firstCSSDecl->Length(); + const uint32_t otherLength = otherCSSDecl->Length(); + if (firstLength != otherLength) { + // early way out if we can + return false; + } + + if (!firstLength) { + // no inline style ! + return true; + } + + for (uint32_t i = 0; i < firstLength; i++) { + nsAutoCString firstValue, otherValue; + nsAutoCString propertyNameString; + firstCSSDecl->Item(i, propertyNameString); + DebugOnly rvIgnored = + firstCSSDecl->GetPropertyValue(propertyNameString, firstValue); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rvIgnored), + "nsICSSDeclaration::GetPropertyValue() failed, but ignored"); + rvIgnored = otherCSSDecl->GetPropertyValue(propertyNameString, otherValue); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rvIgnored), + "nsICSSDeclaration::GetPropertyValue() failed, but ignored"); + if (!firstValue.Equals(otherValue)) { + return false; + } + } + for (uint32_t i = 0; i < otherLength; i++) { + nsAutoCString firstValue, otherValue; + nsAutoCString propertyNameString; + otherCSSDecl->Item(i, propertyNameString); + DebugOnly rvIgnored = + otherCSSDecl->GetPropertyValue(propertyNameString, otherValue); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rvIgnored), + "nsICSSDeclaration::GetPropertyValue() failed, but ignored"); + rvIgnored = firstCSSDecl->GetPropertyValue(propertyNameString, firstValue); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rvIgnored), + "nsICSSDeclaration::GetPropertyValue() failed, but ignored"); + if (!firstValue.Equals(otherValue)) { + return false; + } + } + + return true; +} + +} // namespace mozilla diff --git a/editor/libeditor/CSSEditUtils.h b/editor/libeditor/CSSEditUtils.h new file mode 100644 index 0000000000..a5f604b8f4 --- /dev/null +++ b/editor/libeditor/CSSEditUtils.h @@ -0,0 +1,469 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_CSSEditUtils_h +#define mozilla_CSSEditUtils_h + +#include "mozilla/ChangeStyleTransaction.h" // for ChangeStyleTransaction +#include "nsCOMPtr.h" // for already_AddRefed +#include "nsStringFwd.h" +#include "nsTArray.h" // for nsTArray +#include "nscore.h" // for nsAString, nsresult, nullptr + +class nsComputedDOMStyle; +class nsAtom; +class nsIContent; +class nsICSSDeclaration; +class nsINode; +class nsStaticAtom; +class nsStyledElement; + +namespace mozilla { + +class HTMLEditor; +namespace dom { +class Element; +} // namespace dom + +typedef void (*nsProcessValueFunc)(const nsAString* aInputString, + nsAString& aOutputString, + const char* aDefaultValueString, + const char* aPrependString, + const char* aAppendString); + +class CSSEditUtils final { + public: + explicit CSSEditUtils(HTMLEditor* aEditor); + + enum nsCSSEditableProperty { + eCSSEditableProperty_NONE = 0, + eCSSEditableProperty_background_color, + eCSSEditableProperty_background_image, + eCSSEditableProperty_border, + eCSSEditableProperty_caption_side, + eCSSEditableProperty_color, + eCSSEditableProperty_float, + eCSSEditableProperty_font_family, + eCSSEditableProperty_font_size, + eCSSEditableProperty_font_style, + eCSSEditableProperty_font_weight, + eCSSEditableProperty_height, + eCSSEditableProperty_list_style_type, + eCSSEditableProperty_margin_left, + eCSSEditableProperty_margin_right, + eCSSEditableProperty_text_align, + eCSSEditableProperty_text_decoration, + eCSSEditableProperty_vertical_align, + eCSSEditableProperty_whitespace, + eCSSEditableProperty_width + }; + + // Nb: keep these fields in an order that minimizes padding. + struct CSSEquivTable { + nsCSSEditableProperty cssProperty; + bool gettable; + bool caseSensitiveValue; + nsProcessValueFunc processValueFunctor; + const char* defaultValue; + const char* prependValue; + const char* appendValue; + }; + + /** + * Answers true if the given combination element_name/attribute_name + * has a CSS equivalence in this implementation. + * + * @param aNode [IN] A DOM node. + * @param aProperty [IN] An atom containing a HTML tag name. + * @param aAttribute [IN] An atom containing a HTML + * attribute carried by the element above. + * @return A boolean saying if the tag/attribute has a CSS + * equiv. + */ + static bool IsCSSEditableProperty(nsINode* aNode, nsAtom* aProperty, + nsAtom* aAttribute); + + /** + * Adds/remove a CSS declaration to the STYLE attribute carried by a given + * element. + * + * @param aStyledElement [IN] A DOM styled element. + * @param aProperty [IN] An atom containing the CSS property to set. + * @param aValue [IN] A string containing the value of the CSS + * property. + */ + [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult + SetCSSPropertyWithTransaction(nsStyledElement& aStyledElement, + nsAtom& aProperty, const nsAString& aValue) { + return SetCSSPropertyInternal(aStyledElement, aProperty, aValue, false); + } + [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult SetCSSPropertyPixelsWithTransaction( + nsStyledElement& aStyledElement, nsAtom& aProperty, int32_t aIntValue); + [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult + SetCSSPropertyPixelsWithoutTransaction(nsStyledElement& aStyledElement, + const nsAtom& aProperty, + int32_t aIntValue); + [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult RemoveCSSPropertyWithTransaction( + nsStyledElement& aStyledElement, nsAtom& aProperty, + const nsAString& aPropertyValue) { + return RemoveCSSPropertyInternal(aStyledElement, aProperty, aPropertyValue, + false); + } + + /** + * Gets the specified/computed style value of a CSS property for a given + * node (or its element ancestor if it is not an element). + * + * @param aContent [IN] A DOM node. + * @param aProperty [IN] An atom containing the CSS property to get. + * @param aPropertyValue [OUT] The retrieved value of the property. + */ + static nsresult GetSpecifiedProperty(nsIContent& aContent, + nsAtom& aCSSProperty, nsAString& aValue); + MOZ_CAN_RUN_SCRIPT static nsresult GetComputedProperty(nsIContent& aContent, + nsAtom& aCSSProperty, + nsAString& aValue); + + /** + * Removes a CSS property from the specified declarations in STYLE attribute + * and removes the node if it is an useless span. + * + * @param aStyledElement [IN] The styled element we want to remove a style + * from. + * @param aProperty [IN] The CSS property atom to remove. + * @param aPropertyValue [IN] The value of the property we have to remove + * if the property accepts more than one value. + */ + [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult RemoveCSSInlineStyleWithTransaction( + nsStyledElement& aStyledElement, nsAtom* aProperty, + const nsAString& aPropertyValue); + + /** + * Answers true is the property can be removed by setting a "none" CSS value + * on a node. + * + * @param aProperty [IN] An atom containing a CSS property. + * @param aAttribute [IN] Pointer to an attribute name or null if this + * information is irrelevant. + * @return A boolean saying if the property can be remove by + * setting a "none" value. + */ + static bool IsCSSInvertible(nsAtom& aProperty, nsAtom* aAttribute); + + /** + * Get the default browser background color if we need it for + * GetCSSBackgroundColorState(). + * + * @param aColor [OUT] The default color as it is defined in prefs. + */ + static void GetDefaultBackgroundColor(nsAString& aColor); + + /** + * Get the default length unit used for CSS Indent/Outdent. + * + * @param aLengthUnit [OUT] The default length unit as it is defined in + * prefs. + */ + static void GetDefaultLengthUnit(nsAString& aLengthUnit); + + /** + * Returns the list of values for the CSS equivalences to + * the passed HTML style for the passed node. + * + * @param aContent [IN] A DOM node. + * @param aHTMLProperty [IN] An atom containing an HTML property. + * @param aAttribute [IN] An atom of attribute name or nullptr if + * irrelevant. + * @param aValueString [OUT] The list of CSS values. + */ + MOZ_CAN_RUN_SCRIPT static nsresult + GetComputedCSSEquivalentToHTMLInlineStyleSet(nsIContent& aContent, + nsAtom* aHTMLProperty, + nsAtom* aAttribute, + nsAString& aValue) { + return GetCSSEquivalentToHTMLInlineStyleSetInternal( + aContent, aHTMLProperty, aAttribute, aValue, StyleType::Computed); + } + + /** + * Does the node aNode (or his parent if it is not an element node) carries + * the CSS equivalent styles to the HTML style for this node ? + * + * @param aContent [IN] A DOM node. + * @param aHTMLProperty [IN] An atom containing an HTML property. + * @param aAttribute [IN] A pointer/atom to an attribute name or nullptr + * if irrelevant. + * @param aValueString [IN/OUT] The attribute value (in) the list of CSS + * values (out). + * @return A boolean being true if the css properties are + * not same as initial value. + */ + MOZ_CAN_RUN_SCRIPT static bool IsComputedCSSEquivalentToHTMLInlineStyleSet( + nsIContent& aContent, nsAtom* aHTMLProperty, nsAtom* aAttribute, + nsAString& aValue) { + MOZ_ASSERT(aHTMLProperty || aAttribute); + return IsCSSEquivalentToHTMLInlineStyleSetInternal( + aContent, aHTMLProperty, aAttribute, aValue, StyleType::Computed); + } + MOZ_CAN_RUN_SCRIPT_BOUNDARY static bool + IsSpecifiedCSSEquivalentToHTMLInlineStyleSet(nsIContent& aContent, + nsAtom* aHTMLProperty, + nsAtom* aAttribute, + nsAString& aValue) { + MOZ_ASSERT(aHTMLProperty || aAttribute); + return IsCSSEquivalentToHTMLInlineStyleSetInternal( + aContent, aHTMLProperty, aAttribute, aValue, StyleType::Specified); + } + + /** + * This is a kind of IsCSSEquivalentToHTMLInlineStyleSet. + * IsCSSEquivalentToHTMLInlineStyleSet returns whether the properties + * aren't same as initial value. But this method returns whether the + * properties aren't set. + * If node is , + * - Is(Computed|Specified)CSSEquivalentToHTMLInlineStyleSet returns false. + * - Have(Computed|Specified)CSSEquivalentStyles returns true. + * + * @param aContent [IN] A DOM node. + * @param aHTMLProperty [IN] An atom containing an HTML property. + * @param aAttribute [IN] An atom to an attribute name or nullptr + * if irrelevant. + * @return A boolean being true if the css properties are + * not set. + */ + MOZ_CAN_RUN_SCRIPT static bool HaveComputedCSSEquivalentStyles( + nsIContent& aContent, nsAtom* aHTMLProperty, nsAtom* aAttribute) { + MOZ_ASSERT(aHTMLProperty || aAttribute); + return HaveCSSEquivalentStylesInternal(aContent, aHTMLProperty, aAttribute, + StyleType::Computed); + } + MOZ_CAN_RUN_SCRIPT_BOUNDARY static bool HaveSpecifiedCSSEquivalentStyles( + nsIContent& aContent, nsAtom* aHTMLProperty, nsAtom* aAttribute) { + MOZ_ASSERT(aHTMLProperty || aAttribute); + return HaveCSSEquivalentStylesInternal(aContent, aHTMLProperty, aAttribute, + StyleType::Specified); + } + + /** + * Adds to the node the CSS inline styles equivalent to the HTML style + * and return the number of CSS properties set by the call. + * + * @param aNode [IN] A DOM node. + * @param aHTMLProperty [IN] An atom containing an HTML property. + * @param aAttribute [IN] An atom to an attribute name or nullptr + * if irrelevant. + * @param aValue [IN] The attribute value. + * + * @return The number of CSS properties set by the call. + */ + [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result + SetCSSEquivalentToHTMLStyleWithTransaction(nsStyledElement& aStyledElement, + nsAtom* aProperty, + nsAtom* aAttribute, + const nsAString* aValue) { + return SetCSSEquivalentToHTMLStyleInternal(aStyledElement, aProperty, + aAttribute, aValue, false); + } + [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result + SetCSSEquivalentToHTMLStyleWithoutTransaction(nsStyledElement& aStyledElement, + nsAtom* aProperty, + nsAtom* aAttribute, + const nsAString* aValue) { + return SetCSSEquivalentToHTMLStyleInternal(aStyledElement, aProperty, + aAttribute, aValue, true); + } + + /** + * Removes from the node the CSS inline styles equivalent to the HTML style. + * + * @param aStyledElement [IN] A DOM Element (must not be null). + * @param aHTMLProperty [IN] An atom containing an HTML property. + * @param aAttribute [IN] An atom to an attribute name or nullptr if + * irrelevant. + * @param aValue [IN] The attribute value. + */ + [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult + RemoveCSSEquivalentToHTMLStyleWithTransaction(nsStyledElement& aStyledElement, + nsAtom* aHTMLProperty, + nsAtom* aAttribute, + const nsAString* aValue) { + return RemoveCSSEquivalentToHTMLStyleInternal(aStyledElement, aHTMLProperty, + aAttribute, aValue, false); + } + [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult + RemoveCSSEquivalentToHTMLStyleWithoutTransaction( + nsStyledElement& aStyledElement, nsAtom* aHTMLProperty, + nsAtom* aAttribute, const nsAString* aValue) { + return RemoveCSSEquivalentToHTMLStyleInternal(aStyledElement, aHTMLProperty, + aAttribute, aValue, true); + } + + /** + * Parses a "xxxx.xxxxxuuu" string where x is a digit and u an alpha char. + * + * @param aString [IN] Input string to parse. + * @param aValue [OUT] Numeric part. + * @param aUnit [OUT] Unit part. + */ + static void ParseLength(const nsAString& aString, float* aValue, + nsAtom** aUnit); + + /** + * Sets the mIsCSSPrefChecked private member; used as callback from observer + * when the CSS pref state is changed. + * + * @param aIsCSSPrefChecked [IN] The new boolean state for the pref. + */ + void SetCSSEnabled(bool aIsCSSPrefChecked); + + /** + * Retrieves the mIsCSSPrefChecked private member, true if the CSS pref is + * checked, false if it is not. + * + * @return the boolean value of the CSS pref. + */ + bool IsCSSPrefChecked() const; + + /** + * DoStyledElementsHaveSameStyle compares two elements and checks if they have + * the same specified CSS declarations in the STYLE attribute. The answer is + * always false if at least one of them carries an ID or a class. + * + * @param aStyledElement [IN] A styled element. + * @param aOtherStyledElement [IN] The other styled element. + * @return true if the two elements are considered to + * have same styles. + */ + static bool DoStyledElementsHaveSameStyle( + nsStyledElement& aStyledElement, nsStyledElement& aOtherStyledElement); + + public: + /** + * Gets the computed style for a given element. Can return null. + */ + static already_AddRefed GetComputedStyle( + dom::Element* aElement); + + private: + enum class StyleType { Specified, Computed }; + + /** + * Retrieves the CSS property atom from an enum. + * + * @param aProperty The enum value for the property. + * @return The corresponding atom. + */ + static nsStaticAtom* GetCSSPropertyAtom(nsCSSEditableProperty aProperty); + + /** + * Retrieves the CSS declarations equivalent to a HTML style value for + * a given equivalence table. + * + * @param aOutArrayOfCSSProperty [OUT] The array of css properties. + * @param aOutArrayOfCSSValue [OUT] The array of values for the CSS + * properties above. + * @param aEquivTable The equivalence table. + * @param aValue The HTML style value. + * @param aGetOrRemoveRequest A boolean value being true if the call to + * the current method is made for + * Get*CSSEquivalentToHTMLInlineStyleSet() + * or + * RemoveCSSEquivalentToHTMLInlineStyleSet(). + */ + static void BuildCSSDeclarations( + nsTArray& aOutArrayOfCSSProperty, + nsTArray& aOutArrayOfCSSValue, const CSSEquivTable* aEquivTable, + const nsAString* aValue, bool aGetOrRemoveRequest); + + /** + * Retrieves the CSS declarations equivalent to the given HTML + * property/attribute/value for a given node. + * + * @param aElement The DOM node. + * @param aHTMLProperty An atom containing an HTML property. + * @param aAttribute An atom to an attribute name or nullptr + * if irrelevant + * @param aValue The attribute value. + * @param aOutArrayOfCSSProperty [OUT] The array of CSS properties. + * @param aOutArrayOfCSSValue [OUT] The array of values for the CSS + * properties above. + * @param aGetOrRemoveRequest A boolean value being true if the call to + * the current method is made for + * Get*CSSEquivalentToHTMLInlineStyleSet() or + * RemoveCSSEquivalentToHTMLInlineStyleSet(). + */ + static void GenerateCSSDeclarationsFromHTMLStyle( + dom::Element& aElement, nsAtom* aHTMLProperty, nsAtom* aAttribute, + const nsAString* aValue, nsTArray& aOutArrayOfCSSProperty, + nsTArray& aOutArrayOfCSSValue, bool aGetOrRemoveRequest); + + /** + * Back-end for GetSpecifiedProperty and GetComputedProperty. + * + * @param aNode [IN] A DOM node. + * @param aProperty [IN] A CSS property. + * @param aValue [OUT] The retrieved value for this property. + */ + MOZ_CAN_RUN_SCRIPT static nsresult GetComputedCSSInlinePropertyBase( + nsIContent& aContent, nsAtom& aCSSProperty, nsAString& aValue); + static nsresult GetSpecifiedCSSInlinePropertyBase(nsIContent& aContent, + nsAtom& aCSSProperty, + nsAString& aValue); + + /** + * Those methods are wrapped with corresponding methods which do not have + * "Internal" in their names. Don't use these methods directly even if + * you want to use one of them in this class. + * Note that these methods may run scrip only when StyleType is Computed. + */ + MOZ_CAN_RUN_SCRIPT static nsresult + GetCSSEquivalentToHTMLInlineStyleSetInternal(nsIContent& aContent, + nsAtom* aHTMLProperty, + nsAtom* aAttribute, + nsAString& aValue, + StyleType aStyleType); + MOZ_CAN_RUN_SCRIPT static bool IsCSSEquivalentToHTMLInlineStyleSetInternal( + nsIContent& aContent, nsAtom* aHTMLProperty, nsAtom* aAttribute, + nsAString& aValue, StyleType aStyleType); + MOZ_CAN_RUN_SCRIPT static bool HaveCSSEquivalentStylesInternal( + nsIContent& aContent, nsAtom* aHTMLProperty, nsAtom* aAttribute, + StyleType aStyleType); + + [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult RemoveCSSPropertyInternal( + nsStyledElement& aStyledElement, nsAtom& aProperty, + const nsAString& aPropertyValue, bool aSuppressTxn = false); + [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult + RemoveCSSEquivalentToHTMLStyleInternal(nsStyledElement& aStyledElement, + nsAtom* aHTMLProperty, + nsAtom* aAttribute, + const nsAString* aValue, + bool aSuppressTransaction); + [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult + SetCSSPropertyInternal(nsStyledElement& aStyledElement, nsAtom& aProperty, + const nsAString& aValue, bool aSuppressTxn = false); + [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result + SetCSSEquivalentToHTMLStyleInternal(nsStyledElement& aStyledElement, + nsAtom* aProperty, nsAtom* aAttribute, + const nsAString* aValue, + bool aSuppressTransaction); + + private: + HTMLEditor* mHTMLEditor; + bool mIsCSSPrefChecked; +}; + +#define NS_EDITOR_INDENT_INCREMENT_IN 0.4134f +#define NS_EDITOR_INDENT_INCREMENT_CM 1.05f +#define NS_EDITOR_INDENT_INCREMENT_MM 10.5f +#define NS_EDITOR_INDENT_INCREMENT_PT 29.76f +#define NS_EDITOR_INDENT_INCREMENT_PC 2.48f +#define NS_EDITOR_INDENT_INCREMENT_EM 3 +#define NS_EDITOR_INDENT_INCREMENT_EX 6 +#define NS_EDITOR_INDENT_INCREMENT_PX 40 +#define NS_EDITOR_INDENT_INCREMENT_PERCENT 4 + +} // namespace mozilla + +#endif // #ifndef mozilla_CSSEditUtils_h diff --git a/editor/libeditor/ChangeAttributeTransaction.cpp b/editor/libeditor/ChangeAttributeTransaction.cpp new file mode 100644 index 0000000000..a9791502b7 --- /dev/null +++ b/editor/libeditor/ChangeAttributeTransaction.cpp @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "ChangeAttributeTransaction.h" + +#include "mozilla/dom/Element.h" // for Element + +#include "nsAString.h" +#include "nsError.h" // for NS_ERROR_NOT_INITIALIZED, etc. + +namespace mozilla { + +using namespace dom; + +// static +already_AddRefed ChangeAttributeTransaction::Create( + Element& aElement, nsAtom& aAttribute, const nsAString& aValue) { + RefPtr transaction = + new ChangeAttributeTransaction(aElement, aAttribute, &aValue); + return transaction.forget(); +} + +// static +already_AddRefed +ChangeAttributeTransaction::CreateToRemove(Element& aElement, + nsAtom& aAttribute) { + RefPtr transaction = + new ChangeAttributeTransaction(aElement, aAttribute, nullptr); + return transaction.forget(); +} + +ChangeAttributeTransaction::ChangeAttributeTransaction(Element& aElement, + nsAtom& aAttribute, + const nsAString* aValue) + : EditTransactionBase(), + mElement(&aElement), + mAttribute(&aAttribute), + mValue(aValue ? *aValue : u""_ns), + mRemoveAttribute(!aValue), + mAttributeWasSet(false) {} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeAttributeTransaction, + EditTransactionBase, mElement) + +NS_IMPL_ADDREF_INHERITED(ChangeAttributeTransaction, EditTransactionBase) +NS_IMPL_RELEASE_INHERITED(ChangeAttributeTransaction, EditTransactionBase) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeAttributeTransaction) +NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase) + +NS_IMETHODIMP ChangeAttributeTransaction::DoTransaction() { + // Need to get the current value of the attribute and save it, and set + // mAttributeWasSet + mAttributeWasSet = + mElement->GetAttr(kNameSpaceID_None, mAttribute, mUndoValue); + + // XXX: hack until attribute-was-set code is implemented + if (!mUndoValue.IsEmpty()) { + mAttributeWasSet = true; + } + // XXX: end hack + + // Now set the attribute to the new value + if (mRemoveAttribute) { + OwningNonNull element = *mElement; + nsresult rv = element->UnsetAttr(kNameSpaceID_None, mAttribute, true); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Element::UnsetAttr() failed"); + return rv; + } + + OwningNonNull element = *mElement; + nsresult rv = element->SetAttr(kNameSpaceID_None, mAttribute, mValue, true); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Element::SetAttr() failed"); + return rv; +} + +NS_IMETHODIMP ChangeAttributeTransaction::UndoTransaction() { + if (NS_WARN_IF(!mElement)) { + return NS_ERROR_NOT_AVAILABLE; + } + if (mAttributeWasSet) { + OwningNonNull element = *mElement; + nsresult rv = + element->SetAttr(kNameSpaceID_None, mAttribute, mUndoValue, true); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Element::SetAttr() failed"); + return rv; + } + OwningNonNull element = *mElement; + nsresult rv = element->UnsetAttr(kNameSpaceID_None, mAttribute, true); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Element::UnsetAttr() failed"); + return rv; +} + +NS_IMETHODIMP ChangeAttributeTransaction::RedoTransaction() { + if (NS_WARN_IF(!mElement)) { + return NS_ERROR_NOT_AVAILABLE; + } + if (mRemoveAttribute) { + OwningNonNull element = *mElement; + nsresult rv = element->UnsetAttr(kNameSpaceID_None, mAttribute, true); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Element::UnsetAttr() failed"); + return rv; + } + + OwningNonNull element = *mElement; + nsresult rv = element->SetAttr(kNameSpaceID_None, mAttribute, mValue, true); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Element::SetAttr() failed"); + return rv; +} + +} // namespace mozilla diff --git a/editor/libeditor/ChangeAttributeTransaction.h b/editor/libeditor/ChangeAttributeTransaction.h new file mode 100644 index 0000000000..6f4dddbb60 --- /dev/null +++ b/editor/libeditor/ChangeAttributeTransaction.h @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef ChangeAttributeTransaction_h +#define ChangeAttributeTransaction_h + +#include "mozilla/Attributes.h" // override +#include "mozilla/EditTransactionBase.h" // base class +#include "nsCOMPtr.h" // nsCOMPtr members +#include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED +#include "nsISupportsImpl.h" // NS_DECL_ISUPPORTS_INHERITED +#include "nsString.h" // nsString members + +class nsAtom; + +namespace mozilla { + +namespace dom { +class Element; +} // namespace dom + +/** + * A transaction that changes an attribute of a content node. This transaction + * covers add, remove, and change attribute. + */ +class ChangeAttributeTransaction final : public EditTransactionBase { + protected: + ChangeAttributeTransaction(dom::Element& aElement, nsAtom& aAttribute, + const nsAString* aValue); + + public: + /** + * Creates a change attribute transaction to set an attribute to something. + * This method never returns nullptr. + * + * @param aElement The element whose attribute will be changed. + * @param aAttribute The name of the attribute to change. + * @param aValue The new value for aAttribute. + */ + static already_AddRefed Create( + dom::Element& aElement, nsAtom& aAttribute, const nsAString& aValue); + + /** + * Creates a change attribute transaction to remove an attribute. This + * method never returns nullptr. + * + * @param aElement The element whose attribute will be changed. + * @param aAttribute The name of the attribute to remove. + */ + static already_AddRefed CreateToRemove( + dom::Element& aElement, nsAtom& aAttribute); + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeAttributeTransaction, + EditTransactionBase) + + NS_DECL_EDITTRANSACTIONBASE + NS_DECL_EDITTRANSACTIONBASE_GETASMETHODS_OVERRIDE(ChangeAttributeTransaction) + + MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction() override; + + private: + virtual ~ChangeAttributeTransaction() = default; + + // The element to operate upon + nsCOMPtr mElement; + + // The attribute to change + RefPtr mAttribute; + + // The value to set the attribute to (ignored if mRemoveAttribute==true) + nsString mValue; + + // The value to set the attribute to for undo + nsString mUndoValue; + + // True if the operation is to remove mAttribute from mElement + bool mRemoveAttribute; + + // True if the mAttribute was set on mElement at the time of execution + bool mAttributeWasSet; +}; + +} // namespace mozilla + +#endif // #ifndef ChangeAttributeTransaction_h diff --git a/editor/libeditor/ChangeStyleTransaction.cpp b/editor/libeditor/ChangeStyleTransaction.cpp new file mode 100644 index 0000000000..2215066802 --- /dev/null +++ b/editor/libeditor/ChangeStyleTransaction.cpp @@ -0,0 +1,311 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/ChangeStyleTransaction.h" + +#include "mozilla/dom/Element.h" // for Element +#include "nsAString.h" // for nsAString::Append, etc. +#include "nsCRT.h" // for nsCRT::IsAsciiSpace +#include "nsDebug.h" // for NS_WARNING, etc. +#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc. +#include "nsGkAtoms.h" // for nsGkAtoms, etc. +#include "nsICSSDeclaration.h" // for nsICSSDeclaration. +#include "nsLiteralString.h" // for NS_LITERAL_STRING, etc. +#include "nsReadableUtils.h" // for ToNewUnicode +#include "nsString.h" // for nsAutoString, nsString, etc. +#include "nsStyledElement.h" // for nsStyledElement. +#include "nsUnicharUtils.h" // for nsCaseInsensitiveStringComparator + +namespace mozilla { + +using namespace dom; + +// static +already_AddRefed ChangeStyleTransaction::Create( + nsStyledElement& aStyledElement, nsAtom& aProperty, + const nsAString& aValue) { + RefPtr transaction = + new ChangeStyleTransaction(aStyledElement, aProperty, aValue, false); + return transaction.forget(); +} + +// static +already_AddRefed ChangeStyleTransaction::CreateToRemove( + nsStyledElement& aStyledElement, nsAtom& aProperty, + const nsAString& aValue) { + RefPtr transaction = + new ChangeStyleTransaction(aStyledElement, aProperty, aValue, true); + return transaction.forget(); +} + +ChangeStyleTransaction::ChangeStyleTransaction(nsStyledElement& aStyledElement, + nsAtom& aProperty, + const nsAString& aValue, + bool aRemove) + : EditTransactionBase(), + mStyledElement(&aStyledElement), + mProperty(&aProperty), + mUndoValue(), + mRedoValue(), + mRemoveProperty(aRemove), + mUndoAttributeWasSet(false), + mRedoAttributeWasSet(false) { + CopyUTF16toUTF8(aValue, mValue); +} + +#define kNullCh ('\0') + +NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeStyleTransaction, EditTransactionBase, + mStyledElement) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeStyleTransaction) +NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase) + +NS_IMPL_ADDREF_INHERITED(ChangeStyleTransaction, EditTransactionBase) +NS_IMPL_RELEASE_INHERITED(ChangeStyleTransaction, EditTransactionBase) + +// Answers true if aValue is in the string list of white-space separated values +// aValueList. +bool ChangeStyleTransaction::ValueIncludes(const nsACString& aValueList, + const nsACString& aValue) { + nsAutoCString valueList(aValueList); + bool result = false; + + // put an extra null at the end + valueList.Append(kNullCh); + + char* start = valueList.BeginWriting(); + char* end = start; + + while (kNullCh != *start) { + while (kNullCh != *start && nsCRT::IsAsciiSpace(*start)) { + // skip leading space + start++; + } + end = start; + + while (kNullCh != *end && !nsCRT::IsAsciiSpace(*end)) { + // look for space or end + end++; + } + // end string here + *end = kNullCh; + + if (start < end) { + if (aValue.Equals(nsDependentCString(start), + nsCaseInsensitiveCStringComparator)) { + result = true; + break; + } + } + start = ++end; + } + return result; +} + +// Removes the value aRemoveValue from the string list of white-space separated +// values aValueList +void ChangeStyleTransaction::RemoveValueFromListOfValues( + nsACString& aValues, const nsACString& aRemoveValue) { + nsAutoCString classStr(aValues); + nsAutoCString outString; + // put an extra null at the end + classStr.Append(kNullCh); + + char* start = classStr.BeginWriting(); + char* end = start; + + while (kNullCh != *start) { + while (kNullCh != *start && nsCRT::IsAsciiSpace(*start)) { + // skip leading space + start++; + } + end = start; + + while (kNullCh != *end && !nsCRT::IsAsciiSpace(*end)) { + // look for space or end + end++; + } + // end string here + *end = kNullCh; + + if (start < end && !aRemoveValue.Equals(start)) { + outString.Append(start); + outString.Append(' '); + } + + start = ++end; + } + aValues.Assign(outString); +} + +NS_IMETHODIMP ChangeStyleTransaction::DoTransaction() { + if (NS_WARN_IF(!mStyledElement)) { + return NS_ERROR_NOT_AVAILABLE; + } + + OwningNonNull styledElement = *mStyledElement; + nsCOMPtr cssDecl = styledElement->Style(); + + // FIXME(bug 1606994): Using atoms forces a string copy here which is not + // great. + nsAutoCString propertyNameString; + mProperty->ToUTF8String(propertyNameString); + + mUndoAttributeWasSet = + mStyledElement->HasAttr(kNameSpaceID_None, nsGkAtoms::style); + + nsAutoCString values; + nsresult rv = cssDecl->GetPropertyValue(propertyNameString, values); + if (NS_FAILED(rv)) { + NS_WARNING("nsICSSDeclaration::GetPropertyPriorityValue() failed"); + return rv; + } + mUndoValue.Assign(values); + + // Does this property accept more than one value? (bug 62682) + bool multiple = AcceptsMoreThanOneValue(*mProperty); + + if (mRemoveProperty) { + nsAutoCString returnString; + if (multiple) { + // Let's remove only the value we have to remove and not the others + RemoveValueFromListOfValues(values, "none"_ns); + RemoveValueFromListOfValues(values, mValue); + if (values.IsEmpty()) { + ErrorResult error; + cssDecl->RemoveProperty(propertyNameString, returnString, error); + if (error.Failed()) { + NS_WARNING("nsICSSDeclaration::RemoveProperty() failed"); + return error.StealNSResult(); + } + } else { + ErrorResult error; + nsAutoCString priority; + cssDecl->GetPropertyPriority(propertyNameString, priority); + cssDecl->SetProperty(propertyNameString, values, priority, error); + if (error.Failed()) { + NS_WARNING("nsICSSDeclaration::SetProperty() failed"); + return error.StealNSResult(); + } + } + } else { + ErrorResult error; + cssDecl->RemoveProperty(propertyNameString, returnString, error); + if (error.Failed()) { + NS_WARNING("nsICSSDeclaration::RemoveProperty() failed"); + return error.StealNSResult(); + } + } + } else { + nsAutoCString priority; + cssDecl->GetPropertyPriority(propertyNameString, priority); + if (multiple) { + // Let's add the value we have to add to the others + AddValueToMultivalueProperty(values, mValue); + } else { + values.Assign(mValue); + } + ErrorResult error; + cssDecl->SetProperty(propertyNameString, values, priority, error); + if (error.Failed()) { + NS_WARNING("nsICSSDeclaration::SetProperty() failed"); + return error.StealNSResult(); + } + } + + // Let's be sure we don't keep an empty style attribute + uint32_t length = cssDecl->Length(); + if (!length) { + nsresult rv = + styledElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::style, true); + if (NS_FAILED(rv)) { + NS_WARNING("Element::UnsetAttr(nsGkAtoms::style) failed"); + return rv; + } + } else { + mRedoAttributeWasSet = true; + } + + rv = cssDecl->GetPropertyValue(propertyNameString, mRedoValue); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "nsICSSDeclaration::GetPropertyValue() failed"); + return rv; +} + +nsresult ChangeStyleTransaction::SetStyle(bool aAttributeWasSet, + nsACString& aValue) { + if (NS_WARN_IF(!mStyledElement)) { + return NS_ERROR_NOT_AVAILABLE; + } + + if (aAttributeWasSet) { + OwningNonNull styledElement = *mStyledElement; + + // The style attribute was not empty, let's recreate the declaration + nsAutoCString propertyNameString; + mProperty->ToUTF8String(propertyNameString); + + nsCOMPtr cssDecl = styledElement->Style(); + + ErrorResult error; + if (aValue.IsEmpty()) { + // An empty value means we have to remove the property + nsAutoCString returnString; + cssDecl->RemoveProperty(propertyNameString, returnString, error); + if (error.Failed()) { + NS_WARNING("nsICSSDeclaration::RemoveProperty() failed"); + return error.StealNSResult(); + } + } + // Let's recreate the declaration as it was + nsAutoCString priority; + cssDecl->GetPropertyPriority(propertyNameString, priority); + cssDecl->SetProperty(propertyNameString, aValue, priority, error); + NS_WARNING_ASSERTION(!error.Failed(), + "nsICSSDeclaration::SetProperty() failed"); + return error.StealNSResult(); + } + + OwningNonNull styledElement = *mStyledElement; + nsresult rv = + styledElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::style, true); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "Element::UnsetAttr(nsGkAtoms::style) failed"); + return rv; +} + +NS_IMETHODIMP ChangeStyleTransaction::UndoTransaction() { + nsresult rv = SetStyle(mUndoAttributeWasSet, mUndoValue); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "ChangeStyleTransaction::SetStyle() failed"); + return rv; +} + +NS_IMETHODIMP ChangeStyleTransaction::RedoTransaction() { + nsresult rv = SetStyle(mRedoAttributeWasSet, mRedoValue); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "ChangeStyleTransaction::SetStyle() failed"); + return rv; +} + +// True if the CSS property accepts more than one value +bool ChangeStyleTransaction::AcceptsMoreThanOneValue(nsAtom& aCSSProperty) { + return &aCSSProperty == nsGkAtoms::text_decoration; +} + +// Adds the value aNewValue to the list of white-space separated values aValues +void ChangeStyleTransaction::AddValueToMultivalueProperty( + nsACString& aValues, const nsACString& aNewValue) { + if (aValues.IsEmpty() || aValues.LowerCaseEqualsLiteral("none")) { + aValues.Assign(aNewValue); + } else if (!ValueIncludes(aValues, aNewValue)) { + // We already have another value but not this one; add it + aValues.Append(char16_t(' ')); + aValues.Append(aNewValue); + } +} + +} // namespace mozilla diff --git a/editor/libeditor/ChangeStyleTransaction.h b/editor/libeditor/ChangeStyleTransaction.h new file mode 100644 index 0000000000..d837f21c84 --- /dev/null +++ b/editor/libeditor/ChangeStyleTransaction.h @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_ChangeStyleTransaction_h +#define mozilla_ChangeStyleTransaction_h + +#include "mozilla/EditTransactionBase.h" // base class +#include "nsCOMPtr.h" // nsCOMPtr members +#include "nsCycleCollectionParticipant.h" // various macros +#include "nsString.h" // nsString members + +class nsAtom; +class nsStyledElement; + +namespace mozilla { + +namespace dom { +class Element; +} // namespace dom + +/** + * A transaction that changes the value of a CSS inline style of a content + * node. This transaction covers add, remove, and change a property's value. + */ +class ChangeStyleTransaction final : public EditTransactionBase { + protected: + ChangeStyleTransaction(nsStyledElement& aStyledElement, nsAtom& aProperty, + const nsAString& aValue, bool aRemove); + + public: + /** + * Creates a change style transaction. This never returns nullptr. + * + * @param aStyledElement The node whose style attribute will be changed. + * @param aProperty The name of the property to change. + * @param aValue New value for aProperty. + */ + static already_AddRefed Create( + nsStyledElement& aStyledElement, nsAtom& aProperty, + const nsAString& aValue); + + /** + * Creates a change style transaction. This never returns nullptr. + * + * @param aStyledElement The node whose style attribute will be changed. + * @param aProperty The name of the property to change. + * @param aValue The value to remove from aProperty. + */ + static already_AddRefed CreateToRemove( + nsStyledElement& aStyledElement, nsAtom& aProperty, + const nsAString& aValue); + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeStyleTransaction, + EditTransactionBase) + + NS_DECL_ISUPPORTS_INHERITED + + NS_DECL_EDITTRANSACTIONBASE + NS_DECL_EDITTRANSACTIONBASE_GETASMETHODS_OVERRIDE(ChangeStyleTransaction) + + MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction() override; + + /** + * Returns true if the list of white-space separated values contains aValue + * + * @param aValueList [IN] a list of white-space separated values + * @param aValue [IN] the value to look for in the list + * @return true if the value is in the list of values + */ + static bool ValueIncludes(const nsACString& aValueList, + const nsACString& aValue); + + private: + virtual ~ChangeStyleTransaction() = default; + + /* + * Adds the value aNewValue to list of white-space separated values aValues. + * + * @param aValues [IN/OUT] a list of wite-space separated values + * @param aNewValue [IN] a value this code adds to aValues if it is not + * already in + */ + void AddValueToMultivalueProperty(nsACString& aValues, + const nsACString& aNewValue); + + /** + * Returns true if the property accepts more than one value. + * + * @param aCSSProperty [IN] the CSS property + * @return true if the property accepts more than one value + */ + bool AcceptsMoreThanOneValue(nsAtom& aCSSProperty); + + /** + * Remove a value from a list of white-space separated values. + * @param aValues [IN] a list of white-space separated values + * @param aRemoveValue [IN] the value to remove from the list + */ + void RemoveValueFromListOfValues(nsACString& aValues, + const nsACString& aRemoveValue); + + /** + * If the boolean is true and if the value is not the empty string, + * set the property in the transaction to that value; if the value + * is empty, remove the property from element's styles. If the boolean + * is false, just remove the style attribute. + */ + MOZ_CAN_RUN_SCRIPT nsresult SetStyle(bool aAttributeWasSet, + nsACString& aValue); + + // The element to operate upon. + RefPtr mStyledElement; + + // The CSS property to change. + RefPtr mProperty; + + // The value to set the property to (ignored if mRemoveProperty==true). + nsCString mValue; + + // The value to set the property to for undo. + nsCString mUndoValue; + // The value to set the property to for redo. + nsCString mRedoValue; + + // true if the operation is to remove mProperty from mElement. + bool mRemoveProperty; + + // True if the style attribute was present and not empty before DoTransaction. + bool mUndoAttributeWasSet; + // True if the style attribute is present and not empty after DoTransaction. + bool mRedoAttributeWasSet; +}; + +} // namespace mozilla + +#endif // #ifndef mozilla_ChangeStyleTransaction_h diff --git a/editor/libeditor/CompositionTransaction.cpp b/editor/libeditor/CompositionTransaction.cpp new file mode 100644 index 0000000000..136718201a --- /dev/null +++ b/editor/libeditor/CompositionTransaction.cpp @@ -0,0 +1,390 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "CompositionTransaction.h" + +#include "mozilla/EditorBase.h" // mEditorBase +#include "mozilla/SelectionState.h" // RangeUpdater +#include "mozilla/TextComposition.h" // TextComposition +#include "mozilla/dom/Selection.h" // local var +#include "mozilla/dom/Text.h" // mTextNode +#include "nsAString.h" // params +#include "nsDebug.h" // for NS_ASSERTION, etc +#include "nsError.h" // for NS_SUCCEEDED, NS_FAILED, etc +#include "nsRange.h" // local var +#include "nsISelectionController.h" // for nsISelectionController constants +#include "nsQueryObject.h" // for do_QueryObject + +namespace mozilla { + +using namespace dom; + +// static +already_AddRefed CompositionTransaction::Create( + EditorBase& aEditorBase, const nsAString& aStringToInsert, + const EditorDOMPointInText& aPointToInsert) { + MOZ_ASSERT(aPointToInsert.IsSetAndValid()); + + TextComposition* composition = aEditorBase.GetComposition(); + MOZ_RELEASE_ASSERT(composition); + // XXX Actually, we get different text node and offset from editor in some + // cases. If composition stores text node, we should use it and offset + // in it. + EditorDOMPointInText pointToInsert; + if (Text* textNode = composition->GetContainerTextNode()) { + pointToInsert.Set(textNode, composition->XPOffsetInTextNode()); + NS_WARNING_ASSERTION( + pointToInsert.GetContainerAsText() == + composition->GetContainerTextNode(), + "The editor tries to insert composition string into different node"); + NS_WARNING_ASSERTION( + pointToInsert.Offset() == composition->XPOffsetInTextNode(), + "The editor tries to insert composition string into different offset"); + } else { + pointToInsert = aPointToInsert; + } + RefPtr transaction = + new CompositionTransaction(aEditorBase, aStringToInsert, pointToInsert); + // XXX Now, it might be better to modify the text node information of + // the TextComposition instance in DoTransaction() because updating + // the information before changing actual DOM tree is pretty odd. + composition->OnCreateCompositionTransaction( + aStringToInsert, pointToInsert.ContainerAsText(), pointToInsert.Offset()); + return transaction.forget(); +} + +CompositionTransaction::CompositionTransaction( + EditorBase& aEditorBase, const nsAString& aStringToInsert, + const EditorDOMPointInText& aPointToInsert) + : mTextNode(aPointToInsert.ContainerAsText()), + mOffset(aPointToInsert.Offset()), + mReplaceLength(aEditorBase.GetComposition()->XPLengthInTextNode()), + mRanges(aEditorBase.GetComposition()->GetRanges()), + mStringToInsert(aStringToInsert), + mEditorBase(&aEditorBase), + mFixed(false) { + MOZ_ASSERT(mTextNode->TextLength() >= mOffset); +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(CompositionTransaction, EditTransactionBase, + mEditorBase, mTextNode) +// mRangeList can't lead to cycles + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CompositionTransaction) +NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase) +NS_IMPL_ADDREF_INHERITED(CompositionTransaction, EditTransactionBase) +NS_IMPL_RELEASE_INHERITED(CompositionTransaction, EditTransactionBase) + +NS_IMETHODIMP CompositionTransaction::DoTransaction() { + if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) { + return NS_ERROR_NOT_AVAILABLE; + } + + // Fail before making any changes if there's no selection controller + if (NS_WARN_IF(!mEditorBase->GetSelectionController())) { + return NS_ERROR_NOT_AVAILABLE; + } + + OwningNonNull editorBase = *mEditorBase; + OwningNonNull textNode = *mTextNode; + + // Advance caret: This requires the presentation shell to get the selection. + if (mReplaceLength == 0) { + ErrorResult error; + editorBase->DoInsertText(textNode, mOffset, mStringToInsert, error); + if (error.Failed()) { + NS_WARNING("EditorBase::DoInsertText() failed"); + return error.StealNSResult(); + } + editorBase->RangeUpdaterRef().SelAdjInsertText(textNode, mOffset, + mStringToInsert.Length()); + } else { + // If composition string is split to multiple text nodes, we should put + // whole new composition string to the first text node and remove the + // compostion string in other nodes. + uint32_t replaceableLength = textNode->TextLength() - mOffset; + ErrorResult error; + editorBase->DoReplaceText(textNode, mOffset, mReplaceLength, + mStringToInsert, error); + if (error.Failed()) { + NS_WARNING("EditorBase::DoReplaceText() failed"); + return error.StealNSResult(); + } + + // Don't use RangeUpdaterRef().SelAdjReplaceText() here because undoing + // this transaction will remove whole composition string. Therefore, + // selection should be restored at start of composition string. + // XXX Perhaps, this is a bug of our selection managemnt at undoing. + editorBase->RangeUpdaterRef().SelAdjDeleteText(textNode, mOffset, + replaceableLength); + // But some ranges which after the composition string should be restored + // as-is. + editorBase->RangeUpdaterRef().SelAdjInsertText(textNode, mOffset, + mStringToInsert.Length()); + + if (replaceableLength < mReplaceLength) { + // XXX Perhaps, scanning following sibling text nodes with composition + // string length which we know is wrong because there may be + // non-empty text nodes which are inserted by JS. Instead, we + // should remove all text in the ranges of IME selections. + int32_t remainLength = mReplaceLength - replaceableLength; + IgnoredErrorResult ignoredError; + for (nsIContent* nextSibling = textNode->GetNextSibling(); + nextSibling && nextSibling->IsText() && remainLength; + nextSibling = nextSibling->GetNextSibling()) { + OwningNonNull followingTextNode = + *static_cast(nextSibling); + uint32_t textLength = followingTextNode->TextLength(); + editorBase->DoDeleteText(followingTextNode, 0, remainLength, + ignoredError); + NS_WARNING_ASSERTION(!ignoredError.Failed(), + "EditorBase::DoDeleteText() failed, but ignored"); + ignoredError.SuppressException(); + // XXX Needs to check whether the text is deleted as expected. + editorBase->RangeUpdaterRef().SelAdjDeleteText(followingTextNode, 0, + remainLength); + remainLength -= textLength; + } + } + } + + nsresult rv = SetSelectionForRanges(); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rv), + "CompositionTransaction::SetSelectionForRanges() failed"); + return rv; +} + +NS_IMETHODIMP CompositionTransaction::UndoTransaction() { + if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) { + return NS_ERROR_NOT_AVAILABLE; + } + + // Get the selection first so we'll fail before making any changes if we + // can't get it + RefPtr selection = mEditorBase->GetSelection(); + if (NS_WARN_IF(!selection)) { + return NS_ERROR_NOT_AVAILABLE; + } + + OwningNonNull editorBase = *mEditorBase; + OwningNonNull textNode = *mTextNode; + ErrorResult error; + editorBase->DoDeleteText(textNode, mOffset, mStringToInsert.Length(), error); + if (error.Failed()) { + NS_WARNING("EditorBase::DoDeleteText() failed"); + return error.StealNSResult(); + } + + // set the selection to the insertion point where the string was removed + nsresult rv = selection->CollapseInLimiter(textNode, mOffset); + NS_ASSERTION(NS_SUCCEEDED(rv), "Selection::CollapseInLimiter() failed"); + return rv; +} + +NS_IMETHODIMP CompositionTransaction::Merge(nsITransaction* aOtherTransaction, + bool* aDidMerge) { + if (NS_WARN_IF(!aOtherTransaction) || NS_WARN_IF(!aDidMerge)) { + return NS_ERROR_INVALID_ARG; + } + *aDidMerge = false; + + // Check to make sure we aren't fixed, if we are then nothing gets merged. + if (mFixed) { + return NS_OK; + } + + RefPtr otherTransactionBase = + aOtherTransaction->GetAsEditTransactionBase(); + if (!otherTransactionBase) { + return NS_OK; + } + + // If aTransaction is another CompositionTransaction then merge it + CompositionTransaction* otherCompositionTransaction = + otherTransactionBase->GetAsCompositionTransaction(); + if (!otherCompositionTransaction) { + return NS_OK; + } + + // We merge the next IME transaction by adopting its insert string. + mStringToInsert = otherCompositionTransaction->mStringToInsert; + mRanges = otherCompositionTransaction->mRanges; + *aDidMerge = true; + return NS_OK; +} + +void CompositionTransaction::MarkFixed() { mFixed = true; } + +/* ============ private methods ================== */ + +nsresult CompositionTransaction::SetSelectionForRanges() { + if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) { + return NS_ERROR_NOT_AVAILABLE; + } + OwningNonNull editorBase = *mEditorBase; + OwningNonNull textNode = *mTextNode; + RefPtr ranges = mRanges; + nsresult rv = SetIMESelection(editorBase, textNode, mOffset, + mStringToInsert.Length(), ranges); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "CompositionTransaction::SetIMESelection() failed"); + return rv; +} + +// static +nsresult CompositionTransaction::SetIMESelection( + EditorBase& aEditorBase, Text* aTextNode, uint32_t aOffsetInNode, + uint32_t aLengthOfCompositionString, const TextRangeArray* aRanges) { + RefPtr selection = aEditorBase.GetSelection(); + if (NS_WARN_IF(!selection)) { + return NS_ERROR_NOT_INITIALIZED; + } + + SelectionBatcher selectionBatcher(selection); + + // First, remove all selections of IME composition. + static const RawSelectionType kIMESelections[] = { + nsISelectionController::SELECTION_IME_RAWINPUT, + nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT, + nsISelectionController::SELECTION_IME_CONVERTEDTEXT, + nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT}; + + nsCOMPtr selectionController = + aEditorBase.GetSelectionController(); + if (NS_WARN_IF(!selectionController)) { + return NS_ERROR_NOT_INITIALIZED; + } + + IgnoredErrorResult ignoredError; + for (uint32_t i = 0; i < ArrayLength(kIMESelections); ++i) { + RefPtr selectionOfIME = + selectionController->GetSelection(kIMESelections[i]); + if (!selectionOfIME) { + NS_WARNING("nsISelectionController::GetSelection() failed"); + continue; + } + selectionOfIME->RemoveAllRanges(ignoredError); + NS_WARNING_ASSERTION(!ignoredError.Failed(), + "Selection::RemoveAllRanges() failed, but ignored"); + ignoredError.SuppressException(); + } + + // Set caret position and selection of IME composition with TextRangeArray. + bool setCaret = false; + uint32_t countOfRanges = aRanges ? aRanges->Length() : 0; + +#ifdef DEBUG + // Bounds-checking on debug builds + uint32_t maxOffset = aTextNode->Length(); +#endif + + // NOTE: composition string may be truncated when it's committed and + // maxlength attribute value doesn't allow input of all text of this + // composition. + nsresult rv = NS_OK; + for (uint32_t i = 0; i < countOfRanges; ++i) { + const TextRange& textRange = aRanges->ElementAt(i); + + // Caret needs special handling since its length may be 0 and if it's not + // specified explicitly, we need to handle it ourselves later. + if (textRange.mRangeType == TextRangeType::eCaret) { + NS_ASSERTION(!setCaret, "The ranges already has caret position"); + NS_ASSERTION(!textRange.Length(), + "EditorBase doesn't support wide caret"); + int32_t caretOffset = static_cast( + aOffsetInNode + + std::min(textRange.mStartOffset, aLengthOfCompositionString)); + MOZ_ASSERT(caretOffset >= 0 && + static_cast(caretOffset) <= maxOffset); + rv = selection->CollapseInLimiter(aTextNode, caretOffset); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rv), + "Selection::CollapseInLimiter() failed, but might be ignored"); + setCaret = setCaret || NS_SUCCEEDED(rv); + if (!setCaret) { + continue; + } + // If caret range is specified explicitly, we should show the caret if + // it should be so. + aEditorBase.HideCaret(false); + continue; + } + + // If the clause length is 0, it should be a bug. + if (!textRange.Length()) { + NS_WARNING("Any clauses must not be empty"); + continue; + } + + RefPtr clauseRange; + int32_t startOffset = static_cast( + aOffsetInNode + + std::min(textRange.mStartOffset, aLengthOfCompositionString)); + MOZ_ASSERT(startOffset >= 0 && + static_cast(startOffset) <= maxOffset); + int32_t endOffset = static_cast( + aOffsetInNode + + std::min(textRange.mEndOffset, aLengthOfCompositionString)); + MOZ_ASSERT(endOffset >= startOffset && + static_cast(endOffset) <= maxOffset); + clauseRange = nsRange::Create(aTextNode, startOffset, aTextNode, endOffset, + IgnoreErrors()); + if (!clauseRange) { + NS_WARNING("nsRange::Create() failed, but might be ignored"); + break; + } + + // Set the range of the clause to selection. + RefPtr selectionOfIME = selectionController->GetSelection( + ToRawSelectionType(textRange.mRangeType)); + if (!selectionOfIME) { + NS_WARNING( + "nsISelectionController::GetSelection() failed, but might be " + "ignored"); + break; + } + + IgnoredErrorResult ignoredError; + selectionOfIME->AddRangeAndSelectFramesAndNotifyListeners(*clauseRange, + ignoredError); + if (ignoredError.Failed()) { + NS_WARNING( + "Selection::AddRangeAndSelectFramesAndNotifyListeners() failed, but " + "might be ignored"); + break; + } + + // Set the style of the clause. + rv = selectionOfIME->SetTextRangeStyle(clauseRange, textRange.mRangeStyle); + if (NS_FAILED(rv)) { + NS_WARNING("Selection::SetTextRangeStyle() failed, but might be ignored"); + break; // but this is unexpected... + } + } + + // If the ranges doesn't include explicit caret position, let's set the + // caret to the end of composition string. + if (!setCaret) { + int32_t caretOffset = + static_cast(aOffsetInNode + aLengthOfCompositionString); + MOZ_ASSERT(caretOffset >= 0 && + static_cast(caretOffset) <= maxOffset); + rv = selection->CollapseInLimiter(aTextNode, caretOffset); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "Selection::CollapseInLimiter() failed"); + + // If caret range isn't specified explicitly, we should hide the caret. + // Hiding the caret benefits a Windows build (see bug 555642 comment #6). + // However, when there is no range, we should keep showing caret. + if (countOfRanges) { + aEditorBase.HideCaret(true); + } + } + + return rv; +} + +} // namespace mozilla diff --git a/editor/libeditor/CompositionTransaction.h b/editor/libeditor/CompositionTransaction.h new file mode 100644 index 0000000000..a3b7950346 --- /dev/null +++ b/editor/libeditor/CompositionTransaction.h @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef CompositionTransaction_h +#define CompositionTransaction_h + +#include "mozilla/EditTransactionBase.h" // base class + +#include "mozilla/EditorDOMPoint.h" // EditorDOMPointInText +#include "mozilla/WeakPtr.h" +#include "nsCycleCollectionParticipant.h" // various macros +#include "nsString.h" // mStringToInsert + +namespace mozilla { + +class EditorBase; +class TextComposition; +class TextRangeArray; + +namespace dom { +class Text; +} // namespace dom + +/** + * CompositionTransaction stores all edit for a composition, i.e., + * from compositionstart event to compositionend event. E.g., inserting a + * composition string, modifying the composition string or its IME selection + * ranges and commit or cancel the composition. + */ +class CompositionTransaction final : public EditTransactionBase, + public SupportsWeakPtr { + protected: + CompositionTransaction(EditorBase& aEditorBase, + const nsAString& aStringToInsert, + const EditorDOMPointInText& aPointToInsert); + + public: + /** + * Creates a composition transaction. aEditorBase must not return from + * GetComposition() while calling this method. Note that this method will + * update text node information of aEditorBase.mComposition. + * + * @param aEditorBase The editor which has composition. + * @param aStringToInsert The new composition string to insert. This may + * be different from actual composition string. + * E.g., password editor can hide the character + * with a different character. + * @param aPointToInsert The insertion point. + */ + static already_AddRefed Create( + EditorBase& aEditorBase, const nsAString& aStringToInsert, + const EditorDOMPointInText& aPointToInsert); + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CompositionTransaction, + EditTransactionBase) + + NS_DECL_ISUPPORTS_INHERITED + + NS_DECL_EDITTRANSACTIONBASE + NS_DECL_EDITTRANSACTIONBASE_GETASMETHODS_OVERRIDE(CompositionTransaction) + + NS_IMETHOD Merge(nsITransaction* aOtherTransaction, bool* aDidMerge) override; + + void MarkFixed(); + + MOZ_CAN_RUN_SCRIPT static nsresult SetIMESelection( + EditorBase& aEditorBase, dom::Text* aTextNode, uint32_t aOffsetInNode, + uint32_t aLengthOfCompositionString, const TextRangeArray* aRanges); + + private: + virtual ~CompositionTransaction() = default; + + MOZ_CAN_RUN_SCRIPT nsresult SetSelectionForRanges(); + + // The text element to operate upon. + RefPtr mTextNode; + + // The offsets into mTextNode where the insertion should be placed. + uint32_t mOffset; + + uint32_t mReplaceLength; + + // The range list. + RefPtr mRanges; + + // The text to insert into mTextNode at mOffset. + nsString mStringToInsert; + + // The editor, which is used to get the selection controller. + RefPtr mEditorBase; + + bool mFixed; +}; + +} // namespace mozilla + +#endif // #ifndef CompositionTransaction_h diff --git a/editor/libeditor/CreateElementTransaction.cpp b/editor/libeditor/CreateElementTransaction.cpp new file mode 100644 index 0000000000..2dee25c736 --- /dev/null +++ b/editor/libeditor/CreateElementTransaction.cpp @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "CreateElementTransaction.h" + +#include +#include + +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Selection.h" + +#include "mozilla/Casting.h" +#include "mozilla/EditorBase.h" +#include "mozilla/EditorDOMPoint.h" + +#include "nsAlgorithm.h" +#include "nsAString.h" +#include "nsDebug.h" +#include "nsError.h" +#include "nsIContent.h" +#include "nsINode.h" +#include "nsISupportsUtils.h" +#include "nsMemory.h" +#include "nsReadableUtils.h" +#include "nsStringFwd.h" +#include "nsString.h" + +namespace mozilla { + +using namespace dom; + +template already_AddRefed +CreateElementTransaction::Create(EditorBase& aEditorBase, nsAtom& aTag, + const EditorDOMPoint& aPointToInsert); +template already_AddRefed +CreateElementTransaction::Create(EditorBase& aEditorBase, nsAtom& aTag, + const EditorRawDOMPoint& aPointToInsert); + +template +already_AddRefed CreateElementTransaction::Create( + EditorBase& aEditorBase, nsAtom& aTag, + const EditorDOMPointBase& aPointToInsert) { + RefPtr transaction = + new CreateElementTransaction(aEditorBase, aTag, aPointToInsert); + return transaction.forget(); +} + +template +CreateElementTransaction::CreateElementTransaction( + EditorBase& aEditorBase, nsAtom& aTag, + const EditorDOMPointBase& aPointToInsert) + : EditTransactionBase(), + mEditorBase(&aEditorBase), + mTag(&aTag), + mPointToInsert(aPointToInsert) { + MOZ_ASSERT(!mPointToInsert.IsInDataNode()); + // We only need the child node at inserting new node. + AutoEditorDOMPointOffsetInvalidator lockChild(mPointToInsert); +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(CreateElementTransaction, + EditTransactionBase, mEditorBase, + mPointToInsert, mNewElement) + +NS_IMPL_ADDREF_INHERITED(CreateElementTransaction, EditTransactionBase) +NS_IMPL_RELEASE_INHERITED(CreateElementTransaction, EditTransactionBase) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CreateElementTransaction) +NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase) + +NS_IMETHODIMP CreateElementTransaction::DoTransaction() { + if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTag) || + NS_WARN_IF(!mPointToInsert.IsSet())) { + return NS_ERROR_NOT_INITIALIZED; + } + + OwningNonNull editorBase = *mEditorBase; + + mNewElement = editorBase->CreateHTMLContent(mTag); + if (!mNewElement) { + NS_WARNING("EditorBase::CreateHTMLContent() failed"); + return NS_ERROR_FAILURE; + } + + // Try to insert formatting white-space for the new node: + OwningNonNull newElement = *mNewElement; + nsresult rv = editorBase->MarkElementDirty(newElement); + if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) { + return EditorBase::ToGenericNSResult(rv); + } + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "EditorBase::MarkElementDirty() failed, but ignored"); + + // Insert the new node + ErrorResult error; + InsertNewNode(error); + if (error.Failed()) { + NS_WARNING("CreateElementTransaction::InsertNewNode() failed"); + return error.StealNSResult(); + } + + // Only set selection to insertion point if editor gives permission + if (!editorBase->AllowsTransactionsToChangeSelection()) { + // Do nothing - DOM range gravity will adjust selection + return NS_OK; + } + + RefPtr selection = editorBase->GetSelection(); + if (NS_WARN_IF(!selection)) { + return NS_ERROR_FAILURE; + } + + EditorRawDOMPoint afterNewNode(EditorRawDOMPoint::After(newElement)); + if (NS_WARN_IF(!afterNewNode.IsSet())) { + // If mutation observer or mutation event listener moved or removed the + // new node, we hit this case. Should we use script blocker while we're + // in this method? + return NS_ERROR_FAILURE; + } + IgnoredErrorResult ignoredError; + selection->CollapseInLimiter(afterNewNode, ignoredError); + NS_WARNING_ASSERTION(!ignoredError.Failed(), + "Selection::CollapseInLimiter() failed, but ignored"); + return NS_OK; +} + +void CreateElementTransaction::InsertNewNode(ErrorResult& aError) { + MOZ_ASSERT(mNewElement); + MOZ_ASSERT(mPointToInsert.IsSet()); + + if (mPointToInsert.IsSetAndValid()) { + if (mPointToInsert.IsEndOfContainer()) { + OwningNonNull container = *mPointToInsert.GetContainer(); + OwningNonNull newElement = *mNewElement; + container->AppendChild(newElement, aError); + NS_WARNING_ASSERTION(!aError.Failed(), + "nsINode::AppendChild() failed, but ignored"); + return; + } + MOZ_ASSERT(mPointToInsert.GetChild()); + OwningNonNull container = *mPointToInsert.GetContainer(); + OwningNonNull child = *mPointToInsert.GetChild(); + OwningNonNull newElement = *mNewElement; + container->InsertBefore(newElement, child, aError); + NS_WARNING_ASSERTION(!aError.Failed(), + "nsINode::InsertBefore() failed, but ignored"); + // InsertBefore() may call MightThrowJSException() even if there is no + // error. We don't need the flag here. + aError.WouldReportJSException(); + return; + } + + // We still know a child, but the child is different element's child, + // we should just return error. + if (NS_WARN_IF(mPointToInsert.GetChild() && + mPointToInsert.GetContainer() != + mPointToInsert.GetChild()->GetParentNode())) { + // XXX Is NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE better? Since it won't + // cause throwing exception even if editor user throws an error + // returned from editor's public method. + aError.Throw(NS_ERROR_FAILURE); + return; + } + + // If mPointToInsert has only offset and it's not valid, we need to treat + // it as pointing end of the container. + OwningNonNull container = *mPointToInsert.GetContainer(); + OwningNonNull newElement = *mNewElement; + container->AppendChild(newElement, aError); + NS_WARNING_ASSERTION(!aError.Failed(), + "nsINode::AppendChild() failed, but ignored"); +} + +NS_IMETHODIMP CreateElementTransaction::UndoTransaction() { + if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mPointToInsert.IsSet()) || + NS_WARN_IF(!mNewElement)) { + return NS_ERROR_NOT_AVAILABLE; + } + + OwningNonNull newElement = *mNewElement; + OwningNonNull containerNode = *mPointToInsert.GetContainer(); + ErrorResult error; + containerNode->RemoveChild(newElement, error); + NS_WARNING_ASSERTION(!error.Failed(), "nsINode::RemoveChild() failed"); + return error.StealNSResult(); +} + +NS_IMETHODIMP CreateElementTransaction::RedoTransaction() { + if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mPointToInsert.IsSet()) || + NS_WARN_IF(!mNewElement)) { + return NS_ERROR_NOT_AVAILABLE; + } + + // First, reset mNewElement so it has no attributes or content + // XXX We never actually did this, we only cleared mNewElement's contents if + // it was a CharacterData node (which it's not, it's an Element) + // XXX Don't we need to set selection like DoTransaction()? + + // Now, reinsert mNewElement + ErrorResult error; + InsertNewNode(error); + NS_WARNING_ASSERTION(!error.Failed(), + "CreateElementTransaction::InsertNewNode() failed"); + return error.StealNSResult(); +} + +} // namespace mozilla diff --git a/editor/libeditor/CreateElementTransaction.h b/editor/libeditor/CreateElementTransaction.h new file mode 100644 index 0000000000..fc87f500b1 --- /dev/null +++ b/editor/libeditor/CreateElementTransaction.h @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef CreateElementTransaction_h +#define CreateElementTransaction_h + +#include "mozilla/EditorDOMPoint.h" +#include "mozilla/EditTransactionBase.h" +#include "mozilla/RefPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsISupportsImpl.h" + +class nsAtom; + +/** + * A transaction that creates a new node in the content tree. + */ +namespace mozilla { +namespace dom { +class Element; +} + +class EditorBase; + +class CreateElementTransaction final : public EditTransactionBase { + protected: + template + CreateElementTransaction(EditorBase& aEditorBase, nsAtom& aTag, + const EditorDOMPointBase& aPointToInsert); + + public: + /** + * Create a transaction for creating a new child node of the container of + * aPointToInsert of type aTag. + * + * @param aEditorBase The editor which manages the transaction. + * @param aTag The tag (P, HR, TABLE, etc.) for the new element. + * @param aPointToInsert The new node will be inserted before the child at + * aPointToInsert. If this refers end of the container + * or after, the new node will be appended to the + * container. + */ + template + static already_AddRefed Create( + EditorBase& aEditorBase, nsAtom& aTag, + const EditorDOMPointBase& aPointToInsert); + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CreateElementTransaction, + EditTransactionBase) + + NS_DECL_EDITTRANSACTIONBASE + NS_DECL_EDITTRANSACTIONBASE_GETASMETHODS_OVERRIDE(CreateElementTransaction) + + MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction() override; + + dom::Element* GetNewElement() const { return mNewElement; } + + protected: + virtual ~CreateElementTransaction() = default; + + /** + * InsertNewNode() inserts mNewNode before the child node at mPointToInsert. + */ + MOZ_CAN_RUN_SCRIPT void InsertNewNode(ErrorResult& aError); + + // The document into which the new node will be inserted. + RefPtr mEditorBase; + + // The tag (mapping to object type) for the new element. + RefPtr mTag; + + // The DOM point we will insert mNewNode. + EditorDOMPoint mPointToInsert; + + // The new node to insert. + RefPtr mNewElement; +}; + +} // namespace mozilla + +#endif // #ifndef CreateElementTransaction_h diff --git a/editor/libeditor/DeleteNodeTransaction.cpp b/editor/libeditor/DeleteNodeTransaction.cpp new file mode 100644 index 0000000000..eb106a1288 --- /dev/null +++ b/editor/libeditor/DeleteNodeTransaction.cpp @@ -0,0 +1,140 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DeleteNodeTransaction.h" + +#include "HTMLEditUtils.h" +#include "mozilla/EditorBase.h" +#include "mozilla/SelectionState.h" // RangeUpdater +#include "mozilla/TextEditor.h" +#include "nsDebug.h" +#include "nsError.h" +#include "nsAString.h" + +namespace mozilla { + +// static +already_AddRefed DeleteNodeTransaction::MaybeCreate( + EditorBase& aEditorBase, nsIContent& aContentToDelete) { + RefPtr transaction = + new DeleteNodeTransaction(aEditorBase, aContentToDelete); + if (NS_WARN_IF(!transaction->CanDoIt())) { + return nullptr; + } + return transaction.forget(); +} + +DeleteNodeTransaction::DeleteNodeTransaction(EditorBase& aEditorBase, + nsIContent& aContentToDelete) + : mEditorBase(&aEditorBase), + mContentToDelete(&aContentToDelete), + mParentNode(aContentToDelete.GetParentNode()) {} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteNodeTransaction, EditTransactionBase, + mEditorBase, mContentToDelete, mParentNode, + mRefContent) + +NS_IMPL_ADDREF_INHERITED(DeleteNodeTransaction, EditTransactionBase) +NS_IMPL_RELEASE_INHERITED(DeleteNodeTransaction, EditTransactionBase) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteNodeTransaction) +NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase) + +bool DeleteNodeTransaction::CanDoIt() const { + if (NS_WARN_IF(!mContentToDelete) || NS_WARN_IF(!mEditorBase) || + !mParentNode) { + return false; + } + return mEditorBase->IsTextEditor() || + HTMLEditUtils::IsSimplyEditableNode(*mParentNode); +} + +NS_IMETHODIMP DeleteNodeTransaction::DoTransaction() { + if (NS_WARN_IF(!CanDoIt())) { + return NS_OK; + } + + if (mEditorBase->IsTextEditor() && mContentToDelete->IsText()) { + uint32_t length = mContentToDelete->AsText()->TextLength(); + if (length > 0) { + mEditorBase->AsTextEditor()->WillDeleteText(length, 0, length); + } + } + + // Remember which child mContentToDelete was (by remembering which child was + // next). Note that mRefContent can be nullptr. + mRefContent = mContentToDelete->GetNextSibling(); + + // give range updater a chance. SelAdjDeleteNode() needs to be called + // *before* we do the action, unlike some of the other RangeItem update + // methods. + mEditorBase->RangeUpdaterRef().SelAdjDeleteNode(*mContentToDelete); + + OwningNonNull parentNode = *mParentNode; + OwningNonNull contentToDelete = *mContentToDelete; + ErrorResult error; + parentNode->RemoveChild(contentToDelete, error); + NS_WARNING_ASSERTION(!error.Failed(), "nsINode::RemoveChild() failed"); + return error.StealNSResult(); +} + +MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP +DeleteNodeTransaction::UndoTransaction() { + if (NS_WARN_IF(!CanDoIt())) { + // This is a legal state, the transaction is a no-op. + return NS_OK; + } + ErrorResult error; + OwningNonNull editorBase = *mEditorBase; + OwningNonNull parentNode = *mParentNode; + OwningNonNull contentToDelete = *mContentToDelete; + nsCOMPtr refContent = mRefContent; + // XXX Perhaps, we should check `refContent` is a child of `parentNode`, + // and if it's not, we should stop undoing or something. + parentNode->InsertBefore(contentToDelete, refContent, error); + // InsertBefore() may call MightThrowJSException() even if there is no error. + // We don't need the flag here. + error.WouldReportJSException(); + if (error.Failed()) { + NS_WARNING("nsINode::InsertBefore() failed"); + return error.StealNSResult(); + } + if (editorBase->IsTextEditor() && contentToDelete->IsText()) { + uint32_t length = contentToDelete->AsText()->TextLength(); + if (length > 0) { + nsresult rv = MOZ_KnownLive(editorBase->AsTextEditor()) + ->DidInsertText(length, 0, length); + if (NS_FAILED(rv)) { + NS_WARNING("TextEditor::DidInsertText() failed"); + return rv; + } + } + } + return NS_OK; +} + +NS_IMETHODIMP DeleteNodeTransaction::RedoTransaction() { + if (NS_WARN_IF(!CanDoIt())) { + // This is a legal state, the transaction is a no-op. + return NS_OK; + } + + if (mEditorBase->IsTextEditor() && mContentToDelete->IsText()) { + uint32_t length = mContentToDelete->AsText()->TextLength(); + if (length > 0) { + mEditorBase->AsTextEditor()->WillDeleteText(length, 0, length); + } + } + + mEditorBase->RangeUpdaterRef().SelAdjDeleteNode(*mContentToDelete); + + OwningNonNull parentNode = *mParentNode; + OwningNonNull contentToDelete = *mContentToDelete; + ErrorResult error; + parentNode->RemoveChild(contentToDelete, error); + NS_WARNING_ASSERTION(!error.Failed(), "nsINode::RemoveChild() failed"); + return error.StealNSResult(); +} + +} // namespace mozilla diff --git a/editor/libeditor/DeleteNodeTransaction.h b/editor/libeditor/DeleteNodeTransaction.h new file mode 100644 index 0000000000..c0e7a00508 --- /dev/null +++ b/editor/libeditor/DeleteNodeTransaction.h @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef DeleteNodeTransaction_h +#define DeleteNodeTransaction_h + +#include "mozilla/EditTransactionBase.h" +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIContent.h" +#include "nsINode.h" +#include "nsISupportsImpl.h" +#include "nscore.h" + +namespace mozilla { + +class EditorBase; + +/** + * A transaction that deletes a single element + */ +class DeleteNodeTransaction final : public EditTransactionBase { + protected: + DeleteNodeTransaction(EditorBase& aEditorBase, nsIContent& aContentToDelete); + + public: + /** + * Creates a delete node transaction instance. This returns nullptr if + * it cannot remove the node from its parent. + * + * @param aEditorBase The editor. + * @param aContentToDelete The node to be removed from the DOM tree. + */ + static already_AddRefed MaybeCreate( + EditorBase& aEditorBase, nsIContent& aContentToDelete); + + /** + * CanDoIt() returns true if there are enough members and can modify the + * parent. Otherwise, false. + */ + bool CanDoIt() const; + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteNodeTransaction, + EditTransactionBase) + + NS_DECL_EDITTRANSACTIONBASE + NS_DECL_EDITTRANSACTIONBASE_GETASMETHODS_OVERRIDE(DeleteNodeTransaction) + + MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction() override; + + nsIContent* GetContent() const { return mContentToDelete; } + + protected: + virtual ~DeleteNodeTransaction() = default; + + // The editor for this transaction. + RefPtr mEditorBase; + + // The element to delete. + nsCOMPtr mContentToDelete; + + // Parent of node to delete. + nsCOMPtr mParentNode; + + // Next sibling to remember for undo/redo purposes. + nsCOMPtr mRefContent; +}; + +} // namespace mozilla + +#endif // #ifndef DeleteNodeTransaction_h diff --git a/editor/libeditor/DeleteRangeTransaction.cpp b/editor/libeditor/DeleteRangeTransaction.cpp new file mode 100644 index 0000000000..0980201c0b --- /dev/null +++ b/editor/libeditor/DeleteRangeTransaction.cpp @@ -0,0 +1,270 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DeleteRangeTransaction.h" + +#include "DeleteNodeTransaction.h" +#include "DeleteTextTransaction.h" +#include "mozilla/Assertions.h" +#include "mozilla/ContentIterator.h" +#include "mozilla/dom/Selection.h" +#include "mozilla/EditorBase.h" +#include "mozilla/mozalloc.h" +#include "mozilla/RangeBoundary.h" +#include "nsCOMPtr.h" +#include "nsDebug.h" +#include "nsError.h" +#include "nsIContent.h" +#include "nsINode.h" +#include "nsAString.h" + +namespace mozilla { + +using namespace dom; + +DeleteRangeTransaction::DeleteRangeTransaction(EditorBase& aEditorBase, + const nsRange& aRangeToDelete) + : mEditorBase(&aEditorBase), mRangeToDelete(aRangeToDelete.CloneRange()) {} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteRangeTransaction, + EditAggregateTransaction, mEditorBase, + mRangeToDelete) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteRangeTransaction) +NS_INTERFACE_MAP_END_INHERITING(EditAggregateTransaction) + +NS_IMETHODIMP DeleteRangeTransaction::DoTransaction() { + if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mRangeToDelete)) { + return NS_ERROR_NOT_AVAILABLE; + } + + // Swap mRangeToDelete out into a stack variable, so we make sure to null it + // out on return from this function. Once this function returns, we no longer + // need mRangeToDelete, and keeping it alive in the long term slows down all + // DOM mutations because it's observing them. + RefPtr rangeToDelete; + rangeToDelete.swap(mRangeToDelete); + + // build the child transactions + const RangeBoundary& startRef = rangeToDelete->StartRef(); + const RangeBoundary& endRef = rangeToDelete->EndRef(); + MOZ_ASSERT(startRef.IsSetAndValid()); + MOZ_ASSERT(endRef.IsSetAndValid()); + + if (startRef.Container() == endRef.Container()) { + // the selection begins and ends in the same node + nsresult rv = CreateTxnsToDeleteBetween(startRef.AsRaw(), endRef.AsRaw()); + if (NS_FAILED(rv)) { + NS_WARNING("DeleteRangeTransaction::CreateTxnsToDeleteBetween() failed"); + return rv; + } + } else { + // the selection ends in a different node from where it started. delete + // the relevant content in the start node + nsresult rv = CreateTxnsToDeleteContent(startRef.AsRaw(), nsIEditor::eNext); + if (NS_FAILED(rv)) { + NS_WARNING("DeleteRangeTransaction::CreateTxnsToDeleteContent() failed"); + return rv; + } + // delete the intervening nodes + rv = CreateTxnsToDeleteNodesBetween(rangeToDelete); + if (NS_FAILED(rv)) { + NS_WARNING( + "DeleteRangeTransaction::CreateTxnsToDeleteNodesBetween() failed"); + return rv; + } + // delete the relevant content in the end node + rv = CreateTxnsToDeleteContent(endRef.AsRaw(), nsIEditor::ePrevious); + if (NS_FAILED(rv)) { + NS_WARNING("DeleteRangeTransaction::CreateTxnsToDeleteContent() failed"); + return rv; + } + } + + // if we've successfully built this aggregate transaction, then do it. + nsresult rv = EditAggregateTransaction::DoTransaction(); + if (NS_FAILED(rv)) { + NS_WARNING("EditAggregateTransaction::DoTransaction() failed"); + return rv; + } + + if (!mEditorBase->AllowsTransactionsToChangeSelection()) { + return NS_OK; + } + + RefPtr selection = mEditorBase->GetSelection(); + if (NS_WARN_IF(!selection)) { + return NS_ERROR_NOT_INITIALIZED; + } + rv = selection->CollapseInLimiter(startRef.AsRaw()); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "Selection::CollapseInLimiter() failed"); + return rv; +} + +NS_IMETHODIMP DeleteRangeTransaction::UndoTransaction() { + nsresult rv = EditAggregateTransaction::UndoTransaction(); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "EditAggregateTransaction::UndoTransaction() failed"); + return rv; +} + +NS_IMETHODIMP DeleteRangeTransaction::RedoTransaction() { + nsresult rv = EditAggregateTransaction::RedoTransaction(); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "EditAggregateTransaction::RedoTransaction() failed"); + return rv; +} + +nsresult DeleteRangeTransaction::CreateTxnsToDeleteBetween( + const RawRangeBoundary& aStart, const RawRangeBoundary& aEnd) { + if (NS_WARN_IF(!aStart.IsSetAndValid()) || + NS_WARN_IF(!aEnd.IsSetAndValid()) || + NS_WARN_IF(aStart.Container() != aEnd.Container())) { + return NS_ERROR_INVALID_ARG; + } + + if (NS_WARN_IF(!mEditorBase)) { + return NS_ERROR_NOT_AVAILABLE; + } + + // see what kind of node we have + if (Text* textNode = Text::FromNode(aStart.Container())) { + // if the node is a chardata node, then delete chardata content + int32_t numToDel; + if (aStart == aEnd) { + numToDel = 1; + } else { + numToDel = *aEnd.Offset(RawRangeBoundary::OffsetFilter::kValidOffsets) - + *aStart.Offset(RawRangeBoundary::OffsetFilter::kValidOffsets); + MOZ_DIAGNOSTIC_ASSERT(numToDel > 0); + } + + RefPtr deleteTextTransaction = + DeleteTextTransaction::MaybeCreate( + *mEditorBase, *textNode, + *aStart.Offset(RawRangeBoundary::OffsetFilter::kValidOffsets), + numToDel); + // If the text node isn't editable, it should be never undone/redone. + // So, the transaction shouldn't be recorded. + if (!deleteTextTransaction) { + NS_WARNING("DeleteTextTransaction::MaybeCreate() failed"); + return NS_ERROR_FAILURE; + } + DebugOnly rvIgnored = AppendChild(deleteTextTransaction); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rvIgnored), + "DeleteRangeTransaction::AppendChild() failed, but ignored"); + return NS_OK; + } + + // Even if we detect invalid range, we should ignore it for removing + // specified range's nodes as far as possible. + // XXX This is super expensive. Probably, we should make + // DeleteNodeTransaction() can treat multiple siblings. + for (nsIContent* child = aStart.GetChildAtOffset(); + child && child != aEnd.GetChildAtOffset(); + child = child->GetNextSibling()) { + RefPtr deleteNodeTransaction = + DeleteNodeTransaction::MaybeCreate(*mEditorBase, *child); + // XXX This is odd handling. Even if some children are not editable, + // editor should append transactions because they could be editable + // at undoing/redoing. Additionally, if the transaction needs to + // delete/restore all nodes, it should at undoing/redoing. + if (deleteNodeTransaction) { + DebugOnly rvIgnored = AppendChild(deleteNodeTransaction); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rvIgnored), + "DeleteRangeTransaction::AppendChild() failed, but ignored"); + } + } + + return NS_OK; +} + +nsresult DeleteRangeTransaction::CreateTxnsToDeleteContent( + const RawRangeBoundary& aPoint, nsIEditor::EDirection aAction) { + if (NS_WARN_IF(!aPoint.IsSetAndValid())) { + return NS_ERROR_INVALID_ARG; + } + + if (NS_WARN_IF(!mEditorBase)) { + return NS_ERROR_NOT_AVAILABLE; + } + + Text* textNode = Text::FromNode(aPoint.Container()); + if (!textNode) { + return NS_OK; + } + + // If the node is a chardata node, then delete chardata content + uint32_t startOffset, numToDelete; + if (nsIEditor::eNext == aAction) { + startOffset = *aPoint.Offset(RawRangeBoundary::OffsetFilter::kValidOffsets); + numToDelete = aPoint.Container()->Length() - startOffset; + } else { + startOffset = 0; + numToDelete = *aPoint.Offset(RawRangeBoundary::OffsetFilter::kValidOffsets); + } + + if (!numToDelete) { + return NS_OK; + } + + RefPtr deleteTextTransaction = + DeleteTextTransaction::MaybeCreate(*mEditorBase, *textNode, startOffset, + numToDelete); + NS_WARNING_ASSERTION(deleteTextTransaction, + "DeleteTextTransaction::MaybeCreate() failed"); + // If the text node isn't editable, it should be never undone/redone. + // So, the transaction shouldn't be recorded. + if (!deleteTextTransaction) { + return NS_ERROR_FAILURE; + } + DebugOnly rvIgnored = AppendChild(deleteTextTransaction); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rvIgnored), + "DeleteRangeTransaction::AppendChild() failed, but ignored"); + return NS_OK; +} + +nsresult DeleteRangeTransaction::CreateTxnsToDeleteNodesBetween( + nsRange* aRangeToDelete) { + if (NS_WARN_IF(!mEditorBase)) { + return NS_ERROR_NOT_AVAILABLE; + } + + ContentSubtreeIterator subtreeIter; + nsresult rv = subtreeIter.Init(aRangeToDelete); + if (NS_FAILED(rv)) { + NS_WARNING("ContentSubtreeIterator::Init() failed"); + return rv; + } + + for (; !subtreeIter.IsDone(); subtreeIter.Next()) { + nsINode* node = subtreeIter.GetCurrentNode(); + if (NS_WARN_IF(!node) || NS_WARN_IF(!node->IsContent())) { + return NS_ERROR_FAILURE; + } + + RefPtr deleteNodeTransaction = + DeleteNodeTransaction::MaybeCreate(*mEditorBase, *node->AsContent()); + // XXX This is odd handling. Even if some nodes in the range are not + // editable, editor should append transactions because they could + // at undoing/redoing. Additionally, if the transaction needs to + // delete/restore all nodes, it should at undoing/redoing. + if (!deleteNodeTransaction) { + NS_WARNING("DeleteNodeTransaction::MaybeCreate() failed"); + return NS_ERROR_FAILURE; + } + DebugOnly rvIgnored = AppendChild(deleteNodeTransaction); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rvIgnored), + "DeleteRangeTransaction::AppendChild() failed, but ignored"); + } + return NS_OK; +} + +} // namespace mozilla diff --git a/editor/libeditor/DeleteRangeTransaction.h b/editor/libeditor/DeleteRangeTransaction.h new file mode 100644 index 0000000000..c7bce50014 --- /dev/null +++ b/editor/libeditor/DeleteRangeTransaction.h @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef DeleteRangeTransaction_h +#define DeleteRangeTransaction_h + +#include "EditAggregateTransaction.h" +#include "mozilla/RangeBoundary.h" +#include "nsCycleCollectionParticipant.h" +#include "nsID.h" +#include "nsIEditor.h" +#include "nsISupportsImpl.h" +#include "nsRange.h" +#include "nscore.h" + +class nsINode; + +namespace mozilla { + +class EditorBase; +class RangeUpdater; + +/** + * A transaction that deletes an entire range in the content tree + */ +class DeleteRangeTransaction final : public EditAggregateTransaction { + protected: + DeleteRangeTransaction(EditorBase& aEditorBase, + const nsRange& aRangeToDelete); + + public: + /** + * Creates a delete range transaction. This never returns nullptr. + * + * @param aEditorBase The object providing basic editing operations. + * @param aRangeToDelete The range to delete. + */ + static already_AddRefed Create( + EditorBase& aEditorBase, const nsRange& aRangeToDelete) { + RefPtr transaction = + new DeleteRangeTransaction(aEditorBase, aRangeToDelete); + return transaction.forget(); + } + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteRangeTransaction, + EditAggregateTransaction) + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; + + NS_DECL_EDITTRANSACTIONBASE + NS_DECL_EDITTRANSACTIONBASE_GETASMETHODS_OVERRIDE(DeleteRangeTransaction) + + MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction() override; + + protected: + /** + * CreateTxnsToDeleteBetween() creates a DeleteTextTransaction or some + * DeleteNodeTransactions to remove text or nodes between aStart and aEnd + * and appends the created transactions to the array. + * + * @param aStart Must be set and valid point. + * @param aEnd Must be set and valid point. Additionally, the + * container must be same as aStart's container. + * And of course, this must not be before aStart in + * the DOM tree order. + * @return Returns NS_OK in most cases. + * When the arguments are invalid, returns + * NS_ERROR_INVALID_ARG. + * When mEditorBase isn't available, returns + * NS_ERROR_NOT_AVAIALBLE. + * When created DeleteTextTransaction cannot do its + * transaction, returns NS_ERROR_FAILURE. + * Note that even if one of created DeleteNodeTransaction + * cannot do its transaction, this returns NS_OK. + */ + nsresult CreateTxnsToDeleteBetween(const RawRangeBoundary& aStart, + const RawRangeBoundary& aEnd); + + nsresult CreateTxnsToDeleteNodesBetween(nsRange* aRangeToDelete); + + /** + * CreateTxnsToDeleteContent() creates a DeleteTextTransaction to delete + * text between start of aPoint.GetContainer() and aPoint or aPoint and end of + * aPoint.GetContainer() and appends the created transaction to the array. + * + * @param aPoint Must be set and valid point. If the container is not + * a data node, this method does nothing. + * @param aAction If nsIEditor::eNext, this method creates a transaction + * to delete text from aPoint to the end of the data node. + * Otherwise, this method creates a transaction to delete + * text from start of the data node to aPoint. + * @return Returns NS_OK in most cases. + * When the arguments are invalid, returns + * NS_ERROR_INVALID_ARG. + * When mEditorBase isn't available, returns + * NS_ERROR_NOT_AVAIALBLE. + * When created DeleteTextTransaction cannot do its + * transaction, returns NS_ERROR_FAILURE. + * Note that even if no character will be deleted, + * this returns NS_OK. + */ + nsresult CreateTxnsToDeleteContent(const RawRangeBoundary& aPoint, + nsIEditor::EDirection aAction); + + // The editor for this transaction. + RefPtr mEditorBase; + + // P1 in the range. This is only non-null until DoTransaction is called and + // we convert it into child transactions. + RefPtr mRangeToDelete; +}; + +} // namespace mozilla + +#endif // #ifndef DeleteRangeTransaction_h diff --git a/editor/libeditor/DeleteTextTransaction.cpp b/editor/libeditor/DeleteTextTransaction.cpp new file mode 100644 index 0000000000..6e759db341 --- /dev/null +++ b/editor/libeditor/DeleteTextTransaction.cpp @@ -0,0 +1,154 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DeleteTextTransaction.h" + +#include "HTMLEditUtils.h" +#include "mozilla/Assertions.h" +#include "mozilla/EditorBase.h" +#include "mozilla/EditorDOMPoint.h" +#include "mozilla/SelectionState.h" +#include "mozilla/dom/Selection.h" +#include "nsDebug.h" +#include "nsError.h" +#include "nsISupportsImpl.h" +#include "nsAString.h" + +namespace mozilla { + +using namespace dom; + +// static +already_AddRefed DeleteTextTransaction::MaybeCreate( + EditorBase& aEditorBase, Text& aTextNode, uint32_t aOffset, + uint32_t aLengthToDelete) { + RefPtr transaction = new DeleteTextTransaction( + aEditorBase, aTextNode, aOffset, aLengthToDelete); + return transaction.forget(); +} + +// static +already_AddRefed +DeleteTextTransaction::MaybeCreateForPreviousCharacter(EditorBase& aEditorBase, + Text& aTextNode, + uint32_t aOffset) { + if (NS_WARN_IF(!aOffset)) { + return nullptr; + } + + nsAutoString data; + aTextNode.GetData(data); + if (NS_WARN_IF(data.IsEmpty())) { + return nullptr; + } + + uint32_t length = 1; + uint32_t offset = aOffset - 1; + if (offset && NS_IS_SURROGATE_PAIR(data[offset - 1], data[offset])) { + ++length; + --offset; + } + return DeleteTextTransaction::MaybeCreate(aEditorBase, aTextNode, offset, + length); +} + +// static +already_AddRefed +DeleteTextTransaction::MaybeCreateForNextCharacter(EditorBase& aEditorBase, + Text& aTextNode, + uint32_t aOffset) { + nsAutoString data; + aTextNode.GetData(data); + if (NS_WARN_IF(aOffset >= data.Length()) || NS_WARN_IF(data.IsEmpty())) { + return nullptr; + } + + uint32_t length = 1; + if (aOffset + 1 < data.Length() && + NS_IS_SURROGATE_PAIR(data[aOffset], data[aOffset + 1])) { + ++length; + } + return DeleteTextTransaction::MaybeCreate(aEditorBase, aTextNode, aOffset, + length); +} + +DeleteTextTransaction::DeleteTextTransaction(EditorBase& aEditorBase, + Text& aTextNode, uint32_t aOffset, + uint32_t aLengthToDelete) + : mEditorBase(&aEditorBase), + mTextNode(&aTextNode), + mOffset(aOffset), + mLengthToDelete(aLengthToDelete) { + NS_ASSERTION(mTextNode->Length() >= aOffset + aLengthToDelete, + "Trying to delete more characters than in node"); +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteTextTransaction, EditTransactionBase, + mEditorBase, mTextNode) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteTextTransaction) +NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase) + +bool DeleteTextTransaction::CanDoIt() const { + if (NS_WARN_IF(!mTextNode) || NS_WARN_IF(!mEditorBase)) { + return false; + } + return mEditorBase->IsTextEditor() || + HTMLEditUtils::IsSimplyEditableNode(*mTextNode); +} + +NS_IMETHODIMP DeleteTextTransaction::DoTransaction() { + if (NS_WARN_IF(!CanDoIt())) { + return NS_ERROR_NOT_AVAILABLE; + } + + // Get the text that we're about to delete + ErrorResult error; + mTextNode->SubstringData(mOffset, mLengthToDelete, mDeletedText, error); + if (error.Failed()) { + NS_WARNING("Text::SubstringData() failed"); + return error.StealNSResult(); + } + + OwningNonNull editorBase = *mEditorBase; + OwningNonNull textNode = *mTextNode; + editorBase->DoDeleteText(textNode, mOffset, mLengthToDelete, error); + if (error.Failed()) { + NS_WARNING("EditorBase::DoDeleteText() failed"); + return error.StealNSResult(); + } + + editorBase->RangeUpdaterRef().SelAdjDeleteText(textNode, mOffset, + mLengthToDelete); + + if (!editorBase->AllowsTransactionsToChangeSelection()) { + return NS_OK; + } + + RefPtr selection = editorBase->GetSelection(); + if (NS_WARN_IF(!selection)) { + return NS_ERROR_FAILURE; + } + selection->CollapseInLimiter(EditorRawDOMPoint(textNode, mOffset), error); + NS_WARNING_ASSERTION(!error.Failed(), + "Selection::CollapseInLimiter() failed"); + return error.StealNSResult(); +} + +// XXX: We may want to store the selection state and restore it properly. Was +// it an insertion point or an extended selection? +NS_IMETHODIMP DeleteTextTransaction::UndoTransaction() { + if (NS_WARN_IF(!CanDoIt())) { + return NS_ERROR_NOT_AVAILABLE; + } + RefPtr editorBase = mEditorBase; + RefPtr textNode = mTextNode; + ErrorResult error; + editorBase->DoInsertText(*textNode, mOffset, mDeletedText, error); + NS_WARNING_ASSERTION(!error.Failed(), "EditorBase::DoInsertText() failed"); + return error.StealNSResult(); +} + +} // namespace mozilla diff --git a/editor/libeditor/DeleteTextTransaction.h b/editor/libeditor/DeleteTextTransaction.h new file mode 100644 index 0000000000..0e78eb0a5d --- /dev/null +++ b/editor/libeditor/DeleteTextTransaction.h @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef DeleteTextTransaction_h +#define DeleteTextTransaction_h + +#include "mozilla/EditTransactionBase.h" +#include "mozilla/dom/Text.h" +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsID.h" +#include "nsString.h" +#include "nscore.h" + +namespace mozilla { + +class EditorBase; +class RangeUpdater; + +/** + * A transaction that removes text from a content node. + */ +class DeleteTextTransaction final : public EditTransactionBase { + protected: + DeleteTextTransaction(EditorBase& aEditorBase, dom::Text& aTextNode, + uint32_t aOffset, uint32_t aLengthToDelete); + + public: + /** + * Creates a delete text transaction to remove given range. This returns + * nullptr if it cannot modify the text node. + * + * @param aEditorBase The provider of basic editing operations. + * @param aTextNode The content node to remove text from. + * @param aOffset The location in aElement to begin the deletion. + * @param aLenthToDelete The length to delete. + */ + static already_AddRefed MaybeCreate( + EditorBase& aEditorBase, dom::Text& aTextNode, uint32_t aOffset, + uint32_t aLengthToDelete); + + /** + * Creates a delete text transaction to remove a previous or next character. + * Those methods MAY return nullptr. + * + * @param aEditorBase The provider of basic editing operations. + * @param aTextNode The content node to remove text from. + * @param aOffset The location in aElement to begin the deletion. + */ + static already_AddRefed + MaybeCreateForPreviousCharacter(EditorBase& aEditorBase, dom::Text& aTextNode, + uint32_t aOffset); + static already_AddRefed MaybeCreateForNextCharacter( + EditorBase& aEditorBase, dom::Text& aTextNode, uint32_t aOffset); + + /** + * CanDoIt() returns true if there are enough members and can modify the + * text. Otherwise, false. + */ + bool CanDoIt() const; + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteTextTransaction, + EditTransactionBase) + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; + + NS_DECL_EDITTRANSACTIONBASE + NS_DECL_EDITTRANSACTIONBASE_GETASMETHODS_OVERRIDE(DeleteTextTransaction) + + dom::Text* GetText() const { return mTextNode; } + uint32_t Offset() const { return mOffset; } + uint32_t LengthToDelete() const { return mLengthToDelete; } + + protected: + // The provider of basic editing operations. + RefPtr mEditorBase; + + // The CharacterData node to operate upon. + RefPtr mTextNode; + + // The offset into mTextNode where the deletion is to take place. + uint32_t mOffset; + + // The length to delete. + uint32_t mLengthToDelete; + + // The text that was deleted. + nsString mDeletedText; +}; + +} // namespace mozilla + +#endif // #ifndef DeleteTextTransaction_h diff --git a/editor/libeditor/EditAction.h b/editor/libeditor/EditAction.h new file mode 100644 index 0000000000..0bb2752ae3 --- /dev/null +++ b/editor/libeditor/EditAction.h @@ -0,0 +1,784 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_EditAction_h +#define mozilla_EditAction_h + +#include "mozilla/EventForwards.h" +#include "mozilla/StaticPrefs_dom.h" + +namespace mozilla { + +/** + * EditAction indicates which operation or command causes running the methods + * of editors. + */ +enum class EditAction { + // eNone indicates no edit action is being handled. + eNone, + + // eNotEditing indicates that something is retrieved or initializing + // something at creating, destroying or focus move etc, i.e., not edit + // action is being handled but editor is doing something. + eNotEditing, + + // eInsertText indicates to insert some characters. + eInsertText, + + // eInsertParagraphSeparator indicates to insert a paragraph separator such + // as

,

. + eInsertParagraphSeparator, + + // eInsertLineBreak indicates to insert \n into TextEditor or a
element + // in HTMLEditor. + eInsertLineBreak, + + // eDeleteSelection indicates to delete selected content or content around + // caret if selection is collapsed. + eDeleteSelection, + + // eDeleteBackward indicates to remove previous character element of caret. + // This may be set even when Selection is not collapsed. + eDeleteBackward, + + // eDeleteForward indicates to remove next character or element of caret. + // This may be set even when Selection is not collapsed. + eDeleteForward, + + // eDeleteWordBackward indicates to remove previous word. If caret is in + // a word, remove characters between word start and caret. + // This may be set even when Selection is not collapsed. + eDeleteWordBackward, + + // eDeleteWordForward indicates to remove next word. If caret is in a + // word, remove characters between caret and word end. + // This may be set even when Selection is not collapsed. + eDeleteWordForward, + + // eDeleteToBeginningOfSoftLine indicates to remove characters between + // caret and previous visual line break. + // This may be set even when Selection is not collapsed. + eDeleteToBeginningOfSoftLine, + + // eDeleteToEndOfSoftLine indicates to remove characters between caret and + // next visual line break. + // This may be set even when Selection is not collapsed. + eDeleteToEndOfSoftLine, + + // eDeleteByDrag indicates to remove selection by dragging the content + // to different place. + eDeleteByDrag, + + // eStartComposition indicates that user starts composition. + eStartComposition, + + // eUpdateComposition indicates that user updates composition with + // new non-empty composition string and IME selections. + eUpdateComposition, + + // eCommitComposition indicates that user commits composition. + eCommitComposition, + + // eCancelComposition indicates that user cancels composition. + eCancelComposition, + + // eDeleteByComposition indicates that user starts composition with + // empty string and there was selected content. + eDeleteByComposition, + + // eUndo/eRedo indicate to undo/redo a transaction. + eUndo, + eRedo, + + // eSetTextDirection indicates that setting text direction (LTR or RTL). + eSetTextDirection, + + // eCut indicates to delete selected content and copy it to the clipboard. + eCut, + + // eCopy indicates to copy selected content to the clipboard. + eCopy, + + // ePaste indicates to paste clipboard data. + ePaste, + + // ePasteAsQuotation indicates to paste clipboard data as quotation. + ePasteAsQuotation, + + // eDrop indicates that user drops dragging item into the editor. + eDrop, + + // eIndent indicates that to indent selected line(s). + eIndent, + + // eOutdent indicates that to outdent selected line(s). + eOutdent, + + // eReplaceText indicates to replace a part of range in editor with + // specific text. For example, user select a correct word in suggestions + // of spellchecker or a suggestion in list of autocomplete. + eReplaceText, + + // eInsertTableRowElement indicates to insert table rows (i.e., + // elements). + eInsertTableRowElement, + + // eRemoveTableRowElement indicates to remove table row elements. + eRemoveTableRowElement, + + // eInsertTableColumn indicates to insert cell elements to each row. + eInsertTableColumn, + + // eRemoveTableColumn indicates to remove cell elements from each row. + eRemoveTableColumn, + + // eResizingElement indicates that user starts to resize or keep resizing + // with dragging a resizer which is provided by Gecko. + eResizingElement, + + // eResizeElement indicates that user resizes an element size with finishing + // dragging a resizer which is provided by Gecko. + eResizeElement, + + // eMovingElement indicates that user starts to move or keep moving an + // element with grabber which is provided by Gecko. + eMovingElement, + + // eMoveElement indicates that user finishes moving an element with grabber + // which is provided by Gecko. + eMoveElement, + + // The following edit actions are not user's operation. They are caused + // by if UI does something or web apps does something with JS. + + // eUnknown indicates some special edit actions, e.g., batching of some + // nsI*Editor method calls. This shouldn't be set while handling a user + // operation. + eUnknown, + + // eSetAttribute indicates to set attribute value of an element node. + eSetAttribute, + + // eRemoveAttribute indicates to remove attribute from an element node. + eRemoveAttribute, + + // eInsertNode indicates to insert a node into the tree. + eInsertNode, + + // eDeleteNode indicates to remove a node form the tree. + eRemoveNode, + + // eInsertBlockElement indicates to insert a block-level element like
, + //
, 
  • ,
    etc. + eInsertBlockElement, + + // eInsertHorizontalRuleElement indicates to insert a
    element. + eInsertHorizontalRuleElement, + + // eInsertLinkElement indicates to insert an anchor element which has + // href attribute. + eInsertLinkElement, + + // eInsertUnorderedListElement and eInsertOrderedListElement indicate to + // insert
      or
        element. + eInsertUnorderedListElement, + eInsertOrderedListElement, + + // eRemoveUnorderedListElement and eRemoveOrderedListElement indicate to + // remove
          or
            element. + eRemoveUnorderedListElement, + eRemoveOrderedListElement, + + // eRemoveListElement indicates to remove
              ,
                and/or
                element. + eRemoveListElement, + + // eInsertBlockquoteElement indicates to insert a
                element. + eInsertBlockquoteElement, + + // eNormalizeTable indicates to normalize table. E.g., if a row does + // not have enough number of cells, inserts empty cells. + eNormalizeTable, + + // eRemoveTableElement indicates to remove element. + eRemoveTableElement, + + // eRemoveTableCellContents indicates to remove any children in a table + // cell element. + eDeleteTableCellContents, + + // eInsertTableCellElement indicates to insert table cell elements (i.e., + //
                or ). + eInsertTableCellElement, + + // eRemoveTableCellEelement indicates to remove table cell elements. + eRemoveTableCellElement, + + // eJoinTableCellElements indicates to join table cell elements. + eJoinTableCellElements, + + // eSplitTableCellElement indicates to split table cell elements. + eSplitTableCellElement, + + // eSetTableCellElementType indicates to set table cell element type to + // or . + eSetTableCellElementType, + + // eSetInlineStyleProperty indicates to set CSS another inline style property + // which is not defined below. + eSetInlineStyleProperty, + + // eRemoveInlineStyleProperty indicates to remove a CSS text property which + // is not defined below. + eRemoveInlineStyleProperty, + + // or font-weight. + eSetFontWeightProperty, + eRemoveFontWeightProperty, + + // or text-style: italic/oblique. + eSetTextStyleProperty, + eRemoveTextStyleProperty, + + // or text-decoration: underline. + eSetTextDecorationPropertyUnderline, + eRemoveTextDecorationPropertyUnderline, + + // or text-decoration: line-through. + eSetTextDecorationPropertyLineThrough, + eRemoveTextDecorationPropertyLineThrough, + + // or text-align: super. + eSetVerticalAlignPropertySuper, + eRemoveVerticalAlignPropertySuper, + + // or text-align: sub. + eSetVerticalAlignPropertySub, + eRemoveVerticalAlignPropertySub, + + // or font-family. + eSetFontFamilyProperty, + eRemoveFontFamilyProperty, + + // or color. + eSetColorProperty, + eRemoveColorProperty, + + // + eSetBackgroundColorPropertyInline, + eRemoveBackgroundColorPropertyInline, + + // eRemoveAllInlineStyleProperties indicates to remove all CSS inline + // style properties. + eRemoveAllInlineStyleProperties, + + // eIncrementFontSize indicates to increment font-size. + eIncrementFontSize, + + // eDecrementFontSize indicates to decrement font-size. + eDecrementFontSize, + + // eSetAlignment indicates to set alignment of selected content but different + // from the following. + eSetAlignment, + + // eAlign* and eJustify indicates to align contents in block with left + // edge, right edge, center or justify the text. + eAlignLeft, + eAlignRight, + eAlignCenter, + eJustify, + + // eSetBackgroundColor indicates to set background color. + eSetBackgroundColor, + + // eSetPositionToAbsoluteOrStatic indicates to set position property value + // to "absolute" or "static". + eSetPositionToAbsoluteOrStatic, + + // eIncreaseOrDecreaseZIndex indicates to change z-index of an element. + eIncreaseOrDecreaseZIndex, + + // eEnableOrDisableCSS indicates to enable or disable CSS mode of HTMLEditor. + eEnableOrDisableCSS, + + // eEnableOrDisableAbsolutePositionEditor indicates to enable or disable + // absolute positioned element editing UI. + eEnableOrDisableAbsolutePositionEditor, + + // eEnableOrDisableResizer indicates to enable or disable resizers of + // , and absolutely positioned element. + eEnableOrDisableResizer, + + // eEnableOrDisableInlineTableEditingUI indicates to enable or disable + // inline table editing UI. + eEnableOrDisableInlineTableEditingUI, + + // eSetCharacterSet indicates to set character-set of the document. + eSetCharacterSet, + + // eSetWrapWidth indicates to set wrap width. + eSetWrapWidth, + + // eRewrap indicates to rewrap for current wrap width. + eRewrap, + + // eSetText indicates to set new text of TextEditor, e.g., setting + // HTMLInputElement.value. + eSetText, + + // eSetHTML indicates to set body of HTMLEditor. + eSetHTML, + + // eInsertHTML indicates to insert HTML source code. + eInsertHTML, + + // eHidePassword indicates that editor hides password with mask characters. + eHidePassword, + + // eCreatePaddingBRElementForEmptyEditor indicates that editor wants to + // create a padding
                element for empty editor after it modifies its + // content. + eCreatePaddingBRElementForEmptyEditor, +}; + +// This is int32_t instead of int16_t because nsIInlineSpellChecker.idl's +// spellCheckAfterEditorChange is defined to take it as a long. +// TODO: Make each name eFoo and investigate whether the numeric values +// still have some meaning. +enum class EditSubAction : int32_t { + // eNone indicates not edit sub-action is being handled. This is useful + // of initial value of member variables. + eNone, + + // eUndo and eRedo indicate entire actions of undo/redo operation. + eUndo, + eRedo, + + // eInsertNode indicates to insert a new node into the DOM tree. + eInsertNode, + + // eCreateNode indicates to create a new node and insert it into the DOM tree. + eCreateNode, + + // eDeleteNode indicates to remove a node from the DOM tree. + eDeleteNode, + + // eSplitNode indicates to split a node to 2 nodes. + eSplitNode, + + // eJoinNodes indicates to join 2 nodes. + eJoinNodes, + + // eDeleteText indicates to delete some characters form a text node. + eDeleteText, + + // eInsertText indicates to insert some characters. + eInsertText, + + // eInsertTextComingFromIME indicates to insert or update composition string + // with new text which is new composition string or commit string. + eInsertTextComingFromIME, + + // eDeleteSelectedContent indicates to remove selected content. + eDeleteSelectedContent, + + // eSetTextProperty indicates to set a style from text. + eSetTextProperty, + + // eRemoveTextProperty indicates to remove a style from text. + eRemoveTextProperty, + + // eRemoveAllTextProperties indicate to remove all styles from text. + eRemoveAllTextProperties, + + // eComputeTextToOutput indicates to compute the editor value as plain text + // or something requested format. + eComputeTextToOutput, + + // eSetText indicates to set editor value to new value. + eSetText, + + // eInsertLineBreak indicates to insert a line break,
                or \n to break + // current line. + eInsertLineBreak, + + // eInsertParagraphSeparator indicates to insert paragraph separator,
                or + // \n at least to break current line in HTMLEditor. + eInsertParagraphSeparator, + + // eCreateOrChangeList indicates to create new list or change existing list + // type. + eCreateOrChangeList, + + // eIndent and eOutdent indicates to indent or outdent the target with + // using
                ,
                  ,
                    or just margin of start edge. + eIndent, + eOutdent, + + // eSetOrClearAlignment aligns content or clears alignment with align + // attribute or text-align. + eSetOrClearAlignment, + + // eCreateOrRemoveBlock creates new block or removes existing block and + // move its descendants to where the block was. + eCreateOrRemoveBlock, + + // eMergeBlockContents is not an actual sub-action, but this is used by + // HTMLEditor::MoveBlock() to request special handling in + // HTMLEditor::SplitInlinesAndCollectEditTargetNodesInOneHardLine(). + eMergeBlockContents, + + // eRemoveList removes specific type of list but keep its content. + eRemoveList, + + // eCreateOrChangeDefinitionListItem indicates to format current hard line(s) + // `
                    ` or `
                    `. This may cause creating or changing existing list + // element to new `
                    ` element. + eCreateOrChangeDefinitionListItem, + + // eInsertElement indicates to insert an element. + eInsertElement, + + // eInsertQuotation indicates to insert an element and make it "quoted text". + eInsertQuotation, + + // eInsertQuotedText indicates to insert text which has already been quoted. + eInsertQuotedText, + + // ePasteHTMLContent indicates to paste HTML content in clipboard. + ePasteHTMLContent, + + // eInsertHTMLSource indicates to create a document fragment from given HTML + // source and insert into the DOM tree. So, this is similar to innerHTML. + eInsertHTMLSource, + + // eReplaceHeadWithHTMLSource indicates to create a document fragment from + // given HTML source and replace content of with it. + eReplaceHeadWithHTMLSource, + + // eSetPositionToAbsolute and eSetPositionToStatic indicates to set position + // property to absolute or static. + eSetPositionToAbsolute, + eSetPositionToStatic, + + // eDecreaseZIndex and eIncreaseZIndex indicate to decrease and increase + // z-index value. + eDecreaseZIndex, + eIncreaseZIndex, + + // eCreatePaddingBRElementForEmptyEditor indicates to create a padding
                    + // element for empty editor. + eCreatePaddingBRElementForEmptyEditor, +}; + +inline EditorInputType ToInputType(EditAction aEditAction) { + switch (aEditAction) { + case EditAction::eInsertText: + return EditorInputType::eInsertText; + case EditAction::eReplaceText: + return EditorInputType::eInsertReplacementText; + case EditAction::eInsertLineBreak: + return EditorInputType::eInsertLineBreak; + case EditAction::eInsertParagraphSeparator: + return EditorInputType::eInsertParagraph; + case EditAction::eInsertOrderedListElement: + case EditAction::eRemoveOrderedListElement: + return EditorInputType::eInsertOrderedList; + case EditAction::eInsertUnorderedListElement: + case EditAction::eRemoveUnorderedListElement: + return EditorInputType::eInsertUnorderedList; + case EditAction::eInsertHorizontalRuleElement: + return EditorInputType::eInsertHorizontalRule; + case EditAction::eDrop: + return EditorInputType::eInsertFromDrop; + case EditAction::ePaste: + return EditorInputType::eInsertFromPaste; + case EditAction::ePasteAsQuotation: + return EditorInputType::eInsertFromPasteAsQuotation; + case EditAction::eUpdateComposition: + return EditorInputType::eInsertCompositionText; + case EditAction::eCommitComposition: + if (StaticPrefs::dom_input_events_conform_to_level_1()) { + return EditorInputType::eInsertCompositionText; + } + return EditorInputType::eInsertFromComposition; + case EditAction::eCancelComposition: + if (StaticPrefs::dom_input_events_conform_to_level_1()) { + return EditorInputType::eInsertCompositionText; + } + return EditorInputType::eDeleteCompositionText; + case EditAction::eDeleteByComposition: + if (StaticPrefs::dom_input_events_conform_to_level_1()) { + // XXX Or EditorInputType::eDeleteContent? I don't know which IME may + // causes this situation. + return EditorInputType::eInsertCompositionText; + } + return EditorInputType::eDeleteByComposition; + case EditAction::eInsertLinkElement: + return EditorInputType::eInsertLink; + case EditAction::eDeleteWordBackward: + return EditorInputType::eDeleteWordBackward; + case EditAction::eDeleteWordForward: + return EditorInputType::eDeleteWordForward; + case EditAction::eDeleteToBeginningOfSoftLine: + return EditorInputType::eDeleteSoftLineBackward; + case EditAction::eDeleteToEndOfSoftLine: + return EditorInputType::eDeleteSoftLineForward; + case EditAction::eDeleteByDrag: + return EditorInputType::eDeleteByDrag; + case EditAction::eCut: + return EditorInputType::eDeleteByCut; + case EditAction::eDeleteSelection: + case EditAction::eRemoveTableRowElement: + case EditAction::eRemoveTableColumn: + case EditAction::eRemoveTableElement: + case EditAction::eDeleteTableCellContents: + case EditAction::eRemoveTableCellElement: + return EditorInputType::eDeleteContent; + case EditAction::eDeleteBackward: + return EditorInputType::eDeleteContentBackward; + case EditAction::eDeleteForward: + return EditorInputType::eDeleteContentForward; + case EditAction::eUndo: + return EditorInputType::eHistoryUndo; + case EditAction::eRedo: + return EditorInputType::eHistoryRedo; + case EditAction::eSetFontWeightProperty: + case EditAction::eRemoveFontWeightProperty: + return EditorInputType::eFormatBold; + case EditAction::eSetTextStyleProperty: + case EditAction::eRemoveTextStyleProperty: + return EditorInputType::eFormatItalic; + case EditAction::eSetTextDecorationPropertyUnderline: + case EditAction::eRemoveTextDecorationPropertyUnderline: + return EditorInputType::eFormatUnderline; + case EditAction::eSetTextDecorationPropertyLineThrough: + case EditAction::eRemoveTextDecorationPropertyLineThrough: + return EditorInputType::eFormatStrikeThrough; + case EditAction::eSetVerticalAlignPropertySuper: + case EditAction::eRemoveVerticalAlignPropertySuper: + return EditorInputType::eFormatSuperscript; + case EditAction::eSetVerticalAlignPropertySub: + case EditAction::eRemoveVerticalAlignPropertySub: + return EditorInputType::eFormatSubscript; + case EditAction::eJustify: + return EditorInputType::eFormatJustifyFull; + case EditAction::eAlignCenter: + return EditorInputType::eFormatJustifyCenter; + case EditAction::eAlignRight: + return EditorInputType::eFormatJustifyRight; + case EditAction::eAlignLeft: + return EditorInputType::eFormatJustifyLeft; + case EditAction::eIndent: + return EditorInputType::eFormatIndent; + case EditAction::eOutdent: + return EditorInputType::eFormatOutdent; + case EditAction::eRemoveAllInlineStyleProperties: + return EditorInputType::eFormatRemove; + case EditAction::eSetTextDirection: + return EditorInputType::eFormatSetBlockTextDirection; + case EditAction::eSetBackgroundColorPropertyInline: + case EditAction::eRemoveBackgroundColorPropertyInline: + return EditorInputType::eFormatBackColor; + case EditAction::eSetColorProperty: + case EditAction::eRemoveColorProperty: + return EditorInputType::eFormatFontColor; + case EditAction::eSetFontFamilyProperty: + case EditAction::eRemoveFontFamilyProperty: + return EditorInputType::eFormatFontName; + default: + return EditorInputType::eUnknown; + } +} + +inline bool MayEditActionDeleteAroundCollapsedSelection( + const EditAction aEditAction) { + switch (aEditAction) { + case EditAction::eDeleteSelection: + case EditAction::eDeleteBackward: + case EditAction::eDeleteForward: + case EditAction::eDeleteWordBackward: + case EditAction::eDeleteWordForward: + case EditAction::eDeleteToBeginningOfSoftLine: + case EditAction::eDeleteToEndOfSoftLine: + return true; + default: + return false; + } +} + +inline bool IsEditActionTableEditing(const EditAction aEditAction) { + switch (aEditAction) { + case EditAction::eInsertTableRowElement: + case EditAction::eRemoveTableRowElement: + case EditAction::eInsertTableColumn: + case EditAction::eRemoveTableColumn: + case EditAction::eRemoveTableElement: + case EditAction::eRemoveTableCellElement: + case EditAction::eDeleteTableCellContents: + case EditAction::eInsertTableCellElement: + case EditAction::eJoinTableCellElements: + case EditAction::eSplitTableCellElement: + case EditAction::eSetTableCellElementType: + return true; + default: + return false; + } +} + +inline bool MayEditActionDeleteSelection(const EditAction aEditAction) { + switch (aEditAction) { + case EditAction::eNone: + case EditAction::eNotEditing: + return false; + + // EditActions modifying around selection. + case EditAction::eInsertText: + case EditAction::eInsertParagraphSeparator: + case EditAction::eInsertLineBreak: + case EditAction::eDeleteSelection: + case EditAction::eDeleteBackward: + case EditAction::eDeleteForward: + case EditAction::eDeleteWordBackward: + case EditAction::eDeleteWordForward: + case EditAction::eDeleteToBeginningOfSoftLine: + case EditAction::eDeleteToEndOfSoftLine: + case EditAction::eDeleteByDrag: + return true; + + case EditAction::eStartComposition: + return false; + + case EditAction::eUpdateComposition: + case EditAction::eCommitComposition: + case EditAction::eCancelComposition: + case EditAction::eDeleteByComposition: + return true; + + case EditAction::eUndo: + case EditAction::eRedo: + case EditAction::eSetTextDirection: + return false; + + case EditAction::eCut: + return true; + + case EditAction::eCopy: + return false; + + case EditAction::ePaste: + case EditAction::ePasteAsQuotation: + return true; + + case EditAction::eDrop: + return false; // Not deleting selection at drop. + + // EditActions changing format around selection. + case EditAction::eIndent: + case EditAction::eOutdent: + return false; + + // EditActions inserting or deleting something at specified position. + case EditAction::eInsertTableRowElement: + case EditAction::eRemoveTableRowElement: + case EditAction::eInsertTableColumn: + case EditAction::eRemoveTableColumn: + case EditAction::eResizingElement: + case EditAction::eResizeElement: + case EditAction::eMovingElement: + case EditAction::eMoveElement: + case EditAction::eUnknown: + case EditAction::eSetAttribute: + case EditAction::eRemoveAttribute: + case EditAction::eRemoveNode: + case EditAction::eInsertBlockElement: + return false; + + // EditActions inserting someting around selection or replacing selection + // with something. + case EditAction::eReplaceText: + case EditAction::eInsertNode: + case EditAction::eInsertHorizontalRuleElement: + return true; + + // EditActions chaning format around selection or inserting or deleting + // something at specific position. + case EditAction::eInsertLinkElement: + case EditAction::eInsertUnorderedListElement: + case EditAction::eInsertOrderedListElement: + case EditAction::eRemoveUnorderedListElement: + case EditAction::eRemoveOrderedListElement: + case EditAction::eRemoveListElement: + case EditAction::eInsertBlockquoteElement: + case EditAction::eNormalizeTable: + case EditAction::eRemoveTableElement: + case EditAction::eRemoveTableCellElement: + case EditAction::eDeleteTableCellContents: + case EditAction::eInsertTableCellElement: + case EditAction::eJoinTableCellElements: + case EditAction::eSplitTableCellElement: + case EditAction::eSetTableCellElementType: + case EditAction::eSetInlineStyleProperty: + case EditAction::eRemoveInlineStyleProperty: + case EditAction::eSetFontWeightProperty: + case EditAction::eRemoveFontWeightProperty: + case EditAction::eSetTextStyleProperty: + case EditAction::eRemoveTextStyleProperty: + case EditAction::eSetTextDecorationPropertyUnderline: + case EditAction::eRemoveTextDecorationPropertyUnderline: + case EditAction::eSetTextDecorationPropertyLineThrough: + case EditAction::eRemoveTextDecorationPropertyLineThrough: + case EditAction::eSetVerticalAlignPropertySuper: + case EditAction::eRemoveVerticalAlignPropertySuper: + case EditAction::eSetVerticalAlignPropertySub: + case EditAction::eRemoveVerticalAlignPropertySub: + case EditAction::eSetFontFamilyProperty: + case EditAction::eRemoveFontFamilyProperty: + case EditAction::eSetColorProperty: + case EditAction::eRemoveColorProperty: + case EditAction::eSetBackgroundColorPropertyInline: + case EditAction::eRemoveBackgroundColorPropertyInline: + case EditAction::eRemoveAllInlineStyleProperties: + case EditAction::eIncrementFontSize: + case EditAction::eDecrementFontSize: + case EditAction::eSetAlignment: + case EditAction::eAlignLeft: + case EditAction::eAlignRight: + case EditAction::eAlignCenter: + case EditAction::eJustify: + case EditAction::eSetBackgroundColor: + case EditAction::eSetPositionToAbsoluteOrStatic: + case EditAction::eIncreaseOrDecreaseZIndex: + return false; + + // EditActions controlling editor feature or state. + case EditAction::eEnableOrDisableCSS: + case EditAction::eEnableOrDisableAbsolutePositionEditor: + case EditAction::eEnableOrDisableResizer: + case EditAction::eEnableOrDisableInlineTableEditingUI: + case EditAction::eSetCharacterSet: + case EditAction::eSetWrapWidth: + return false; + + case EditAction::eRewrap: + case EditAction::eSetText: + case EditAction::eSetHTML: + case EditAction::eInsertHTML: + return true; + + case EditAction::eHidePassword: + case EditAction::eCreatePaddingBRElementForEmptyEditor: + return false; + } + return false; +} + +} // namespace mozilla + +inline bool operator!(const mozilla::EditSubAction& aEditSubAction) { + return aEditSubAction == mozilla::EditSubAction::eNone; +} + +#endif // #ifdef mozilla_EditAction_h diff --git a/editor/libeditor/EditActionListener.h b/editor/libeditor/EditActionListener.h new file mode 100644 index 0000000000..0d814314e1 --- /dev/null +++ b/editor/libeditor/EditActionListener.h @@ -0,0 +1,14 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __editActionListener_h__ +#define __editActionListener_h__ + +class EditActionListener { + public: + virtual void EditAction() = 0; +}; + +#endif /* __editActionListener_h__ */ diff --git a/editor/libeditor/EditAggregateTransaction.cpp b/editor/libeditor/EditAggregateTransaction.cpp new file mode 100644 index 0000000000..c940bcca1f --- /dev/null +++ b/editor/libeditor/EditAggregateTransaction.cpp @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "EditAggregateTransaction.h" +#include "mozilla/ReverseIterator.h" // for Reversed +#include "nsAString.h" +#include "nsCOMPtr.h" // for nsCOMPtr +#include "nsError.h" // for NS_OK, etc. +#include "nsISupportsUtils.h" // for NS_ADDREF +#include "nsString.h" // for nsAutoString + +namespace mozilla { + +NS_IMPL_CYCLE_COLLECTION_INHERITED(EditAggregateTransaction, + EditTransactionBase, mChildren) + +NS_IMPL_ADDREF_INHERITED(EditAggregateTransaction, EditTransactionBase) +NS_IMPL_RELEASE_INHERITED(EditAggregateTransaction, EditTransactionBase) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditAggregateTransaction) +NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase) + +NS_IMETHODIMP EditAggregateTransaction::DoTransaction() { + // FYI: It's legal (but not very useful) to have an empty child list. + for (const OwningNonNull& childTransaction : + CopyableAutoTArray, 10>(mChildren)) { + nsresult rv = MOZ_KnownLive(childTransaction)->DoTransaction(); + if (NS_FAILED(rv)) { + NS_WARNING("EditTransactionBase::DoTransaction() failed"); + return rv; + } + } + return NS_OK; +} + +NS_IMETHODIMP EditAggregateTransaction::UndoTransaction() { + // FYI: It's legal (but not very useful) to have an empty child list. + // Undo goes through children backwards. + const CopyableAutoTArray, 10> children( + mChildren); + for (const OwningNonNull& childTransaction : + Reversed(children)) { + nsresult rv = MOZ_KnownLive(childTransaction)->UndoTransaction(); + if (NS_FAILED(rv)) { + NS_WARNING("EditTransactionBase::UndoTransaction() failed"); + return rv; + } + } + return NS_OK; +} + +NS_IMETHODIMP EditAggregateTransaction::RedoTransaction() { + // It's legal (but not very useful) to have an empty child list. + const CopyableAutoTArray, 10> children( + mChildren); + for (const OwningNonNull& childTransaction : children) { + nsresult rv = MOZ_KnownLive(childTransaction)->RedoTransaction(); + if (NS_FAILED(rv)) { + NS_WARNING("EditTransactionBase::RedoTransaction() failed"); + return rv; + } + } + return NS_OK; +} + +NS_IMETHODIMP EditAggregateTransaction::Merge(nsITransaction* aOtherTransaction, + bool* aDidMerge) { + if (aDidMerge) { + *aDidMerge = false; + } + if (mChildren.IsEmpty()) { + return NS_OK; + } + // FIXME: Is this really intended not to loop? It looks like the code + // that used to be here sort of intended to loop, but didn't. + return mChildren[0]->Merge(aOtherTransaction, aDidMerge); +} + +NS_IMETHODIMP EditAggregateTransaction::AppendChild( + EditTransactionBase* aTransaction) { + if (NS_WARN_IF(!aTransaction)) { + return NS_ERROR_INVALID_ARG; + } + + mChildren.AppendElement(*aTransaction); + return NS_OK; +} + +NS_IMETHODIMP EditAggregateTransaction::GetName(nsAtom** aName) { + if (NS_WARN_IF(!aName)) { + return NS_ERROR_INVALID_ARG; + } + if (NS_WARN_IF(!mName)) { + return NS_ERROR_FAILURE; + } + *aName = do_AddRef(mName).take(); + return NS_OK; +} + +} // namespace mozilla diff --git a/editor/libeditor/EditAggregateTransaction.h b/editor/libeditor/EditAggregateTransaction.h new file mode 100644 index 0000000000..d9ae9b7f78 --- /dev/null +++ b/editor/libeditor/EditAggregateTransaction.h @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef EditAggregateTransaction_h +#define EditAggregateTransaction_h + +#include "mozilla/EditTransactionBase.h" +#include "mozilla/OwningNonNull.h" +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsAtom.h" +#include "nsISupportsImpl.h" +#include "nsTArray.h" +#include "nscore.h" + +namespace mozilla { + +/** + * base class for all document editing transactions that require aggregation. + * provides a list of child transactions. + */ +class EditAggregateTransaction : public EditTransactionBase { + protected: + EditAggregateTransaction() = default; + + public: + /** + * Creates an edit aggregate transaction. This never returns nullptr. + */ + static already_AddRefed Create() { + RefPtr transaction = + new EditAggregateTransaction(); + return transaction.forget(); + } + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(EditAggregateTransaction, + EditTransactionBase) + + NS_DECL_EDITTRANSACTIONBASE + + MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction() override; + NS_IMETHOD Merge(nsITransaction* aOtherTransaction, bool* aDidMerge) override; + + /** + * Append a transaction to this aggregate. + */ + NS_IMETHOD AppendChild(EditTransactionBase* aTransaction); + + /** + * Get the name assigned to this transaction. + */ + NS_IMETHOD GetName(nsAtom** aName); + + const nsTArray>& ChildTransactions() + const { + return mChildren; + } + + protected: + virtual ~EditAggregateTransaction() = default; + + nsTArray> mChildren; + RefPtr mName; +}; + +} // namespace mozilla + +#endif // #ifndef EditAggregateTransaction_h diff --git a/editor/libeditor/EditTransactionBase.cpp b/editor/libeditor/EditTransactionBase.cpp new file mode 100644 index 0000000000..79452fb133 --- /dev/null +++ b/editor/libeditor/EditTransactionBase.cpp @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/EditTransactionBase.h" + +#include "ChangeAttributeTransaction.h" +#include "ChangeStyleTransaction.h" +#include "CompositionTransaction.h" +#include "CreateElementTransaction.h" +#include "DeleteNodeTransaction.h" +#include "DeleteRangeTransaction.h" +#include "DeleteTextTransaction.h" +#include "EditAggregateTransaction.h" +#include "InsertNodeTransaction.h" +#include "InsertTextTransaction.h" +#include "JoinNodeTransaction.h" +#include "PlaceholderTransaction.h" +#include "ReplaceTextTransaction.h" +#include "SplitNodeTransaction.h" + +#include "nsError.h" +#include "nsISupportsBase.h" + +namespace mozilla { + +NS_IMPL_CYCLE_COLLECTION_CLASS(EditTransactionBase) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_0(EditTransactionBase) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditTransactionBase) + // We don't have anything to traverse, but some of our subclasses do. +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditTransactionBase) + NS_INTERFACE_MAP_ENTRY(nsITransaction) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITransaction) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(EditTransactionBase) +NS_IMPL_CYCLE_COLLECTING_RELEASE(EditTransactionBase) + +NS_IMETHODIMP EditTransactionBase::RedoTransaction() { return DoTransaction(); } + +NS_IMETHODIMP EditTransactionBase::GetIsTransient(bool* aIsTransient) { + *aIsTransient = false; + + return NS_OK; +} + +NS_IMETHODIMP EditTransactionBase::Merge(nsITransaction* aOtherTransaction, + bool* aDidMerge) { + *aDidMerge = false; + return NS_OK; +} + +#define NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(aClass) \ + aClass* EditTransactionBase::GetAs##aClass() { return nullptr; } \ + const aClass* EditTransactionBase::GetAs##aClass() const { return nullptr; } + +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(ChangeAttributeTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(ChangeStyleTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(CompositionTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(CreateElementTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(DeleteNodeTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(DeleteRangeTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(DeleteTextTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(EditAggregateTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(InsertNodeTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(InsertTextTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(JoinNodeTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(PlaceholderTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(ReplaceTextTransaction) +NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS(SplitNodeTransaction) + +#undef NS_IMPL_EDITTRANSACTIONBASE_GETASMETHODS + +} // namespace mozilla diff --git a/editor/libeditor/EditTransactionBase.h b/editor/libeditor/EditTransactionBase.h new file mode 100644 index 0000000000..5fe968ea85 --- /dev/null +++ b/editor/libeditor/EditTransactionBase.h @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_EditTransactionBase_h +#define mozilla_EditTransactionBase_h + +#include "nsCycleCollectionParticipant.h" +#include "nsISupportsImpl.h" +#include "nsITransaction.h" +#include "nscore.h" + +already_AddRefed +nsITransaction::GetAsEditTransactionBase() { + RefPtr editTransactionBase; + return NS_SUCCEEDED( + GetAsEditTransactionBase(getter_AddRefs(editTransactionBase))) + ? editTransactionBase.forget() + : nullptr; +} + +namespace mozilla { + +class ChangeAttributeTransaction; +class ChangeStyleTransaction; +class CompositionTransaction; +class CreateElementTransaction; +class DeleteNodeTransaction; +class DeleteRangeTransaction; +class DeleteTextTransaction; +class EditAggregateTransaction; +class InsertNodeTransaction; +class InsertTextTransaction; +class JoinNodeTransaction; +class PlaceholderTransaction; +class ReplaceTextTransaction; +class SplitNodeTransaction; + +#define NS_DECL_GETASTRANSACTION_BASE(aClass) \ + virtual aClass* GetAs##aClass(); \ + virtual const aClass* GetAs##aClass() const; + +/** + * Base class for all document editing transactions. + */ +class EditTransactionBase : public nsITransaction { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditTransactionBase, nsITransaction) + + MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction(void) override; + NS_IMETHOD GetIsTransient(bool* aIsTransient) override; + NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override; + NS_IMETHOD GetAsEditTransactionBase( + EditTransactionBase** aEditTransactionBase) final { + MOZ_ASSERT(aEditTransactionBase); + MOZ_ASSERT(!*aEditTransactionBase); + *aEditTransactionBase = do_AddRef(this).take(); + return NS_OK; + } + + NS_DECL_GETASTRANSACTION_BASE(ChangeAttributeTransaction) + NS_DECL_GETASTRANSACTION_BASE(ChangeStyleTransaction) + NS_DECL_GETASTRANSACTION_BASE(CompositionTransaction) + NS_DECL_GETASTRANSACTION_BASE(CreateElementTransaction) + NS_DECL_GETASTRANSACTION_BASE(DeleteNodeTransaction) + NS_DECL_GETASTRANSACTION_BASE(DeleteRangeTransaction) + NS_DECL_GETASTRANSACTION_BASE(DeleteTextTransaction) + NS_DECL_GETASTRANSACTION_BASE(EditAggregateTransaction) + NS_DECL_GETASTRANSACTION_BASE(InsertNodeTransaction) + NS_DECL_GETASTRANSACTION_BASE(InsertTextTransaction) + NS_DECL_GETASTRANSACTION_BASE(JoinNodeTransaction) + NS_DECL_GETASTRANSACTION_BASE(PlaceholderTransaction) + NS_DECL_GETASTRANSACTION_BASE(ReplaceTextTransaction) + NS_DECL_GETASTRANSACTION_BASE(SplitNodeTransaction) + + protected: + virtual ~EditTransactionBase() = default; +}; + +#undef NS_DECL_GETASTRANSACTION_BASE + +} // namespace mozilla + +#define NS_DECL_EDITTRANSACTIONBASE \ + MOZ_CAN_RUN_SCRIPT NS_IMETHOD DoTransaction() override; \ + MOZ_CAN_RUN_SCRIPT NS_IMETHOD UndoTransaction() override; + +#define NS_DECL_EDITTRANSACTIONBASE_GETASMETHODS_OVERRIDE(aClass) \ + aClass* GetAs##aClass() final { return this; } \ + const aClass* GetAs##aClass() const final { return this; } + +#endif // #ifndef mozilla_EditTransactionBase_h diff --git a/editor/libeditor/EditorBase.cpp b/editor/libeditor/EditorBase.cpp new file mode 100644 index 0000000000..4004c7aaf9 --- /dev/null +++ b/editor/libeditor/EditorBase.cpp @@ -0,0 +1,5757 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "EditorBase.h" + +#include "mozilla/DebugOnly.h" // for DebugOnly +#include "mozilla/Encoding.h" // for Encoding + +#include // for nullptr, stdout +#include // for strcmp + +#include "ChangeAttributeTransaction.h" // for ChangeAttributeTransaction +#include "CompositionTransaction.h" // for CompositionTransaction +#include "CreateElementTransaction.h" // for CreateElementTransaction +#include "DeleteNodeTransaction.h" // for DeleteNodeTransaction +#include "DeleteRangeTransaction.h" // for DeleteRangeTransaction +#include "DeleteTextTransaction.h" // for DeleteTextTransaction +#include "EditAggregateTransaction.h" // for EditAggregateTransaction +#include "EditTransactionBase.h" // for EditTransactionBase +#include "EditorEventListener.h" // for EditorEventListener +#include "gfxFontUtils.h" // for gfxFontUtils +#include "HTMLEditUtils.h" // for HTMLEditUtils +#include "InsertNodeTransaction.h" // for InsertNodeTransaction +#include "InsertTextTransaction.h" // for InsertTextTransaction +#include "JoinNodeTransaction.h" // for JoinNodeTransaction +#include "PlaceholderTransaction.h" // for PlaceholderTransaction +#include "SplitNodeTransaction.h" // for SplitNodeTransaction +#include "mozilla/BasePrincipal.h" // for BasePrincipal +#include "mozilla/CheckedInt.h" // for CheckedInt +#include "mozilla/ComposerCommandsUpdater.h" // for ComposerCommandsUpdater +#include "mozilla/CSSEditUtils.h" // for CSSEditUtils +#include "mozilla/EditAction.h" // for EditSubAction +#include "mozilla/EditorDOMPoint.h" // for EditorDOMPoint +#include "mozilla/EditorSpellCheck.h" // for EditorSpellCheck +#include "mozilla/EditorUtils.h" // for various helper classes. +#include "mozilla/EditTransactionBase.h" // for EditTransactionBase +#include "mozilla/FlushType.h" // for FlushType::Frames +#include "mozilla/HTMLEditor.h" // for HTMLEditor +#include "mozilla/IMEContentObserver.h" // for IMEContentObserver +#include "mozilla/IMEStateManager.h" // for IMEStateManager +#include "mozilla/InputEventOptions.h" // for InputEventOptions +#include "mozilla/InternalMutationEvent.h" // for NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED +#include "mozilla/mozalloc.h" // for operator new, etc. +#include "mozilla/mozInlineSpellChecker.h" // for mozInlineSpellChecker +#include "mozilla/mozSpellChecker.h" // for mozSpellChecker +#include "mozilla/Preferences.h" // for Preferences +#include "mozilla/PresShell.h" // for PresShell +#include "mozilla/RangeBoundary.h" // for RawRangeBoundary, RangeBoundary +#include "mozilla/Services.h" // for GetObserverService +#include "mozilla/ServoCSSParser.h" // for ServoCSSParser +#include "mozilla/StaticPrefs_bidi.h" // for StaticPrefs::bidi_* +#include "mozilla/StaticPrefs_dom.h" // for StaticPrefs::dom_* +#include "mozilla/StaticPrefs_editor.h" // for StaticPrefs::editor_* +#include "mozilla/StaticPrefs_layout.h" // for StaticPrefs::layout_* +#include "mozilla/TextComposition.h" // for TextComposition +#include "mozilla/TextInputListener.h" // for TextInputListener +#include "mozilla/TextServicesDocument.h" // for TextServicesDocument +#include "mozilla/TextEditor.h" +#include "mozilla/TextEvents.h" +#include "mozilla/TransactionManager.h" // for TransactionManager +#include "mozilla/Tuple.h" +#include "mozilla/dom/AbstractRange.h" // for AbstractRange +#include "mozilla/dom/Attr.h" // for Attr +#include "mozilla/dom/CharacterData.h" // for CharacterData +#include "mozilla/dom/DataTransfer.h" // for DataTransfer +#include "mozilla/dom/Element.h" // for Element, nsINode::AsElement +#include "mozilla/dom/EventTarget.h" // for EventTarget +#include "mozilla/dom/HTMLBodyElement.h" +#include "mozilla/dom/HTMLBRElement.h" +#include "mozilla/dom/Selection.h" // for Selection, etc. +#include "mozilla/dom/StaticRange.h" // for StaticRange +#include "mozilla/dom/Text.h" +#include "mozilla/dom/Event.h" +#include "nsAString.h" // for nsAString::Length, etc. +#include "nsCCUncollectableMarker.h" // for nsCCUncollectableMarker +#include "nsCaret.h" // for nsCaret +#include "nsCaseTreatment.h" +#include "nsCharTraits.h" // for NS_IS_HIGH_SURROGATE, etc. +#include "nsComponentManagerUtils.h" // for do_CreateInstance +#include "nsContentUtils.h" // for nsContentUtils +#include "nsDOMString.h" // for DOMStringIsNull +#include "nsDebug.h" // for NS_WARNING, etc. +#include "nsError.h" // for NS_OK, etc. +#include "nsFocusManager.h" // for nsFocusManager +#include "nsFrameSelection.h" // for nsFrameSelection +#include "nsGenericHTMLElement.h" // for nsGenericHTMLElement +#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::dir +#include "nsIContent.h" // for nsIContent +#include "mozilla/dom/Document.h" // for Document +#include "nsIDocumentStateListener.h" // for nsIDocumentStateListener +#include "nsIEditActionListener.h" // for nsIEditActionListener +#include "nsIEditorObserver.h" // for nsIEditorObserver +#include "nsIFrame.h" // for nsIFrame +#include "nsIInlineSpellChecker.h" // for nsIInlineSpellChecker, etc. +#include "nsNameSpaceManager.h" // for kNameSpaceID_None, etc. +#include "nsINode.h" // for nsINode, etc. +#include "nsISelectionController.h" // for nsISelectionController, etc. +#include "nsISelectionDisplay.h" // for nsISelectionDisplay, etc. +#include "nsISupportsBase.h" // for nsISupports +#include "nsISupportsUtils.h" // for NS_ADDREF, NS_IF_ADDREF +#include "nsITransferable.h" // for nsITransferable +#include "nsITransactionManager.h" +#include "nsIWeakReference.h" // for nsISupportsWeakReference +#include "nsIWidget.h" // for nsIWidget, IMEState, etc. +#include "nsPIDOMWindow.h" // for nsPIDOMWindow +#include "nsPresContext.h" // for nsPresContext +#include "nsRange.h" // for nsRange +#include "nsReadableUtils.h" // for EmptyString, ToNewCString +#include "nsString.h" // for nsAutoString, nsString, etc. +#include "nsStringFwd.h" // for nsString +#include "nsStyleConsts.h" // for StyleDirection::Rtl, etc. +#include "nsStyleStruct.h" // for nsStyleDisplay, nsStyleText, etc. +#include "nsStyleStructFwd.h" // for nsIFrame::StyleUIReset, etc. +#include "nsStyleUtil.h" // for nsStyleUtil +#include "nsTextNode.h" // for nsTextNode +#include "nsThreadUtils.h" // for nsRunnable +#include "prtime.h" // for PR_Now + +class nsIOutputStream; +class nsITransferable; + +namespace mozilla { + +using namespace dom; +using namespace widget; + +using ChildBlockBoundary = HTMLEditUtils::ChildBlockBoundary; + +/***************************************************************************** + * mozilla::EditorBase + *****************************************************************************/ +template EditorBase::AutoCaretBidiLevelManager::AutoCaretBidiLevelManager( + const EditorBase& aEditorBase, nsIEditor::EDirection aDirectionAndAmount, + const EditorDOMPoint& aPointAtCaret); +template EditorBase::AutoCaretBidiLevelManager::AutoCaretBidiLevelManager( + const EditorBase& aEditorBase, nsIEditor::EDirection aDirectionAndAmount, + const EditorRawDOMPoint& aPointAtCaret); + +EditorBase::EditorBase() + : mEditActionData(nullptr), + mPlaceholderName(nullptr), + mModCount(0), + mFlags(0), + mUpdateCount(0), + mPlaceholderBatch(0), + mWrapColumn(0), + mNewlineHandling(StaticPrefs::editor_singleLine_pasteNewlines()), + mCaretStyle(StaticPrefs::layout_selection_caret_style()), + mDocDirtyState(-1), + mSpellcheckCheckboxState(eTriUnset), + mInitSucceeded(false), + mAllowsTransactionsToChangeSelection(true), + mDidPreDestroy(false), + mDidPostCreate(false), + mDispatchInputEvent(true), + mIsInEditSubAction(false), + mHidingCaret(false), + mSpellCheckerDictionaryUpdated(true), + mIsHTMLEditorClass(false) { +#ifdef XP_WIN + if (!mCaretStyle) { + mCaretStyle = 1; + } +#endif // #ifdef XP_WIN + if (mNewlineHandling < nsIEditor::eNewlinesPasteIntact || + mNewlineHandling > nsIEditor::eNewlinesStripSurroundingWhitespace) { + mNewlineHandling = nsIEditor::eNewlinesPasteToFirst; + } +} + +EditorBase::~EditorBase() { + MOZ_ASSERT(!IsInitialized() || mDidPreDestroy, + "Why PreDestroy hasn't been called?"); + + if (mComposition) { + mComposition->OnEditorDestroyed(); + mComposition = nullptr; + } + // If this editor is still hiding the caret, we need to restore it. + HideCaret(false); + mTransactionManager = nullptr; +} + +NS_IMPL_CYCLE_COLLECTION_CLASS(EditorBase) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EditorBase) + // Remove event listeners first since EditorEventListener may need + // mDocument, mEventTarget, etc. + if (tmp->mEventListener) { + tmp->mEventListener->Disconnect(); + tmp->mEventListener = nullptr; + } + + NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootElement) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaddingBRElementForEmptyEditor) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectionController) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mIMEContentObserver) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSpellChecker) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextServicesDocument) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextInputListener) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mTransactionManager) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mActionListeners) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlaceholderTransaction) + NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditorBase) + Document* currentDoc = + tmp->mRootElement ? tmp->mRootElement->GetUncomposedDoc() : nullptr; + if (currentDoc && nsCCUncollectableMarker::InGeneration( + cb, currentDoc->GetMarkedCCGeneration())) { + return NS_SUCCESS_INTERRUPTED_TRAVERSE; + } + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRootElement) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaddingBRElementForEmptyEditor) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectionController) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIMEContentObserver) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineSpellChecker) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextServicesDocument) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextInputListener) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransactionManager) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActionListeners) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorObservers) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocStateListeners) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventTarget) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventListener) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlaceholderTransaction) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditorBase) + NS_INTERFACE_MAP_ENTRY(nsISelectionListener) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY(nsIEditor) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditor) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(EditorBase) +NS_IMPL_CYCLE_COLLECTING_RELEASE(EditorBase) + +nsresult EditorBase::Init(Document& aDocument, Element* aRoot, + nsISelectionController* aSelectionController, + uint32_t aFlags, const nsAString& aValue) { + MOZ_ASSERT(GetTopLevelEditSubAction() == EditSubAction::eNone, + "Initializing during an edit action is an error"); + + // First only set flags, but other stuff shouldn't be initialized now. + // Note that SetFlags() will be called by PostCreate(). + mFlags = aFlags; + + mDocument = &aDocument; + // HTML editors currently don't have their own selection controller, + // so they'll pass null as aSelCon, and we'll get the selection controller + // off of the presshell. + nsCOMPtr selectionController; + if (aSelectionController) { + mSelectionController = aSelectionController; + selectionController = aSelectionController; + } else { + selectionController = GetPresShell(); + } + MOZ_ASSERT(selectionController, + "Selection controller should be available at this point"); + + if (mEditActionData) { + // During edit action, selection is cached. But this selection is invalid + // now since selection controller is updated, so we have to update this + // cache. + Selection* selection = selectionController->GetSelection( + nsISelectionController::SELECTION_NORMAL); + NS_WARNING_ASSERTION(selection, + "SelectionController::GetSelection() failed"); + if (selection) { + mEditActionData->UpdateSelectionCache(*selection); + } + } + + // set up root element if we are passed one. + if (aRoot) { + mRootElement = aRoot; + } + + mUpdateCount = 0; + + // If this is an editor for or + diff --git a/editor/libeditor/crashtests/1402196.html b/editor/libeditor/crashtests/1402196.html new file mode 100644 index 0000000000..6867d36414 --- /dev/null +++ b/editor/libeditor/crashtests/1402196.html @@ -0,0 +1,21 @@ + + + + + + +
                + + +

                + + diff --git a/editor/libeditor/crashtests/1402469.html b/editor/libeditor/crashtests/1402469.html new file mode 100644 index 0000000000..04b1adc96f --- /dev/null +++ b/editor/libeditor/crashtests/1402469.html @@ -0,0 +1,16 @@ + + + + + + + +
                +
                  +
                + + diff --git a/editor/libeditor/crashtests/1402526.html b/editor/libeditor/crashtests/1402526.html new file mode 100644 index 0000000000..4d6077d995 --- /dev/null +++ b/editor/libeditor/crashtests/1402526.html @@ -0,0 +1,14 @@ + + +
                + \ No newline at end of file diff --git a/editor/libeditor/crashtests/1402904.html b/editor/libeditor/crashtests/1402904.html new file mode 100644 index 0000000000..96880ce4a3 --- /dev/null +++ b/editor/libeditor/crashtests/1402904.html @@ -0,0 +1,31 @@ + + + +
              1. +
                  +
                • +a;#2 diff --git a/editor/libeditor/crashtests/1405747.html b/editor/libeditor/crashtests/1405747.html new file mode 100644 index 0000000000..38923228db --- /dev/null +++ b/editor/libeditor/crashtests/1405747.html @@ -0,0 +1,23 @@ + + + + +\ No newline at end of file diff --git a/editor/libeditor/crashtests/1405897.html b/editor/libeditor/crashtests/1405897.html new file mode 100644 index 0000000000..c5c60bc6cf --- /dev/null +++ b/editor/libeditor/crashtests/1405897.html @@ -0,0 +1,16 @@ + + + + + + +
                  diff --git a/editor/libeditor/crashtests/1578916.html b/editor/libeditor/crashtests/1578916.html new file mode 100644 index 0000000000..08883f0c95 --- /dev/null +++ b/editor/libeditor/crashtests/1578916.html @@ -0,0 +1,15 @@ + + + + diff --git a/editor/libeditor/crashtests/643786-1.html b/editor/libeditor/crashtests/643786-1.html new file mode 100644 index 0000000000..3f0b27a546 --- /dev/null +++ b/editor/libeditor/crashtests/643786-1.html @@ -0,0 +1,18 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/650572-1.html b/editor/libeditor/crashtests/650572-1.html new file mode 100644 index 0000000000..a86f6e6186 --- /dev/null +++ b/editor/libeditor/crashtests/650572-1.html @@ -0,0 +1,18 @@ + + + + + +
                  + + diff --git a/editor/libeditor/crashtests/667321-1.html b/editor/libeditor/crashtests/667321-1.html new file mode 100644 index 0000000000..2752695221 --- /dev/null +++ b/editor/libeditor/crashtests/667321-1.html @@ -0,0 +1,15 @@ + + + + + +
                  + diff --git a/editor/libeditor/crashtests/682650-1.html b/editor/libeditor/crashtests/682650-1.html new file mode 100644 index 0000000000..66ebc2f628 --- /dev/null +++ b/editor/libeditor/crashtests/682650-1.html @@ -0,0 +1,30 @@ + + + + + + + + + diff --git a/editor/libeditor/crashtests/713427-1.html b/editor/libeditor/crashtests/713427-1.html new file mode 100644 index 0000000000..21da24693a --- /dev/null +++ b/editor/libeditor/crashtests/713427-1.html @@ -0,0 +1,9 @@ + + +
                  + + + +
                  + + diff --git a/editor/libeditor/crashtests/713427-2.xhtml b/editor/libeditor/crashtests/713427-2.xhtml new file mode 100644 index 0000000000..39ac18ed07 --- /dev/null +++ b/editor/libeditor/crashtests/713427-2.xhtml @@ -0,0 +1,28 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/716456-1.html b/editor/libeditor/crashtests/716456-1.html new file mode 100644 index 0000000000..a5ef5a2cc3 --- /dev/null +++ b/editor/libeditor/crashtests/716456-1.html @@ -0,0 +1,29 @@ + + + + + + +
                  + diff --git a/editor/libeditor/crashtests/745494.html b/editor/libeditor/crashtests/745494.html new file mode 100644 index 0000000000..ce15fc6363 --- /dev/null +++ b/editor/libeditor/crashtests/745494.html @@ -0,0 +1,17 @@ + + + + + + +
                  + diff --git a/editor/libeditor/crashtests/759748.html b/editor/libeditor/crashtests/759748.html new file mode 100644 index 0000000000..1e85a3877d --- /dev/null +++ b/editor/libeditor/crashtests/759748.html @@ -0,0 +1,58 @@ + + + diff --git a/editor/libeditor/crashtests/761861.html b/editor/libeditor/crashtests/761861.html new file mode 100644 index 0000000000..2a7e06a154 --- /dev/null +++ b/editor/libeditor/crashtests/761861.html @@ -0,0 +1,15 @@ + + + diff --git a/editor/libeditor/crashtests/762183.html b/editor/libeditor/crashtests/762183.html new file mode 100644 index 0000000000..1916ac6fb5 --- /dev/null +++ b/editor/libeditor/crashtests/762183.html @@ -0,0 +1,6 @@ +x y + diff --git a/editor/libeditor/crashtests/766305.html b/editor/libeditor/crashtests/766305.html new file mode 100644 index 0000000000..a5000fe738 --- /dev/null +++ b/editor/libeditor/crashtests/766305.html @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/editor/libeditor/crashtests/766360.html b/editor/libeditor/crashtests/766360.html new file mode 100644 index 0000000000..76c30456d6 --- /dev/null +++ b/editor/libeditor/crashtests/766360.html @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/editor/libeditor/crashtests/766387.html b/editor/libeditor/crashtests/766387.html new file mode 100644 index 0000000000..20ccc60d44 --- /dev/null +++ b/editor/libeditor/crashtests/766387.html @@ -0,0 +1,20 @@ + + + + + + +
                  a
                  + diff --git a/editor/libeditor/crashtests/766413.html b/editor/libeditor/crashtests/766413.html new file mode 100644 index 0000000000..1a7092d92a --- /dev/null +++ b/editor/libeditor/crashtests/766413.html @@ -0,0 +1,42 @@ + + + + + + + + diff --git a/editor/libeditor/crashtests/766795.html b/editor/libeditor/crashtests/766795.html new file mode 100644 index 0000000000..b4ade30209 --- /dev/null +++ b/editor/libeditor/crashtests/766795.html @@ -0,0 +1,21 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/766845.xhtml b/editor/libeditor/crashtests/766845.xhtml new file mode 100644 index 0000000000..409e210109 --- /dev/null +++ b/editor/libeditor/crashtests/766845.xhtml @@ -0,0 +1,27 @@ + + + + + +
                  + + diff --git a/editor/libeditor/crashtests/767169.html b/editor/libeditor/crashtests/767169.html new file mode 100644 index 0000000000..a7673bce62 --- /dev/null +++ b/editor/libeditor/crashtests/767169.html @@ -0,0 +1,23 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/768748.html b/editor/libeditor/crashtests/768748.html new file mode 100644 index 0000000000..09206dce3f --- /dev/null +++ b/editor/libeditor/crashtests/768748.html @@ -0,0 +1,16 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/768765.html b/editor/libeditor/crashtests/768765.html new file mode 100644 index 0000000000..551e4ec6c3 --- /dev/null +++ b/editor/libeditor/crashtests/768765.html @@ -0,0 +1,36 @@ + + + + + + + + diff --git a/editor/libeditor/crashtests/769008-1.html b/editor/libeditor/crashtests/769008-1.html new file mode 100644 index 0000000000..8ea8a3601d --- /dev/null +++ b/editor/libeditor/crashtests/769008-1.html @@ -0,0 +1,23 @@ + + + + + +
                  + diff --git a/editor/libeditor/crashtests/769967.xhtml b/editor/libeditor/crashtests/769967.xhtml new file mode 100644 index 0000000000..af07571591 --- /dev/null +++ b/editor/libeditor/crashtests/769967.xhtml @@ -0,0 +1,16 @@ +x diff --git a/editor/libeditor/crashtests/771749.html b/editor/libeditor/crashtests/771749.html new file mode 100644 index 0000000000..9237364f2d --- /dev/null +++ b/editor/libeditor/crashtests/771749.html @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/editor/libeditor/crashtests/772282.html b/editor/libeditor/crashtests/772282.html new file mode 100644 index 0000000000..bba3d6bd67 --- /dev/null +++ b/editor/libeditor/crashtests/772282.html @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/editor/libeditor/crashtests/776323.html b/editor/libeditor/crashtests/776323.html new file mode 100644 index 0000000000..9fc2776c37 --- /dev/null +++ b/editor/libeditor/crashtests/776323.html @@ -0,0 +1,18 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/793866.html b/editor/libeditor/crashtests/793866.html new file mode 100644 index 0000000000..4984474dbc --- /dev/null +++ b/editor/libeditor/crashtests/793866.html @@ -0,0 +1,21 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/848644.html b/editor/libeditor/crashtests/848644.html new file mode 100644 index 0000000000..95570fabe3 --- /dev/null +++ b/editor/libeditor/crashtests/848644.html @@ -0,0 +1,2 @@ + + diff --git a/editor/libeditor/crashtests/crashtests.list b/editor/libeditor/crashtests/crashtests.list new file mode 100644 index 0000000000..db7036e605 --- /dev/null +++ b/editor/libeditor/crashtests/crashtests.list @@ -0,0 +1,138 @@ +load 336081-1.xhtml +load 336104.html +load 382527-1.html +load 382778-1.html +load 402172-1.html +load 403965-1.xhtml +load 407074-1.html +load 407079-1.html +load 407256-1.html +load 407277-1.html +load 414178-1.html +load 418923-1.html +load 420439.html +load 428489-1.html +load 429586-1.html +load 430624-1.html +load 431086-1.xhtml +load 448329-1.html +load 448329-2.html +load 448329-3.html +load 456727-1.html +load 456727-2.html +load 459613.html +needs-focus load 467647-1.html +load 475132-1.xhtml +load 499844-1.html +load 503709-1.xhtml +load 513375-1.xhtml +load 535632-1.xhtml +load 574558-1.xhtml +load 580151-1.xhtml +load 582138-1.xhtml +load 612565-1.html +load 615015-1.html +load 615450-1.html +load 633709.xhtml +load 636074-1.html +load 639736-1.xhtml +load 643786-1.html +load 650572-1.html +load 667321-1.html +load 682650-1.html +load 713427-1.html +load 713427-2.xhtml +load 716456-1.html +needs-focus load 745494.html +load 759748.html +load 761861.html +load 762183.html +load 766305.html +load 766360.html +load 766387.html +load 766413.html +load 766795.html +load 766845.xhtml +load 767169.html +load 768748.html +load 768765.html +load 769008-1.html +load 769967.xhtml +needs-focus load 771749.html +load 772282.html +load 776323.html +needs-focus load 793866.html +load 848644.html +load 1057677.html +needs-focus load 1128787.html +load 1134545.html +load 1158452.html +load 1158651.html +load 1244894.xhtml +load 1264921.html +load 1272490.html +load 1274050.html +load 1317704.html +load 1317718.html +load 1324505.html +needs-focus load 1343918.html +load 1344097.html +load 1345015.html +load 1348851.html +load 1350772.html +load 1364133.html +load 1366176.html +asserts(4) load 1375131.html # assertion in WSRunScanner::GetEditableBlockParentOrTopmotEditableInlineContent() +load 1381541.html +load 1383747.html +load 1383755.html +load 1383763.html +load 1384161.html +load 1388075.html +load 1393171.html +needs-focus load 1402196.html +load 1402469.html +load 1402526.html +pref(dom.document.exec_command.nested_calls_allowed,true) asserts(1) load 1402904.html # assertion is that mutation event listener caused by execCommand calls another execCommand +pref(dom.document.exec_command.nested_calls_allowed,true) asserts(1) load 1405747.html # assertion is that mutation event listener caused by execCommand calls another execCommand +load 1405897.html +asserts(4) load 1408170.html # 4: assertion in WSRunScanner::GetEditableBlockParentOrTopmotEditableInlineContent() +asserts(0-1) load 1414581.html +load 1415231.html +load 1423767.html +needs-focus load 1423776.html +needs-focus load 1424450.html +load 1425091.html +load 1426709.html +load 1441619.html +load 1443664.html +skip-if(Android) needs-focus load 1444630.html +load 1446451.html +pref(dom.document.exec_command.nested_calls_allowed,true) asserts(2) load 1464251.html # assertion is that mutation event listener caused by execCommand calls another execCommand +pref(layout.accessiblecaret.enabled,true) load 1470926.html +pref(dom.document.exec_command.nested_calls_allowed,true) asserts(1) load 1474978.html # assertion is that mutation event listener caused by execCommand calls another execCommand +load 1525481.html +load 1533913.html +asserts(3) load 1534394.html # assertion in WSRunScanner::GetEditableBlockParentOrTopmotEditableInlineContent() +load 1547897.html +load 1547898.html +load 1556799.html +load 1579934.html +load 1574544.html +load 1578916.html +load 1581246.html +load 1596516.html +load 1605741.html +load 1613521.html +load 1618906.html +load 1623913.html +load 1624005.html # throws +load 1624007.html +load 1624011.html +load 1644903.html +load 1645983-1.html +load 1645983-2.html +load 1648564.html +load 1659717.html +load 1663725.html # throws +pref(dom.document.exec_command.nested_calls_allowed,true) load 1666556.html diff --git a/editor/libeditor/moz.build b/editor/libeditor/moz.build new file mode 100644 index 0000000000..5f0da1b8ff --- /dev/null +++ b/editor/libeditor/moz.build @@ -0,0 +1,99 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +MOCHITEST_MANIFESTS += [ + "tests/browserscope/mochitest.ini", + "tests/mochitest.ini", +] + +MOCHITEST_CHROME_MANIFESTS += ["tests/chrome.ini"] + +BROWSER_CHROME_MANIFESTS += ["tests/browser.ini"] + +EXPORTS.mozilla += [ + "ChangeStyleTransaction.h", + "CSSEditUtils.h", + "EditAction.h", + "EditorBase.h", + "EditorCommands.h", + "EditorController.h", + "EditorDOMPoint.h", + "EditorUtils.h", + "EditTransactionBase.h", + "HTMLEditor.h", + "HTMLEditorController.h", + "ManualNAC.h", + "SelectionState.h", + "TextEditor.h", + "TypeInState.h", +] + +UNIFIED_SOURCES += [ + "ChangeAttributeTransaction.cpp", + "ChangeStyleTransaction.cpp", + "CompositionTransaction.cpp", + "CreateElementTransaction.cpp", + "CSSEditUtils.cpp", + "DeleteNodeTransaction.cpp", + "DeleteRangeTransaction.cpp", + "DeleteTextTransaction.cpp", + "EditAggregateTransaction.cpp", + "EditorBase.cpp", + "EditorCommands.cpp", + "EditorController.cpp", + "EditorEventListener.cpp", + "EditorUtils.cpp", + "EditTransactionBase.cpp", + "HTMLAbsPositionEditor.cpp", + "HTMLAnonymousNodeEditor.cpp", + "HTMLEditor.cpp", + "HTMLEditorCommands.cpp", + "HTMLEditorController.cpp", + "HTMLEditorDataTransfer.cpp", + "HTMLEditorDeleteHandler.cpp", + "HTMLEditorDocumentCommands.cpp", + "HTMLEditorEventListener.cpp", + "HTMLEditorObjectResizer.cpp", + "HTMLEditorState.cpp", + "HTMLEditSubActionHandler.cpp", + "HTMLEditUtils.cpp", + "HTMLInlineTableEditor.cpp", + "HTMLStyleEditor.cpp", + "HTMLTableEditor.cpp", + "InsertNodeTransaction.cpp", + "InsertTextTransaction.cpp", + "InternetCiter.cpp", + "JoinNodeTransaction.cpp", + "PlaceholderTransaction.cpp", + "ReplaceTextTransaction.cpp", + "SelectionState.cpp", + "SplitNodeTransaction.cpp", + "TextEditor.cpp", + "TextEditorDataTransfer.cpp", + "TextEditSubActionHandler.cpp", + "TypeInState.cpp", + "WSRunObject.cpp", +] + +LOCAL_INCLUDES += [ + "/dom/base", + "/dom/html", + "/extensions/spellcheck/src", + "/layout/generic", + "/layout/style", + "/layout/tables", + "/layout/xul", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +FINAL_LIBRARY = "xul" + +if CONFIG["CC_TYPE"] in ("clang", "gcc"): + CXXFLAGS += ["-Wno-error=shadow"] + +with Files("tests/*1151186*"): + BUG_COMPONENT = ("Core", "DOM: UI Events & Focus Handling") diff --git a/editor/libeditor/tests/.eslintrc.js b/editor/libeditor/tests/.eslintrc.js new file mode 100644 index 0000000000..40ffdf1f0b --- /dev/null +++ b/editor/libeditor/tests/.eslintrc.js @@ -0,0 +1,11 @@ +"use strict"; + +module.exports = { + extends: ["plugin:mozilla/browser-test", "plugin:mozilla/mochitest-test"], + + plugins: ["no-unsanitized"], + + rules: { + "no-unsanitized/property": "off", + }, +}; diff --git a/editor/libeditor/tests/browser.ini b/editor/libeditor/tests/browser.ini new file mode 100644 index 0000000000..b2ec0aa521 --- /dev/null +++ b/editor/libeditor/tests/browser.ini @@ -0,0 +1,7 @@ +[browser_bug527935.js] +skip-if = toolkit == 'android' +prefs = + editor.white_space_normalization.blink_compatible=true +support-files = + bug527935.html + bug527935_2.html diff --git a/editor/libeditor/tests/browser_bug527935.js b/editor/libeditor/tests/browser_bug527935.js new file mode 100644 index 0000000000..0f69a7dc20 --- /dev/null +++ b/editor/libeditor/tests/browser_bug527935.js @@ -0,0 +1,85 @@ +add_task(async function() { + await new Promise(resolve => waitForFocus(resolve, window)); + + const kPageURL = + "http://example.org/browser/editor/libeditor/tests/bug527935.html"; + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: kPageURL, + }, + async function(aBrowser) { + var popupShown = false; + function listener() { + popupShown = true; + } + SpecialPowers.addAutoCompletePopupEventListener( + window, + "popupshowing", + listener + ); + + await SpecialPowers.spawn(aBrowser, [], async function() { + var window = content.window.wrappedJSObject; + var document = window.document; + var formTarget = document.getElementById("formTarget"); + var initValue = document.getElementById("initValue"); + + window.loadPromise = new Promise(resolve => { + formTarget.onload = resolve; + }); + + initValue.focus(); + initValue.value = "foo"; + }); + + EventUtils.synthesizeKey("KEY_Enter"); + + await SpecialPowers.spawn(aBrowser, [], async function() { + var window = content.window.wrappedJSObject; + var document = window.document; + + await window.loadPromise; + + var newInput = document.createElement("input"); + newInput.setAttribute("name", "test"); + document.body.appendChild(newInput); + + var event = document.createEvent("KeyboardEvent"); + + event.initKeyEvent( + "keypress", + true, + true, + null, + false, + false, + false, + false, + 0, + "f".charCodeAt(0) + ); + newInput.value = ""; + newInput.focus(); + newInput.dispatchEvent(event); + }); + + await new Promise(resolve => hitEventLoop(resolve, 100)); + + ok(!popupShown, "Popup must not be opened"); + SpecialPowers.removeAutoCompletePopupEventListener( + window, + "popupshowing", + listener + ); + } + ); +}); + +function hitEventLoop(func, times) { + if (times > 0) { + setTimeout(hitEventLoop, 0, func, times - 1); + } else { + setTimeout(func, 0); + } +} diff --git a/editor/libeditor/tests/browserscope/lib/richtext/LICENSE b/editor/libeditor/tests/browserscope/lib/richtext/LICENSE new file mode 100644 index 0000000000..57bc88a15a --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/editor/libeditor/tests/browserscope/lib/richtext/README b/editor/libeditor/tests/browserscope/lib/richtext/README new file mode 100644 index 0000000000..a3bc3110f4 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext/README @@ -0,0 +1,58 @@ +README FOR BROWSERSCOPE +----------------------- + +Hey there - thanks for downloading the code. This file has instructions +for getting setup so that you can run the codebase locally. + +This project is built on Google App Engine using the +Django web application framework and written in Python. + +To get started, you'll need to first download the App Engine SDK at: +http://code.google.com/appengine/downloads.html + +For local development, just startup the server: +./pathto/google_appengine/dev_appserver.py --port=8080 browserscope + +You should then be able to access the local application at: +http://localhost:8080/ + +Note: the first time you hit the homepage it may take a little +while - that's because it's trying to read out median times for all +of the tests from a nonexistent datastore and write to memcache. +Just be a lil patient. + +You can run the unit tests at: + http://localhost:8080/test + + +CONTRIBUTING +------------------ + +Most likely you are interested in adding new tests or creating +a new test category. If you are interested in adding tests to an existing +"category" you may want to get in touch with the maintainer for that +branch of the tree. We are really looking forward to receiving your +code in patch format. Currently the category maintainers are: +Network: Steve Souders +Reflow: Lindsey Simon +Security: Adam Barth and Collin Jackson + + +To create a completely new test category: + * Copy one of the existing directories in categories/ + * Edit your test_set.py, handlers.py + * Add your files in templates/ and static/ + * Update urls.py and settings.CATEGORIES + * Follow the examples of other tests re: + * beaconing using/testdriver_base + * your GetScoreAndDisplayValue method + * your GetRowScoreAndDisplayValue method + +References: + * App Engine Docs - http://code.google.com/appengine/docs/python/overview.html + * App Engine Group - http://groups.google.com/group/google-appengine + * Python Docs - http://www.python.org/doc/ + * Django - http://www.djangoproject.com/ + + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext/README.Mozilla b/editor/libeditor/tests/browserscope/lib/richtext/README.Mozilla new file mode 100644 index 0000000000..5d304943f7 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext/README.Mozilla @@ -0,0 +1,17 @@ +The BrowserScope project provides a set of cross-browser HTML editor tests, +which we import in our test suite in order to run them as part of our +continuous integration system. + +We pull tests occasionally from their Subversion repository using the pull +script which can be found in this directory. We also record the revision ID +which we've used in the current_revision file inside this directory. + +Using the pull script is quite easy, just switch to this directory, and say: + +sh update_from_upstream + +There are tests which we're currently failing on, and there will probably be +more of those in the future. We should maintain a list of the failing tests +manually in currentStatus.js (which can also be found in this directory), to +make sure that the suite passes entirely, with failing tests marked as todo +items. diff --git a/editor/libeditor/tests/browserscope/lib/richtext/currentStatus.js b/editor/libeditor/tests/browserscope/lib/richtext/currentStatus.js new file mode 100644 index 0000000000..b30775d043 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext/currentStatus.js @@ -0,0 +1,46 @@ +/** + * This file lists the tests in the BrowserScope suite which we are currently + * failing. We mark them as todo items to keep track of them. + */ + +var knownFailures = { + // Dummy result items. There is one for each category. + 'apply' : { + '0-undefined' : true + }, + 'unapply' : { + '0-undefined' : true + }, + 'change' : { + '0-undefined' : true + }, + 'query' : { + '0-undefined' : true + }, + 'a' : { + 'createbookmark-0' : true, + 'fontsize-1' : true, + 'subscript-1' : true, + 'superscript-1' : true, + }, + 'u': { + 'removeformat-1' : true, + 'removeformat-2' : true, + 'strikethrough-2' : true, + 'subscript-1' : true, + 'superscript-1' : true, + 'unbookmark-0' : true, + }, + 'q': { + 'fontsize-1' : true, + 'fontsize-2' : true, + }, + 'c': { + 'fontsize-1' : true, + 'fontsize-2' : true, + }, +}; + +function isKnownFailure(type, test, param) { + return (type in knownFailures) && ((test + "-" + param) in knownFailures[type]); +} diff --git a/editor/libeditor/tests/browserscope/lib/richtext/current_revision b/editor/libeditor/tests/browserscope/lib/richtext/current_revision new file mode 100644 index 0000000000..1e25699145 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext/current_revision @@ -0,0 +1 @@ +775 diff --git a/editor/libeditor/tests/browserscope/lib/richtext/richtext/editable.html b/editor/libeditor/tests/browserscope/lib/richtext/richtext/editable.html new file mode 100644 index 0000000000..a294f0b56b --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext/richtext/editable.html @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/editor/libeditor/tests/browserscope/lib/richtext/richtext/js/range.js b/editor/libeditor/tests/browserscope/lib/richtext/richtext/js/range.js new file mode 100644 index 0000000000..edd23f86b9 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext/richtext/js/range.js @@ -0,0 +1,1069 @@ +var goog$global = this, goog$isString = function(val) { + return typeof val == "string" +}; +Math.floor(Math.random() * 2147483648).toString(36); +var goog$now = Date.now || function() { + return(new Date).getTime() +}, goog$inherits = function(childCtor, parentCtor) { + function tempCtor() { + } + tempCtor.prototype = parentCtor.prototype; + childCtor.superClass_ = parentCtor.prototype; + childCtor.prototype = new tempCtor +};var goog$array$peek = function(array) { + return array[array.length - 1] +}, goog$array$indexOf = function(arr, obj, opt_fromIndex) { + if(arr.indexOf)return arr.indexOf(obj, opt_fromIndex); + if(Array.indexOf)return Array.indexOf(arr, obj, opt_fromIndex); + for(var fromIndex = opt_fromIndex == null ? 0 : opt_fromIndex < 0 ? Math.max(0, arr.length + opt_fromIndex) : opt_fromIndex, i = fromIndex;i < arr.length;i++)if(i in arr && arr[i] === obj)return i; + return-1 +}, goog$array$map = function(arr, f, opt_obj) { + if(arr.map)return arr.map(f, opt_obj); + if(Array.map)return Array.map(arr, f, opt_obj); + for(var l = arr.length, res = [], resLength = 0, arr2 = goog$isString(arr) ? arr.split("") : arr, i = 0;i < l;i++)if(i in arr2)res[resLength++] = f.call(opt_obj, arr2[i], i, arr); + return res +}, goog$array$some = function(arr, f, opt_obj) { + if(arr.some)return arr.some(f, opt_obj); + if(Array.some)return Array.some(arr, f, opt_obj); + for(var l = arr.length, arr2 = goog$isString(arr) ? arr.split("") : arr, i = 0;i < l;i++)if(i in arr2 && f.call(opt_obj, arr2[i], i, arr))return true; + return false +}, goog$array$every = function(arr, f, opt_obj) { + if(arr.every)return arr.every(f, opt_obj); + if(Array.every)return Array.every(arr, f, opt_obj); + for(var l = arr.length, arr2 = goog$isString(arr) ? arr.split("") : arr, i = 0;i < l;i++)if(i in arr2 && !f.call(opt_obj, arr2[i], i, arr))return false; + return true +}, goog$array$find = function(arr, f, opt_obj) { + var i; + JSCompiler_inline_label_goog$array$findIndex_12: { + for(var JSCompiler_inline_l = arr.length, JSCompiler_inline_arr2 = goog$isString(arr) ? arr.split("") : arr, JSCompiler_inline_i = 0;JSCompiler_inline_i < JSCompiler_inline_l;JSCompiler_inline_i++)if(JSCompiler_inline_i in JSCompiler_inline_arr2 && f.call(opt_obj, JSCompiler_inline_arr2[JSCompiler_inline_i], JSCompiler_inline_i, arr)) { + i = JSCompiler_inline_i; + break JSCompiler_inline_label_goog$array$findIndex_12 + }i = -1 + }return i < 0 ? null : goog$isString(arr) ? arr.charAt(i) : arr[i] +};var goog$string$trim = function(str) { + return str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, "") +}, goog$string$htmlEscape = function(str, opt_isLikelyToContainHtmlChars) { + if(opt_isLikelyToContainHtmlChars)return str.replace(goog$string$amperRe_, "&").replace(goog$string$ltRe_, "<").replace(goog$string$gtRe_, ">").replace(goog$string$quotRe_, """); + else { + if(!goog$string$allRe_.test(str))return str; + if(str.includes("&"))str = str.replace(goog$string$amperRe_, "&"); + if(str.includes("<"))str = str.replace(goog$string$ltRe_, "<"); + if(str.includes(">"))str = str.replace(goog$string$gtRe_, ">"); + if(str.includes('"'))str = str.replace(goog$string$quotRe_, """); + return str + } +}, goog$string$amperRe_ = /&/g, goog$string$ltRe_ = //g, goog$string$quotRe_ = /\"/g, goog$string$allRe_ = /[&<>\"]/, goog$string$contains = function(s, ss) { + return s.includes(ss) +}, goog$string$compareVersions = function(version1, version2) { + for(var order = 0, v1Subs = goog$string$trim(String(version1)).split("."), v2Subs = goog$string$trim(String(version2)).split("."), subCount = Math.max(v1Subs.length, v2Subs.length), subIdx = 0;order == 0 && subIdx < subCount;subIdx++) { + var v1Sub = v1Subs[subIdx] || "", v2Sub = v2Subs[subIdx] || "", v1CompParser = new RegExp("(\\d*)(\\D*)", "g"), v2CompParser = new RegExp("(\\d*)(\\D*)", "g"); + do { + var v1Comp = v1CompParser.exec(v1Sub) || ["", "", ""], v2Comp = v2CompParser.exec(v2Sub) || ["", "", ""]; + if(v1Comp[0].length == 0 && v2Comp[0].length == 0)break; + var v1CompNum = v1Comp[1].length == 0 ? 0 : parseInt(v1Comp[1], 10), v2CompNum = v2Comp[1].length == 0 ? 0 : parseInt(v2Comp[1], 10); + order = goog$string$compareElements_(v1CompNum, v2CompNum) || goog$string$compareElements_(v1Comp[2].length == 0, v2Comp[2].length == 0) || goog$string$compareElements_(v1Comp[2], v2Comp[2]) + }while(order == 0) + }return order +}, goog$string$compareElements_ = function(left, right) { + if(left < right)return-1; + else if(left > right)return 1; + return 0 +}; +goog$now();var goog$userAgent$detectedOpera_, goog$userAgent$detectedIe_, goog$userAgent$detectedWebkit_, goog$userAgent$detectedMobile_, goog$userAgent$detectedGecko_, goog$userAgent$detectedCamino_, goog$userAgent$detectedMac_, goog$userAgent$detectedWindows_, goog$userAgent$detectedLinux_, goog$userAgent$detectedX11_, goog$userAgent$getUserAgentString = function() { + return goog$global.navigator ? goog$global.navigator.userAgent : null +}, goog$userAgent$getNavigator = function() { + return goog$global.navigator +}; +goog$userAgent$detectedCamino_ = goog$userAgent$detectedGecko_ = goog$userAgent$detectedMobile_ = goog$userAgent$detectedWebkit_ = goog$userAgent$detectedIe_ = goog$userAgent$detectedOpera_ = false; +var JSCompiler_inline_ua_15; +if(JSCompiler_inline_ua_15 = goog$userAgent$getUserAgentString()) { + var JSCompiler_inline_navigator$$1_16 = goog$userAgent$getNavigator(); + goog$userAgent$detectedOpera_ = JSCompiler_inline_ua_15.indexOf("Opera") == 0; + goog$userAgent$detectedIe_ = !goog$userAgent$detectedOpera_ && JSCompiler_inline_ua_15.includes("MSIE"); + goog$userAgent$detectedMobile_ = (goog$userAgent$detectedWebkit_ = !goog$userAgent$detectedOpera_ && JSCompiler_inline_ua_15.includes("WebKit")) && JSCompiler_inline_ua_15.includes("Mobile"); + goog$userAgent$detectedCamino_ = (goog$userAgent$detectedGecko_ = !goog$userAgent$detectedOpera_ && !goog$userAgent$detectedWebkit_ && JSCompiler_inline_navigator$$1_16.product == "Gecko") && JSCompiler_inline_navigator$$1_16.vendor == "Camino" +}var goog$userAgent$OPERA = goog$userAgent$detectedOpera_, goog$userAgent$IE = goog$userAgent$detectedIe_, goog$userAgent$GECKO = goog$userAgent$detectedGecko_, goog$userAgent$WEBKIT = goog$userAgent$detectedWebkit_, goog$userAgent$MOBILE = goog$userAgent$detectedMobile_, goog$userAgent$PLATFORM, JSCompiler_inline_navigator$$2_19 = goog$userAgent$getNavigator(); +goog$userAgent$PLATFORM = JSCompiler_inline_navigator$$2_19 && JSCompiler_inline_navigator$$2_19.platform || ""; +goog$userAgent$detectedMac_ = goog$string$contains(goog$userAgent$PLATFORM, "Mac"); +goog$userAgent$detectedWindows_ = goog$string$contains(goog$userAgent$PLATFORM, "Win"); +goog$userAgent$detectedLinux_ = goog$string$contains(goog$userAgent$PLATFORM, "Linux"); +goog$userAgent$detectedX11_ = !!goog$userAgent$getNavigator() && goog$string$contains(goog$userAgent$getNavigator().appVersion || "", "X11"); +var goog$userAgent$VERSION, JSCompiler_inline_version$$6_26 = "", JSCompiler_inline_re$$2_27; +if(goog$userAgent$OPERA && goog$global.opera) { + var JSCompiler_inline_operaVersion_28 = goog$global.opera.version; + JSCompiler_inline_version$$6_26 = typeof JSCompiler_inline_operaVersion_28 == "function" ? JSCompiler_inline_operaVersion_28() : JSCompiler_inline_operaVersion_28 +}else { + if(goog$userAgent$GECKO)JSCompiler_inline_re$$2_27 = /rv\:([^\);]+)(\)|;)/; + else if(goog$userAgent$IE)JSCompiler_inline_re$$2_27 = /MSIE\s+([^\);]+)(\)|;)/; + else if(goog$userAgent$WEBKIT)JSCompiler_inline_re$$2_27 = /WebKit\/(\S+)/; + if(JSCompiler_inline_re$$2_27) { + var JSCompiler_inline_arr$$41_29 = JSCompiler_inline_re$$2_27.exec(goog$userAgent$getUserAgentString()); + JSCompiler_inline_version$$6_26 = JSCompiler_inline_arr$$41_29 ? JSCompiler_inline_arr$$41_29[1] : "" + } +}goog$userAgent$VERSION = JSCompiler_inline_version$$6_26; +var goog$userAgent$isVersionCache_ = {}, goog$userAgent$isVersion = function(version) { + return goog$userAgent$isVersionCache_[version] || (goog$userAgent$isVersionCache_[version] = goog$string$compareVersions(goog$userAgent$VERSION, version) >= 0) +};var goog$dom$getWindow = function(opt_doc) { + return opt_doc ? goog$dom$getWindow_(opt_doc) : window +}, goog$dom$getWindow_ = function(doc) { + if(doc.parentWindow)return doc.parentWindow; + if(goog$userAgent$WEBKIT && !goog$userAgent$isVersion("500") && !goog$userAgent$MOBILE) { + var scriptElement = doc.createElement("script"); + scriptElement.innerHTML = "document.parentWindow=window"; + var parentElement = doc.documentElement; + parentElement.appendChild(scriptElement); + parentElement.removeChild(scriptElement); + return doc.parentWindow + }return doc.defaultView +}, goog$dom$appendChild = function(parent, child) { + parent.appendChild(child) +}, goog$dom$BAD_CONTAINS_WEBKIT_ = goog$userAgent$WEBKIT && goog$userAgent$isVersion("522"), goog$dom$contains = function(parent, descendant) { + if(typeof parent.contains != "undefined" && !goog$dom$BAD_CONTAINS_WEBKIT_ && descendant.nodeType == 1)return parent == descendant || parent.contains(descendant); + if(typeof parent.compareDocumentPosition != "undefined")return parent == descendant || Boolean(parent.compareDocumentPosition(descendant) & 16); + for(;descendant && parent != descendant;)descendant = descendant.parentNode; + return descendant == parent +}, goog$dom$compareNodeOrder = function(node1, node2) { + if(node1 == node2)return 0; + if(node1.compareDocumentPosition)return node1.compareDocumentPosition(node2) & 2 ? 1 : -1; + if("sourceIndex" in node1 || node1.parentNode && "sourceIndex" in node1.parentNode) { + var isElement1 = node1.nodeType == 1, isElement2 = node2.nodeType == 1; + if(isElement1 && isElement2)return node1.sourceIndex - node2.sourceIndex; + else { + var parent1 = node1.parentNode, parent2 = node2.parentNode; + if(parent1 == parent2)return goog$dom$compareSiblingOrder_(node1, node2); + if(!isElement1 && goog$dom$contains(parent1, node2))return-1 * goog$dom$compareParentsDescendantNodeIe_(node1, node2); + if(!isElement2 && goog$dom$contains(parent2, node1))return goog$dom$compareParentsDescendantNodeIe_(node2, node1); + return(isElement1 ? node1.sourceIndex : parent1.sourceIndex) - (isElement2 ? node2.sourceIndex : parent2.sourceIndex) + } + }var doc = goog$dom$getOwnerDocument(node1), range1, range2; + range1 = doc.createRange(); + range1.selectNode(node1); + range1.collapse(true); + range2 = doc.createRange(); + range2.selectNode(node2); + range2.collapse(true); + return range1.compareBoundaryPoints(goog$global.Range.START_TO_END, range2) +}, goog$dom$compareParentsDescendantNodeIe_ = function(textNode, node) { + var parent = textNode.parentNode; + if(parent == node)return-1; + for(var sibling = node;sibling.parentNode != parent;)sibling = sibling.parentNode; + return goog$dom$compareSiblingOrder_(sibling, textNode) +}, goog$dom$compareSiblingOrder_ = function(node1, node2) { + for(var s = node2;s = s.previousSibling;)if(s == node1)return-1; + return 1 +}, goog$dom$findCommonAncestor = function() { + var i, count = arguments.length; + if(count) { + if(count == 1)return arguments[0] + }else return null; + var paths = [], minLength = Infinity; + for(i = 0;i < count;i++) { + for(var ancestors = [], node = arguments[i];node;) { + ancestors.unshift(node); + node = node.parentNode + }paths.push(ancestors); + minLength = Math.min(minLength, ancestors.length) + }var output = null; + for(i = 0;i < minLength;i++) { + for(var first = paths[0][i], j = 1;j < count;j++)if(first != paths[j][i])return output; + output = first + }return output +}, goog$dom$getOwnerDocument = function(node) { + // Added 'editorDoc' as hack for browsers that don't support node.ownerDocument + return node.nodeType == 9 ? node : node.ownerDocument || node.document || editorDoc +}, goog$dom$DomHelper = function(opt_document) { + this.document_ = opt_document || goog$global.document || document +}; +goog$dom$DomHelper.prototype.getDocument = function() { + return this.document_ +}; +goog$dom$DomHelper.prototype.createElement = function(name) { + return this.document_.createElement(name) +}; +goog$dom$DomHelper.prototype.getWindow = function() { + return goog$dom$getWindow_(this.document_) +}; +goog$dom$DomHelper.prototype.appendChild = goog$dom$appendChild; +goog$dom$DomHelper.prototype.contains = goog$dom$contains;var goog$Disposable = function() { +};if("StopIteration" in goog$global)var goog$iter$StopIteration = goog$global.StopIteration; +else goog$iter$StopIteration = Error("StopIteration"); +var goog$iter$Iterator = function() { +}; +goog$iter$Iterator.prototype.next = function() { + throw goog$iter$StopIteration; +}; +goog$iter$Iterator.prototype.__iterator__ = function() { + return this +};var goog$debug$exposeException = function(err, opt_fn) { + try { + var e, JSCompiler_inline_href_34; + JSCompiler_inline_label_goog$getObjectByName_61: { + for(var JSCompiler_inline_parts = "window.location.href".split("."), JSCompiler_inline_cur = goog$global, JSCompiler_inline_part;JSCompiler_inline_part = JSCompiler_inline_parts.shift();)if(JSCompiler_inline_cur[JSCompiler_inline_part])JSCompiler_inline_cur = JSCompiler_inline_cur[JSCompiler_inline_part]; + else { + JSCompiler_inline_href_34 = null; + break JSCompiler_inline_label_goog$getObjectByName_61 + }JSCompiler_inline_href_34 = JSCompiler_inline_cur + }e = typeof err == "string" ? {message:err, name:"Unknown error", lineNumber:"Not available", fileName:JSCompiler_inline_href_34, stack:"Not available"} : !err.lineNumber || !err.fileName || !err.stack ? {message:err.message, name:err.name, lineNumber:err.lineNumber || err.line || "Not available", fileName:err.fileName || err.filename || err.sourceURL || JSCompiler_inline_href_34, stack:err.stack || "Not available"} : err; + var error = "Message: " + goog$string$htmlEscape(e.message) + '\nUrl: ' + e.fileName + "\nLine: " + e.lineNumber + "\n\nBrowser stack:\n" + goog$string$htmlEscape(e.stack + "-> ") + "[end]\n\nJS stack traversal:\n" + goog$string$htmlEscape(goog$debug$getStacktrace(opt_fn) + "-> "); + return error + }catch(e2) { + return"Exception trying to expose exception! You win, we lose. " + e2 + } +}, goog$debug$getStacktrace = function(opt_fn) { + return goog$debug$getStacktraceHelper_(opt_fn || arguments.callee.caller, []) +}, goog$debug$getStacktraceHelper_ = function(fn, visited) { + var sb = [], JSCompiler_inline_result_36; + JSCompiler_inline_label_goog$array$contains_41:JSCompiler_inline_result_36 = visited.contains ? visited.contains(fn) : goog$array$indexOf(visited, fn) > -1; + if(JSCompiler_inline_result_36)sb.push("[...circular reference...]"); + else if(fn && visited.length < 50) { + sb.push(goog$debug$getFunctionName(fn) + "("); + for(var args = fn.arguments, i = 0;i < args.length;i++) { + i > 0 && sb.push(", "); + var argDesc, arg = args[i]; + switch(typeof arg) { + case "object": + argDesc = arg ? "object" : "null"; + break; + case "string": + argDesc = arg; + break; + case "number": + argDesc = String(arg); + break; + case "boolean": + argDesc = arg ? "true" : "false"; + break; + case "function": + argDesc = (argDesc = goog$debug$getFunctionName(arg)) ? argDesc : "[fn]"; + break; + case "undefined": + ; + default: + argDesc = typeof arg; + break + } + if(argDesc.length > 40)argDesc = argDesc.substr(0, 40) + "..."; + sb.push(argDesc) + }visited.push(fn); + sb.push(")\n"); + try { + sb.push(goog$debug$getStacktraceHelper_(fn.caller, visited)) + }catch(e) { + sb.push("[exception trying to get caller]\n") + } + }else fn ? sb.push("[...long stack...]") : sb.push("[end]"); + return sb.join("") +}, goog$debug$getFunctionName = function(fn) { + var functionSource = String(fn); + if(!goog$debug$fnNameCache_[functionSource]) { + var matches = /function ([^\(]+)/.exec(functionSource); + if(matches) { + var method = matches[1]; + goog$debug$fnNameCache_[functionSource] = method + }else goog$debug$fnNameCache_[functionSource] = "[Anonymous]" + }return goog$debug$fnNameCache_[functionSource] +}, goog$debug$fnNameCache_ = {};var goog$debug$LogRecord = function(level, msg, loggerName, opt_time, opt_sequenceNumber) { + this.sequenceNumber_ = typeof opt_sequenceNumber == "number" ? opt_sequenceNumber : goog$debug$LogRecord$nextSequenceNumber_++; + this.time_ = opt_time || goog$now(); + this.level_ = level; + this.msg_ = msg; + this.loggerName_ = loggerName +}; +goog$debug$LogRecord.prototype.exception_ = null; +goog$debug$LogRecord.prototype.exceptionText_ = null; +var goog$debug$LogRecord$nextSequenceNumber_ = 0; +goog$debug$LogRecord.prototype.setException = function(exception) { + this.exception_ = exception +}; +goog$debug$LogRecord.prototype.setExceptionText = function(text) { + this.exceptionText_ = text +}; +goog$debug$LogRecord.prototype.setLevel = function(level) { + this.level_ = level +};var goog$debug$Logger = function(name) { + this.name_ = name; + this.parent_ = null; + this.children_ = {}; + this.handlers_ = [] +}; +goog$debug$Logger.prototype.level_ = null; +var goog$debug$Logger$Level = function(name, value) { + this.name = name; + this.value = value +}; +goog$debug$Logger$Level.prototype.toString = function() { + return this.name +}; +new goog$debug$Logger$Level("OFF", Infinity); +new goog$debug$Logger$Level("SHOUT", 1200); +var goog$debug$Logger$Level$SEVERE = new goog$debug$Logger$Level("SEVERE", 1000), goog$debug$Logger$Level$WARNING = new goog$debug$Logger$Level("WARNING", 900); +new goog$debug$Logger$Level("INFO", 800); +var goog$debug$Logger$Level$CONFIG = new goog$debug$Logger$Level("CONFIG", 700); +new goog$debug$Logger$Level("FINE", 500); +new goog$debug$Logger$Level("FINER", 400); +new goog$debug$Logger$Level("FINEST", 300); +new goog$debug$Logger$Level("ALL", 0); +goog$debug$Logger.prototype.setLevel = function(level) { + this.level_ = level +}; +goog$debug$Logger.prototype.isLoggable = function(level) { + if(this.level_)return level.value >= this.level_.value; + if(this.parent_)return this.parent_.isLoggable(level); + return false +}; +goog$debug$Logger.prototype.log = function(level, msg, opt_exception) { + this.isLoggable(level) && this.logRecord(this.getLogRecord(level, msg, opt_exception)) +}; +goog$debug$Logger.prototype.getLogRecord = function(level, msg, opt_exception) { + var logRecord = new goog$debug$LogRecord(level, String(msg), this.name_); + if(opt_exception) { + logRecord.setException(opt_exception); + logRecord.setExceptionText(goog$debug$exposeException(opt_exception, arguments.callee.caller)) + }return logRecord +}; +goog$debug$Logger.prototype.severe = function(msg, opt_exception) { + this.log(goog$debug$Logger$Level$SEVERE, msg, opt_exception) +}; +goog$debug$Logger.prototype.warning = function(msg, opt_exception) { + this.log(goog$debug$Logger$Level$WARNING, msg, opt_exception) +}; +goog$debug$Logger.prototype.logRecord = function(logRecord) { + if(this.isLoggable(logRecord.level_))for(var target = this;target;) { + target.callPublish_(logRecord); + target = target.parent_ + } +}; +goog$debug$Logger.prototype.callPublish_ = function(logRecord) { + for(var i = 0;i < this.handlers_.length;i++)this.handlers_[i](logRecord) +}; +goog$debug$Logger.prototype.setParent_ = function(parent) { + this.parent_ = parent +}; +goog$debug$Logger.prototype.addChild_ = function(name, logger) { + this.children_[name] = logger +}; +var goog$debug$LogManager$loggers_ = {}, goog$debug$LogManager$rootLogger_ = null, goog$debug$LogManager$getLogger = function(name) { + if(!goog$debug$LogManager$rootLogger_) { + goog$debug$LogManager$rootLogger_ = new goog$debug$Logger(""); + goog$debug$LogManager$loggers_[""] = goog$debug$LogManager$rootLogger_; + goog$debug$LogManager$rootLogger_.setLevel(goog$debug$Logger$Level$CONFIG) + }return name in goog$debug$LogManager$loggers_ ? goog$debug$LogManager$loggers_[name] : goog$debug$LogManager$createLogger_(name) +}, goog$debug$LogManager$createLogger_ = function(name) { + var logger = new goog$debug$Logger(name), parts = name.split("."), leafName = parts[parts.length - 1]; + parts.length = parts.length - 1; + var parentName = parts.join("."), parentLogger = goog$debug$LogManager$getLogger(parentName); + parentLogger.addChild_(leafName, logger); + logger.setParent_(parentLogger); + return goog$debug$LogManager$loggers_[name] = logger +};var goog$dom$SavedRange = function() { + goog$Disposable.call(this) +}; +goog$inherits(goog$dom$SavedRange, goog$Disposable); +goog$debug$LogManager$getLogger("goog.dom.SavedRange");var goog$dom$TagIterator = function(opt_node, opt_reversed, opt_unconstrained, opt_tagType, opt_depth) { + this.reversed = !!opt_reversed; + opt_node && this.setPosition(opt_node, opt_tagType); + this.depth = opt_depth != undefined ? opt_depth : this.tagType || 0; + if(this.reversed)this.depth *= -1; + this.constrained = !opt_unconstrained +}; +goog$inherits(goog$dom$TagIterator, goog$iter$Iterator); +goog$dom$TagIterator.prototype.node = null; +goog$dom$TagIterator.prototype.tagType = null; +goog$dom$TagIterator.prototype.started_ = false; +goog$dom$TagIterator.prototype.setPosition = function(node, opt_tagType, opt_depth) { + if(this.node = node)this.tagType = typeof opt_tagType == "number" ? opt_tagType : this.node.nodeType != 1 ? 0 : this.reversed ? -1 : 1; + if(typeof opt_depth == "number")this.depth = opt_depth +}; +goog$dom$TagIterator.prototype.next = function() { + var node; + if(this.started_) { + if(!this.node || this.constrained && this.depth == 0)throw goog$iter$StopIteration;node = this.node; + var startType = this.reversed ? -1 : 1; + if(this.tagType == startType) { + var child = this.reversed ? node.lastChild : node.firstChild; + child ? this.setPosition(child) : this.setPosition(node, startType * -1) + }else { + var sibling = this.reversed ? node.previousSibling : node.nextSibling; + sibling ? this.setPosition(sibling) : this.setPosition(node.parentNode, startType * -1) + }this.depth += this.tagType * (this.reversed ? -1 : 1) + }else this.started_ = true; + node = this.node; + if(!this.node)throw goog$iter$StopIteration;return node +}; +goog$dom$TagIterator.prototype.isStartTag = function() { + return this.tagType == 1 +};var goog$dom$AbstractRange = function() { +}; +goog$dom$AbstractRange.prototype.getTextRanges = function() { + for(var output = [], i = 0, len = this.getTextRangeCount();i < len;i++)output.push(this.getTextRange(i)); + return output +}; +goog$dom$AbstractRange.prototype.getAnchorNode = function() { + return this.isReversed() ? this.getEndNode() : this.getStartNode() +}; +goog$dom$AbstractRange.prototype.getAnchorOffset = function() { + return this.isReversed() ? this.getEndOffset() : this.getStartOffset() +}; +goog$dom$AbstractRange.prototype.getFocusNode = function() { + return this.isReversed() ? this.getStartNode() : this.getEndNode() +}; +goog$dom$AbstractRange.prototype.getFocusOffset = function() { + return this.isReversed() ? this.getStartOffset() : this.getEndOffset() +}; +goog$dom$AbstractRange.prototype.isReversed = function() { + return false +}; +goog$dom$AbstractRange.prototype.getDocument = function() { + return goog$dom$getOwnerDocument(goog$userAgent$IE ? this.getContainer() : this.getStartNode()) +}; +goog$dom$AbstractRange.prototype.getWindow = function() { + return goog$dom$getWindow(this.getDocument()) +}; +goog$dom$AbstractRange.prototype.containsNode = function(node, opt_allowPartial) { + return this.containsRange(goog$dom$TextRange$createFromNodeContents(node, undefined), opt_allowPartial) +}; +var goog$dom$RangeIterator = function(node, opt_reverse) { + goog$dom$TagIterator.call(this, node, opt_reverse, true) +}; +goog$inherits(goog$dom$RangeIterator, goog$dom$TagIterator);var goog$dom$AbstractMultiRange = function() { +}; +goog$inherits(goog$dom$AbstractMultiRange, goog$dom$AbstractRange); +goog$dom$AbstractMultiRange.prototype.containsRange = function(otherRange, opt_allowPartial) { + var ranges = this.getTextRanges(), otherRanges = otherRange.getTextRanges(), fn = opt_allowPartial ? goog$array$some : goog$array$every; + return fn(otherRanges, function(otherRange) { + return goog$array$some(ranges, function(range) { + return range.containsRange(otherRange, opt_allowPartial) + }) + }) +};var goog$dom$TextRangeIterator = function(startNode, startOffset, endNode, endOffset, opt_reverse) { + var goNext; + if(startNode) { + this.startNode_ = startNode; + this.startOffset_ = startOffset; + this.endNode_ = endNode; + this.endOffset_ = endOffset; + if(startNode.nodeType == 1 && startNode.tagName != "BR") { + var startChildren = startNode.childNodes, candidate = startChildren[startOffset]; + if(candidate) { + this.startNode_ = candidate; + this.startOffset_ = 0 + }else { + if(startChildren.length)this.startNode_ = goog$array$peek(startChildren); + goNext = true + } + }if(endNode.nodeType == 1)if(this.endNode_ = endNode.childNodes[endOffset])this.endOffset_ = 0; + else this.endNode_ = endNode + }goog$dom$RangeIterator.call(this, opt_reverse ? this.endNode_ : this.startNode_, opt_reverse); + if(goNext)try { + this.next() + }catch(e) { + if(e != goog$iter$StopIteration)throw e; + } +}; +goog$inherits(goog$dom$TextRangeIterator, goog$dom$RangeIterator); +goog$dom$TextRangeIterator.prototype.startNode_ = null; +goog$dom$TextRangeIterator.prototype.endNode_ = null; +goog$dom$TextRangeIterator.prototype.startOffset_ = 0; +goog$dom$TextRangeIterator.prototype.endOffset_ = 0; +goog$dom$TextRangeIterator.prototype.getStartNode = function() { + return this.startNode_ +}; +goog$dom$TextRangeIterator.prototype.getEndNode = function() { + return this.endNode_ +}; +goog$dom$TextRangeIterator.prototype.isLast = function() { + return this.started_ && this.node == this.endNode_ && (!this.endOffset_ || !this.isStartTag()) +}; +goog$dom$TextRangeIterator.prototype.next = function() { + if(this.isLast())throw goog$iter$StopIteration;return goog$dom$TextRangeIterator.superClass_.next.call(this) +};var goog$userAgent$jscript$DETECTED_HAS_JSCRIPT_, goog$userAgent$jscript$DETECTED_VERSION_, JSCompiler_inline_hasScriptEngine_44 = "ScriptEngine" in goog$global; +goog$userAgent$jscript$DETECTED_VERSION_ = (goog$userAgent$jscript$DETECTED_HAS_JSCRIPT_ = JSCompiler_inline_hasScriptEngine_44 && goog$global.ScriptEngine() == "JScript") ? goog$global.ScriptEngineMajorVersion() + "." + goog$global.ScriptEngineMinorVersion() + "." + goog$global.ScriptEngineBuildVersion() : "0";var goog$dom$browserrange$AbstractRange = function() { +}; +goog$dom$browserrange$AbstractRange.prototype.containsRange = function(range, opt_allowPartial) { + return this.containsBrowserRange(range.range_, opt_allowPartial) +}; +goog$dom$browserrange$AbstractRange.prototype.containsBrowserRange = function(range, opt_allowPartial) { + try { + return opt_allowPartial ? this.compareBrowserRangeEndpoints(range, 0, 1) >= 0 && this.compareBrowserRangeEndpoints(range, 1, 0) <= 0 : this.compareBrowserRangeEndpoints(range, 0, 0) >= 0 && this.compareBrowserRangeEndpoints(range, 1, 1) <= 0 + }catch(e) { + if(!goog$userAgent$IE)throw e;return false + } +}; +goog$dom$browserrange$AbstractRange.prototype.containsNode = function(node, opt_allowPartial) { + return this.containsRange(goog$userAgent$IE ? goog$dom$browserrange$IeRange$createFromNodeContents(node) : goog$userAgent$WEBKIT ? new goog$dom$browserrange$WebKitRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)) : goog$userAgent$GECKO ? new goog$dom$browserrange$GeckoRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)) : new goog$dom$browserrange$W3cRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)), opt_allowPartial) +}; +goog$dom$browserrange$AbstractRange.prototype.__iterator__ = function() { + return new goog$dom$TextRangeIterator(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset()) +};var goog$dom$browserrange$W3cRange = function(range) { + this.range_ = range +}; +goog$inherits(goog$dom$browserrange$W3cRange, goog$dom$browserrange$AbstractRange); +var goog$dom$browserrange$W3cRange$getBrowserRangeForNode = function(node) { + var nodeRange = goog$dom$getOwnerDocument(node).createRange(); + if(node.nodeType == 3) { + nodeRange.setStart(node, 0); + nodeRange.setEnd(node, node.length) + }else { + for(var tempNode, leaf = node;tempNode = leaf.firstChild;)leaf = tempNode; + nodeRange.setStart(leaf, 0); + for(leaf = node;tempNode = leaf.lastChild;)leaf = tempNode; + nodeRange.setEnd(leaf, leaf.nodeType == 1 ? leaf.childNodes.length : leaf.length) + }return nodeRange +}, goog$dom$browserrange$W3cRange$getBrowserRangeForNodes_ = function(startNode, startOffset, endNode, endOffset) { + var nodeRange = goog$dom$getOwnerDocument(startNode).createRange(); + nodeRange.setStart(startNode, startOffset); + nodeRange.setEnd(endNode, endOffset); + return nodeRange +}; +goog$dom$browserrange$W3cRange.prototype.getContainer = function() { + return this.range_.commonAncestorContainer +}; +goog$dom$browserrange$W3cRange.prototype.getStartNode = function() { + return this.range_.startContainer +}; +goog$dom$browserrange$W3cRange.prototype.getStartOffset = function() { + return this.range_.startOffset +}; +goog$dom$browserrange$W3cRange.prototype.getEndNode = function() { + return this.range_.endContainer +}; +goog$dom$browserrange$W3cRange.prototype.getEndOffset = function() { + return this.range_.endOffset +}; +goog$dom$browserrange$W3cRange.prototype.compareBrowserRangeEndpoints = function(range, thisEndpoint, otherEndpoint) { + return this.range_.compareBoundaryPoints(otherEndpoint == 1 ? thisEndpoint == 1 ? goog$global.Range.START_TO_START : goog$global.Range.START_TO_END : thisEndpoint == 1 ? goog$global.Range.END_TO_START : goog$global.Range.END_TO_END, range) +}; +goog$dom$browserrange$W3cRange.prototype.isCollapsed = function() { + return this.range_.collapsed +}; +goog$dom$browserrange$W3cRange.prototype.select = function(reverse) { + var win = goog$dom$getWindow(goog$dom$getOwnerDocument(this.getStartNode())); + this.selectInternal(win.getSelection(), reverse) +}; +goog$dom$browserrange$W3cRange.prototype.selectInternal = function(selection) { + selection.addRange(this.range_) +}; +goog$dom$browserrange$W3cRange.prototype.collapse = function(toStart) { + this.range_.collapse(toStart) +};var goog$dom$browserrange$GeckoRange = function(range) { + goog$dom$browserrange$W3cRange.call(this, range) +}; +goog$inherits(goog$dom$browserrange$GeckoRange, goog$dom$browserrange$W3cRange); +goog$dom$browserrange$GeckoRange.prototype.selectInternal = function(selection, reversed) { + var anchorNode = reversed ? this.getEndNode() : this.getStartNode(), anchorOffset = reversed ? this.getEndOffset() : this.getStartOffset(), focusNode = reversed ? this.getStartNode() : this.getEndNode(), focusOffset = reversed ? this.getStartOffset() : this.getEndOffset(); + selection.collapse(anchorNode, anchorOffset); + if(anchorNode != focusNode || anchorOffset != focusOffset)selection.extend(focusNode, focusOffset) +};var goog$dom$browserrange$IeRange = function(range, doc) { + this.range_ = range; + this.doc_ = doc +}; +goog$inherits(goog$dom$browserrange$IeRange, goog$dom$browserrange$AbstractRange); +var goog$dom$browserrange$IeRange$logger_ = goog$debug$LogManager$getLogger("goog.dom.browserrange.IeRange"), goog$dom$browserrange$IeRange$getBrowserRangeForNode_ = function(node) { + var nodeRange = goog$dom$getOwnerDocument(node).body.createTextRange(); + if(node.nodeType == 1)nodeRange.moveToElementText(node); + else { + for(var offset = 0, sibling = node;sibling = sibling.previousSibling;) { + var nodeType = sibling.nodeType; + if(nodeType == 3)offset += sibling.length; + else if(nodeType == 1) { + nodeRange.moveToElementText(sibling); + break + } + }sibling || nodeRange.moveToElementText(node.parentNode); + nodeRange.collapse(!sibling); + offset && nodeRange.move("character", offset); + nodeRange.moveEnd("character", node.length) + }return nodeRange +}, goog$dom$browserrange$IeRange$getBrowserRangeForNodes_ = function(startNode, startOffset, endNode, endOffset) { + var child, collapse = false; + if(startNode.nodeType == 1) { + startOffset > startNode.childNodes.length && goog$dom$browserrange$IeRange$logger_.severe("Cannot have startOffset > startNode child count"); + child = startNode.childNodes[startOffset]; + collapse = !child; + startNode = child || startNode; + startOffset = 0 + }var leftRange = goog$dom$browserrange$IeRange$getBrowserRangeForNode_(startNode); + startOffset && leftRange.move("character", startOffset); + collapse && leftRange.collapse(false); + collapse = false; + if(endNode.nodeType == 1) { + startOffset > startNode.childNodes.length && goog$dom$browserrange$IeRange$logger_.severe("Cannot have endOffset > endNode child count"); + endNode = (child = endNode.childNodes[endOffset]) || endNode; + if(endNode.tagName == "BR")endOffset = 1; + else { + endOffset = 0; + collapse = !child + } + }var rightRange = goog$dom$browserrange$IeRange$getBrowserRangeForNode_(endNode); + rightRange.collapse(!collapse); + endOffset && rightRange.moveEnd("character", endOffset); + leftRange.setEndPoint("EndToEnd", rightRange); + return leftRange +}, goog$dom$browserrange$IeRange$createFromNodeContents = function(node) { + var range = new goog$dom$browserrange$IeRange(goog$dom$browserrange$IeRange$getBrowserRangeForNode_(node), goog$dom$getOwnerDocument(node)); + range.parentNode_ = node; + return range +}; +goog$dom$browserrange$IeRange.prototype.parentNode_ = null; +goog$dom$browserrange$IeRange.prototype.startNode_ = null; +goog$dom$browserrange$IeRange.prototype.endNode_ = null; +goog$dom$browserrange$IeRange.prototype.clearCachedValues_ = function() { + this.parentNode_ = this.startNode_ = this.endNode_ = null +}; +goog$dom$browserrange$IeRange.prototype.getContainer = function() { + if(!this.parentNode_) { + for(var selectText = this.range_.text, i = 1;selectText.charAt(selectText.length - i) == " ";i++)this.range_.moveEnd("character", -1); + for(var parent = this.range_.parentElement(), htmlText = this.range_.htmlText.replace(/(\r\n|\r|\n)+/g, " ");htmlText.length > parent.outerHTML.replace(/(\r\n|\r|\n)+/g, " ").length;)parent = parent.parentNode; + for(;parent.childNodes.length == 1 && parent.innerText == (parent.firstChild.nodeType == 3 ? parent.firstChild.nodeValue : parent.firstChild.innerText);) { + if(parent.firstChild.tagName == "IMG")break; + parent = parent.firstChild + }if(selectText.length == 0)parent = this.findDeepestContainer_(parent); + this.parentNode_ = parent + }return this.parentNode_ +}; +goog$dom$browserrange$IeRange.prototype.findDeepestContainer_ = function(node) { + for(var childNodes = node.childNodes, i = 0, len = childNodes.length;i < len;i++) { + var child = childNodes[i]; + if(child.nodeType == 1)if(this.range_.inRange(goog$dom$browserrange$IeRange$getBrowserRangeForNode_(child)))return this.findDeepestContainer_(child) + }return node +}; +goog$dom$browserrange$IeRange.prototype.getStartNode = function() { + return this.startNode_ || (this.startNode_ = this.getEndpointNode_(1)) +}; +goog$dom$browserrange$IeRange.prototype.getStartOffset = function() { + return this.getOffset_(1) +}; +goog$dom$browserrange$IeRange.prototype.getEndNode = function() { + return this.endNode_ || (this.endNode_ = this.getEndpointNode_(0)) +}; +goog$dom$browserrange$IeRange.prototype.getEndOffset = function() { + return this.getOffset_(0) +}; +goog$dom$browserrange$IeRange.prototype.containsRange = function(range, opt_allowPartial) { + return this.containsBrowserRange(range.range_, opt_allowPartial) +}; +goog$dom$browserrange$IeRange.prototype.compareBrowserRangeEndpoints = function(range, thisEndpoint, otherEndpoint) { + return this.range_.compareEndPoints((thisEndpoint == 1 ? "Start" : "End") + "To" + (otherEndpoint == 1 ? "Start" : "End"), range) +}; +goog$dom$browserrange$IeRange.prototype.getEndpointNode_ = function(endpoint, opt_node) { + var node = opt_node || this.getContainer(); + if(!node || !node.firstChild) { + if(endpoint == 0 && node.previousSibling && node.previousSibling.tagName == "BR" && this.getOffset_(endpoint, node) == 0)node = node.previousSibling; + return node.tagName == "BR" ? node.parentNode : node + }for(var child = endpoint == 1 ? node.firstChild : node.lastChild;child;) { + if(this.containsNode(child, true))return this.getEndpointNode_(endpoint, child); + child = endpoint == 1 ? child.nextSibling : child.previousSibling + }return node +}; +goog$dom$browserrange$IeRange.prototype.getOffset_ = function(endpoint, opt_container) { + var container = opt_container || (endpoint == 1 ? this.getStartNode() : this.getEndNode()); + if(container.nodeType == 1) { + for(var children = container.childNodes, len = children.length, i = endpoint == 1 ? 0 : len - 1;i >= 0 && i < len;) { + var child = children[i]; + if(this.containsNode(child, true)) { + endpoint == 0 && child.previousSibling && child.previousSibling.tagName == "BR" && this.getOffset_(endpoint, child) == 0 && i--; + break + }i += endpoint == 1 ? 1 : -1 + }return i == -1 ? 0 : i + }else { + var range = this.range_.duplicate(), nodeRange = goog$dom$browserrange$IeRange$getBrowserRangeForNode_(container); + range.setEndPoint(endpoint == 1 ? "EndToEnd" : "StartToStart", nodeRange); + var rangeLength = range.text.length; + return endpoint == 0 ? rangeLength : container.length - rangeLength + } +}; +goog$dom$browserrange$IeRange.prototype.isCollapsed = function() { + return this.range_.text == "" +}; +goog$dom$browserrange$IeRange.prototype.select = function() { + this.range_.select() +}; +goog$dom$browserrange$IeRange.prototype.collapse = function(toStart) { + this.range_.collapse(toStart); + if(toStart)this.endNode_ = this.startNode_; + else this.startNode_ = this.endNode_ +};var goog$dom$browserrange$WebKitRange = function(range) { + goog$dom$browserrange$W3cRange.call(this, range) +}; +goog$inherits(goog$dom$browserrange$WebKitRange, goog$dom$browserrange$W3cRange); +goog$dom$browserrange$WebKitRange.prototype.compareBrowserRangeEndpoints = function(range, thisEndpoint, otherEndpoint) { + if(goog$userAgent$isVersion("528"))return goog$dom$browserrange$WebKitRange.superClass_.compareBrowserRangeEndpoints.call(this, range, thisEndpoint, otherEndpoint); + return this.range_.compareBoundaryPoints(otherEndpoint == 1 ? thisEndpoint == 1 ? goog$global.Range.START_TO_START : goog$global.Range.END_TO_START : thisEndpoint == 1 ? goog$global.Range.START_TO_END : goog$global.Range.END_TO_END, range) +}; +goog$dom$browserrange$WebKitRange.prototype.selectInternal = function(selection, reversed) { + selection.removeAllRanges(); + reversed ? selection.setBaseAndExtent(this.getEndNode(), this.getEndOffset(), this.getStartNode(), this.getStartOffset()) : selection.setBaseAndExtent(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset()) +};var goog$dom$browserrange$createRangeFromNodes = function(startNode, startOffset, endNode, endOffset) { + return goog$userAgent$IE ? new goog$dom$browserrange$IeRange(goog$dom$browserrange$IeRange$getBrowserRangeForNodes_(startNode, startOffset, endNode, endOffset), goog$dom$getOwnerDocument(startNode)) : goog$userAgent$WEBKIT ? new goog$dom$browserrange$WebKitRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNodes_(startNode, startOffset, endNode, endOffset)) : goog$userAgent$GECKO ? new goog$dom$browserrange$GeckoRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNodes_(startNode, startOffset, + endNode, endOffset)) : new goog$dom$browserrange$W3cRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNodes_(startNode, startOffset, endNode, endOffset)) +};var goog$dom$TextRange = function() { +}; +goog$inherits(goog$dom$TextRange, goog$dom$AbstractRange); +var goog$dom$TextRange$createFromBrowserRangeWrapper_ = function(browserRange, opt_isReversed) { + var range = new goog$dom$TextRange; + range.browserRangeWrapper_ = browserRange; + range.isReversed_ = !!opt_isReversed; + return range +}, goog$dom$TextRange$createFromNodeContents = function(node, opt_isReversed) { + return goog$dom$TextRange$createFromBrowserRangeWrapper_(goog$userAgent$IE ? goog$dom$browserrange$IeRange$createFromNodeContents(node) : goog$userAgent$WEBKIT ? new goog$dom$browserrange$WebKitRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)) : goog$userAgent$GECKO ? new goog$dom$browserrange$GeckoRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)) : new goog$dom$browserrange$W3cRange(goog$dom$browserrange$W3cRange$getBrowserRangeForNode(node)), opt_isReversed) +}, goog$dom$TextRange$createFromNodes = function(anchorNode, anchorOffset, focusNode, focusOffset) { + var range = new goog$dom$TextRange; + range.isReversed_ = goog$dom$Range$isReversed(anchorNode, anchorOffset, focusNode, focusOffset); + if(anchorNode.tagName == "BR") { + var parent = anchorNode.parentNode; + anchorOffset = goog$array$indexOf(parent.childNodes, anchorNode); + anchorNode = parent + }if(focusNode.tagName == "BR") { + parent = focusNode.parentNode; + focusOffset = goog$array$indexOf(parent.childNodes, focusNode); + focusNode = parent + }if(range.isReversed_) { + range.startNode_ = focusNode; + range.startOffset_ = focusOffset; + range.endNode_ = anchorNode; + range.endOffset_ = anchorOffset + }else { + range.startNode_ = anchorNode; + range.startOffset_ = anchorOffset; + range.endNode_ = focusNode; + range.endOffset_ = focusOffset + }return range +}; +goog$dom$TextRange.prototype.browserRangeWrapper_ = null; +goog$dom$TextRange.prototype.startNode_ = null; +goog$dom$TextRange.prototype.startOffset_ = null; +goog$dom$TextRange.prototype.endNode_ = null; +goog$dom$TextRange.prototype.endOffset_ = null; +goog$dom$TextRange.prototype.isReversed_ = false; +goog$dom$TextRange.prototype.getType = function() { + return"text" +}; +goog$dom$TextRange.prototype.getBrowserRangeObject = function() { + return this.getBrowserRangeWrapper_().range_ +}; +goog$dom$TextRange.prototype.clearCachedValues_ = function() { + this.startNode_ = this.startOffset_ = this.endNode_ = this.endOffset_ = null +}; +goog$dom$TextRange.prototype.getTextRangeCount = function() { + return 1 +}; +goog$dom$TextRange.prototype.getTextRange = function() { + return this +}; +goog$dom$TextRange.prototype.getBrowserRangeWrapper_ = function() { + return this.browserRangeWrapper_ || (this.browserRangeWrapper_ = goog$dom$browserrange$createRangeFromNodes(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset())) +}; +goog$dom$TextRange.prototype.getContainer = function() { + return this.getBrowserRangeWrapper_().getContainer() +}; +goog$dom$TextRange.prototype.getStartNode = function() { + return this.startNode_ || (this.startNode_ = this.getBrowserRangeWrapper_().getStartNode()) +}; +goog$dom$TextRange.prototype.getStartOffset = function() { + return this.startOffset_ != null ? this.startOffset_ : (this.startOffset_ = this.getBrowserRangeWrapper_().getStartOffset()) +}; +goog$dom$TextRange.prototype.getEndNode = function() { + return this.endNode_ || (this.endNode_ = this.getBrowserRangeWrapper_().getEndNode()) +}; +goog$dom$TextRange.prototype.getEndOffset = function() { + return this.endOffset_ != null ? this.endOffset_ : (this.endOffset_ = this.getBrowserRangeWrapper_().getEndOffset()) +}; +goog$dom$TextRange.prototype.isReversed = function() { + return this.isReversed_ +}; +goog$dom$TextRange.prototype.containsRange = function(otherRange, opt_allowPartial) { + var otherRangeType = otherRange.getType(); + if(otherRangeType == "text")return this.getBrowserRangeWrapper_().containsRange(otherRange.getBrowserRangeWrapper_(), opt_allowPartial); + else if(otherRangeType == "control") { + var elements = otherRange.getElements(), fn = opt_allowPartial ? goog$array$some : goog$array$every; + return fn(elements, function(el) { + return this.containsNode(el, opt_allowPartial) + }, this) + } +}; +goog$dom$TextRange.prototype.isCollapsed = function() { + return this.getBrowserRangeWrapper_().isCollapsed() +}; +goog$dom$TextRange.prototype.__iterator__ = function() { + return new goog$dom$TextRangeIterator(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset()) +}; +goog$dom$TextRange.prototype.select = function() { + this.getBrowserRangeWrapper_().select(this.isReversed_) +}; +goog$dom$TextRange.prototype.saveUsingDom = function() { + return new goog$dom$DomSavedTextRange_(this) +}; +goog$dom$TextRange.prototype.collapse = function(toAnchor) { + var toStart = this.isReversed() ? !toAnchor : toAnchor; + this.browserRangeWrapper_ && this.browserRangeWrapper_.collapse(toStart); + if(toStart) { + this.endNode_ = this.startNode_; + this.endOffset_ = this.startOffset_ + }else { + this.startNode_ = this.endNode_; + this.startOffset_ = this.endOffset_ + }this.isReversed_ = false +}; +var goog$dom$DomSavedTextRange_ = function(range) { + this.anchorNode_ = range.getAnchorNode(); + this.anchorOffset_ = range.getAnchorOffset(); + this.focusNode_ = range.getFocusNode(); + this.focusOffset_ = range.getFocusOffset() +}; +goog$inherits(goog$dom$DomSavedTextRange_, goog$dom$SavedRange);var goog$dom$ControlRange = function() { +}; +goog$inherits(goog$dom$ControlRange, goog$dom$AbstractMultiRange); +goog$dom$ControlRange.prototype.range_ = null; +goog$dom$ControlRange.prototype.elements_ = null; +goog$dom$ControlRange.prototype.sortedElements_ = null; +goog$dom$ControlRange.prototype.clearCachedValues_ = function() { + this.sortedElements_ = this.elements_ = null +}; +goog$dom$ControlRange.prototype.getType = function() { + return"control" +}; +goog$dom$ControlRange.prototype.getBrowserRangeObject = function() { + return this.range_ || document.body.createControlRange() +}; +goog$dom$ControlRange.prototype.getTextRangeCount = function() { + return this.range_ ? this.range_.length : 0 +}; +goog$dom$ControlRange.prototype.getTextRange = function(i) { + return goog$dom$TextRange$createFromNodeContents(this.range_.item(i)) +}; +goog$dom$ControlRange.prototype.getContainer = function() { + return goog$dom$findCommonAncestor.apply(null, this.getElements()) +}; +goog$dom$ControlRange.prototype.getStartNode = function() { + return this.getSortedElements()[0] +}; +goog$dom$ControlRange.prototype.getStartOffset = function() { + return 0 +}; +goog$dom$ControlRange.prototype.getEndNode = function() { + var sorted = this.getSortedElements(), startsLast = goog$array$peek(sorted); + return goog$array$find(sorted, function(el) { + return goog$dom$contains(el, startsLast) + }) +}; +goog$dom$ControlRange.prototype.getEndOffset = function() { + return this.getEndNode().childNodes.length +}; +goog$dom$ControlRange.prototype.getElements = function() { + if(!this.elements_) { + this.elements_ = []; + if(this.range_)for(var i = 0;i < this.range_.length;i++)this.elements_.push(this.range_.item(i)) + }return this.elements_ +}; +goog$dom$ControlRange.prototype.getSortedElements = function() { + if(!this.sortedElements_) { + this.sortedElements_ = this.getElements().concat(); + this.sortedElements_.sort(function(a, b) { + return a.sourceIndex - b.sourceIndex + }) + }return this.sortedElements_ +}; +goog$dom$ControlRange.prototype.isCollapsed = function() { + return!this.range_ || !this.range_.length +}; +goog$dom$ControlRange.prototype.__iterator__ = function() { + return new goog$dom$ControlRangeIterator(this) +}; +goog$dom$ControlRange.prototype.select = function() { + this.range_ && this.range_.select() +}; +goog$dom$ControlRange.prototype.saveUsingDom = function() { + return new goog$dom$DomSavedControlRange_(this) +}; +goog$dom$ControlRange.prototype.collapse = function() { + this.range_ = null; + this.clearCachedValues_() +}; +var goog$dom$DomSavedControlRange_ = function(range) { + this.elements_ = range.getElements() +}; +goog$inherits(goog$dom$DomSavedControlRange_, goog$dom$SavedRange); +var goog$dom$ControlRangeIterator = function(range) { + if(range) { + this.elements_ = range.getSortedElements(); + this.startNode_ = this.elements_.shift(); + this.endNode_ = goog$array$peek(this.elements_) || this.startNode_ + }goog$dom$RangeIterator.call(this, this.startNode_, false) +}; +goog$inherits(goog$dom$ControlRangeIterator, goog$dom$RangeIterator); +goog$dom$ControlRangeIterator.prototype.startNode_ = null; +goog$dom$ControlRangeIterator.prototype.endNode_ = null; +goog$dom$ControlRangeIterator.prototype.elements_ = null; +goog$dom$ControlRangeIterator.prototype.getStartNode = function() { + return this.startNode_ +}; +goog$dom$ControlRangeIterator.prototype.getEndNode = function() { + return this.endNode_ +}; +goog$dom$ControlRangeIterator.prototype.isLast = function() { + return!this.depth && !this.elements_.length +}; +goog$dom$ControlRangeIterator.prototype.next = function() { + if(this.isLast())throw goog$iter$StopIteration;else if(!this.depth) { + var el = this.elements_.shift(); + this.setPosition(el, 1, 1); + return el + }return goog$dom$ControlRangeIterator.superClass_.next.call(this) +};var goog$dom$MultiRange = function() { + this.browserRanges_ = []; + this.ranges_ = []; + this.container_ = this.sortedRanges_ = null +}; +goog$inherits(goog$dom$MultiRange, goog$dom$AbstractMultiRange); +goog$dom$MultiRange.prototype.logger_ = goog$debug$LogManager$getLogger("goog.dom.MultiRange"); +goog$dom$MultiRange.prototype.clearCachedValues_ = function() { + this.ranges_ = []; + this.container_ = this.sortedRanges_ = null +}; +goog$dom$MultiRange.prototype.getType = function() { + return"mutli" +}; +goog$dom$MultiRange.prototype.getBrowserRangeObject = function() { + this.browserRanges_.length > 1 && this.logger_.warning("getBrowserRangeObject called on MultiRange with more than 1 range"); + return this.browserRanges_[0] +}; +goog$dom$MultiRange.prototype.getTextRangeCount = function() { + return this.browserRanges_.length +}; +goog$dom$MultiRange.prototype.getTextRange = function(i) { + this.ranges_[i] || (this.ranges_[i] = goog$dom$TextRange$createFromBrowserRangeWrapper_(goog$userAgent$IE ? new goog$dom$browserrange$IeRange(this.browserRanges_[i], goog$dom$getOwnerDocument(this.browserRanges_[i].parentElement())) : goog$userAgent$WEBKIT ? new goog$dom$browserrange$WebKitRange(this.browserRanges_[i]) : goog$userAgent$GECKO ? new goog$dom$browserrange$GeckoRange(this.browserRanges_[i]) : new goog$dom$browserrange$W3cRange(this.browserRanges_[i]), undefined)); + return this.ranges_[i] +}; +goog$dom$MultiRange.prototype.getContainer = function() { + if(!this.container_) { + for(var nodes = [], i = 0, len = this.getTextRangeCount();i < len;i++)nodes.push(this.getTextRange(i).getContainer()); + this.container_ = goog$dom$findCommonAncestor.apply(null, nodes) + }return this.container_ +}; +goog$dom$MultiRange.prototype.getSortedRanges = function() { + if(!this.sortedRanges_) { + this.sortedRanges_ = this.getTextRanges(); + this.sortedRanges_.sort(function(a, b) { + var aStartNode = a.getStartNode(), aStartOffset = a.getStartOffset(), bStartNode = b.getStartNode(), bStartOffset = b.getStartOffset(); + if(aStartNode == bStartNode && aStartOffset == bStartOffset)return 0; + return goog$dom$Range$isReversed(aStartNode, aStartOffset, bStartNode, bStartOffset) ? 1 : -1 + }) + }return this.sortedRanges_ +}; +goog$dom$MultiRange.prototype.getStartNode = function() { + return this.getSortedRanges()[0].getStartNode() +}; +goog$dom$MultiRange.prototype.getStartOffset = function() { + return this.getSortedRanges()[0].getStartOffset() +}; +goog$dom$MultiRange.prototype.getEndNode = function() { + return goog$array$peek(this.getSortedRanges()).getEndNode() +}; +goog$dom$MultiRange.prototype.getEndOffset = function() { + return goog$array$peek(this.getSortedRanges()).getEndOffset() +}; +goog$dom$MultiRange.prototype.isCollapsed = function() { + return this.browserRanges_.length == 0 || this.browserRanges_.length == 1 && this.getTextRange(0).isCollapsed() +}; +goog$dom$MultiRange.prototype.__iterator__ = function() { + return new goog$dom$MultiRangeIterator(this) +}; +goog$dom$MultiRange.prototype.select = function() { + var selection; + JSCompiler_inline_label_goog$dom$AbstractRange$getBrowserSelectionForWindow_50: { + var JSCompiler_inline_win = this.getWindow(); + if(JSCompiler_inline_win.getSelection)selection = JSCompiler_inline_win.getSelection(); + else { + var JSCompiler_inline_doc = JSCompiler_inline_win.document; + selection = JSCompiler_inline_doc.selection || JSCompiler_inline_doc.getSelection && JSCompiler_inline_doc.getSelection() + } + }selection.removeAllRanges(); + for(var i = 0, len = this.getTextRangeCount();i < len;i++)selection.addRange(this.getTextRange(i).getBrowserRangeObject()) +}; +goog$dom$MultiRange.prototype.saveUsingDom = function() { + return new goog$dom$DomSavedMultiRange_(this) +}; +goog$dom$MultiRange.prototype.collapse = function(toAnchor) { + if(!this.isCollapsed()) { + var range = toAnchor ? this.getTextRange(0) : this.getTextRange(this.getTextRangeCount() - 1); + this.clearCachedValues_(); + range.collapse(toAnchor); + this.ranges_ = [range]; + this.sortedRanges_ = [range]; + this.browserRanges_ = [range.getBrowserRangeObject()] + } +}; +var goog$dom$DomSavedMultiRange_ = function(range) { + this.savedRanges_ = goog$array$map(range.getTextRanges(), function(range) { + return range.saveUsingDom() + }) +}; +goog$inherits(goog$dom$DomSavedMultiRange_, goog$dom$SavedRange); +var goog$dom$MultiRangeIterator = function(range) { + if(range) { + this.ranges_ = range.getSortedRanges(); + if(this.ranges_.length) { + this.startNode_ = this.ranges_[0].getStartNode(); + this.endNode_ = goog$array$peek(this.ranges_).getEndNode() + } + }goog$dom$RangeIterator.call(this, this.startNode_, false) +}; +goog$inherits(goog$dom$MultiRangeIterator, goog$dom$RangeIterator); +goog$dom$MultiRangeIterator.prototype.startNode_ = null; +goog$dom$MultiRangeIterator.prototype.endNode_ = null; +goog$dom$MultiRangeIterator.prototype.ranges_ = null; +goog$dom$MultiRangeIterator.prototype.getStartNode = function() { + return this.startNode_ +}; +goog$dom$MultiRangeIterator.prototype.getEndNode = function() { + return this.endNode_ +}; +goog$dom$MultiRangeIterator.prototype.isLast = function() { + return this.ranges_.length == 1 && this.ranges_[0].isLast() +}; +goog$dom$MultiRangeIterator.prototype.next = function() { + do try { + this.ranges_[0].next(); + break + }catch(ex) { + if(ex != goog$iter$StopIteration)throw ex;this.ranges_.shift() + }while(this.ranges_.length); + if(this.ranges_.length) { + var range = this.ranges_[0]; + this.setPosition(range.node, range.tagType, range.depth); + return range.node + }else throw goog$iter$StopIteration; +};var goog$dom$Range$createCaret = function(node, offset) { + return goog$dom$TextRange$createFromNodes(node, offset, node, offset) +}, goog$dom$Range$createFromNodes = function(startNode, startOffset, endNode, endOffset) { + return goog$dom$TextRange$createFromNodes(startNode, startOffset, endNode, endOffset) +}, goog$dom$Range$isReversed = function(anchorNode, anchorOffset, focusNode, focusOffset) { + if(anchorNode == focusNode)return focusOffset < anchorOffset; + var child; + if(anchorNode.nodeType == 1 && anchorOffset)if(child = anchorNode.childNodes[anchorOffset]) { + anchorNode = child; + anchorOffset = 0 + }else if(goog$dom$contains(anchorNode, focusNode))return true; + if(focusNode.nodeType == 1 && focusOffset)if(child = focusNode.childNodes[focusOffset]) { + focusNode = child; + focusOffset = 0 + }else if(goog$dom$contains(focusNode, anchorNode))return false; + return(goog$dom$compareNodeOrder(anchorNode, focusNode) || anchorOffset - focusOffset) > 0 +};window.createCaret = goog$dom$Range$createCaret; +window.createFromNodes = goog$dom$Range$createFromNodes; +try { + goog$dom$Range$createCaret(document.body, 0).select() +}catch(e$$13) { +}; + +/************************************************** + Trace: + 56.427 Start Handling request + 0 56.427 Start Building cUnit + 1 56.428 Done 1 ms Building cUnit + 0 56.428 Start Checking memcacheg + 0 56.428 Start Connecting to memcacheg + 8 56.436 Done 8 ms Connecting to memcacheg + 1 56.437 Done 9 ms Checking memcacheg + 0 56.437 Done 10 ms Handling request +**************************************************/ diff --git a/editor/libeditor/tests/browserscope/lib/richtext/richtext/richtext.html b/editor/libeditor/tests/browserscope/lib/richtext/richtext/richtext.html new file mode 100644 index 0000000000..140f1a2045 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext/richtext/richtext.html @@ -0,0 +1,1081 @@ + + + + + Rich Text Tests + + + + + +

                  Apply Formatting

                  +
                  CommandstyleWithCSSStatusOutput
                  +

                  Unapply Formatting

                  + + +
                  CommandCommand unappliedStatusHTML Attempted to UnapplyResulting HTML
                  +

                  Query Formatting State

                  + + +
                  CommandStatusHTMLExpectedActual
                  +

                  Query Formatting Value

                  + + +
                  CommandStatusHTMLExpectedActual
                  +

                  Change Formatting

                  + + +
                  CommandStatusArgumentOriginal HTMLResulting HTML
                  + + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext/update_from_upstream b/editor/libeditor/tests/browserscope/lib/richtext/update_from_upstream new file mode 100644 index 0000000000..2071454a85 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext/update_from_upstream @@ -0,0 +1,16 @@ +#!/bin/sh + +set -x + +if test -d richtext; then + rm -drf richtext; +fi + +svn checkout http://browserscope.googlecode.com/svn/trunk/categories/richtext/static richtext | tail -1 | sed 's/[^0-9]//g' > current_revision + +find richtext -type d -name .svn -exec rm -drf \{\} \; 2> /dev/null + +hg add current_revision richtext + +hg stat . + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/LICENSE b/editor/libeditor/tests/browserscope/lib/richtext2/LICENSE new file mode 100644 index 0000000000..57bc88a15a --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/README b/editor/libeditor/tests/browserscope/lib/richtext2/README new file mode 100644 index 0000000000..a3bc3110f4 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/README @@ -0,0 +1,58 @@ +README FOR BROWSERSCOPE +----------------------- + +Hey there - thanks for downloading the code. This file has instructions +for getting setup so that you can run the codebase locally. + +This project is built on Google App Engine using the +Django web application framework and written in Python. + +To get started, you'll need to first download the App Engine SDK at: +http://code.google.com/appengine/downloads.html + +For local development, just startup the server: +./pathto/google_appengine/dev_appserver.py --port=8080 browserscope + +You should then be able to access the local application at: +http://localhost:8080/ + +Note: the first time you hit the homepage it may take a little +while - that's because it's trying to read out median times for all +of the tests from a nonexistent datastore and write to memcache. +Just be a lil patient. + +You can run the unit tests at: + http://localhost:8080/test + + +CONTRIBUTING +------------------ + +Most likely you are interested in adding new tests or creating +a new test category. If you are interested in adding tests to an existing +"category" you may want to get in touch with the maintainer for that +branch of the tree. We are really looking forward to receiving your +code in patch format. Currently the category maintainers are: +Network: Steve Souders +Reflow: Lindsey Simon +Security: Adam Barth and Collin Jackson + + +To create a completely new test category: + * Copy one of the existing directories in categories/ + * Edit your test_set.py, handlers.py + * Add your files in templates/ and static/ + * Update urls.py and settings.CATEGORIES + * Follow the examples of other tests re: + * beaconing using/testdriver_base + * your GetScoreAndDisplayValue method + * your GetRowScoreAndDisplayValue method + +References: + * App Engine Docs - http://code.google.com/appengine/docs/python/overview.html + * App Engine Group - http://groups.google.com/group/google-appengine + * Python Docs - http://www.python.org/doc/ + * Django - http://www.djangoproject.com/ + + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/README.Mozilla b/editor/libeditor/tests/browserscope/lib/richtext2/README.Mozilla new file mode 100644 index 0000000000..7d730874c6 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/README.Mozilla @@ -0,0 +1,27 @@ +The BrowserScope project provides a set of cross-browser HTML editor tests, +which we import in our test suite in order to run them as part of our +continuous integration system. + +We pull tests occasionally from their Subversion repository using the pull +script which can be found in this directory. We also record the revision ID +which we've used in the current_revision file inside this directory. + +Using the pull script is quite easy, just switch to this directory, and say: + +sh update_from_upstream + +There are tests which we're currently failing on, and there will probably be +more of those in the future. We should maintain a list of the failing tests +manually in currentStatus.js (which can also be found in this directory), to +make sure that the suite passes entirely, with failing tests marked as todo +items. + +The current status of the test suite needs to be updated whenever an editor +bug gets fixed, which makes us pass one of the tests. When that happens, +you should set the UPDATE_TEST_RESULTS constant to true in test_richtext2.html, +run the test suite, paste the result JSON string in a JSON beautifier (such +as http://jsbeautifier.org/), and use the result to update currentStatus.js. + +As a special case, if there are platform-specific failures, these are instead +recorded manually in platformFailures.js. (Currently, this applies only to +tests that are dependent on underlying platform support for the Thai script.) diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js b/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js new file mode 100644 index 0000000000..a414039cb7 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js @@ -0,0 +1,1843 @@ +/** + * The current status of the test suite. + * + * See README.Mozilla for details on how to generate this. + */ +const knownFailures = { + value: { + "A-Proposed-FS:18px_TEXT-1_SI-dM": true, + "A-Proposed-FS:18px_TEXT-1_SI-body": true, + "A-Proposed-FS:18px_TEXT-1_SI-div": true, + "A-Proposed-FS:large_TEXT-1_SI-dM": true, + "A-Proposed-FS:large_TEXT-1_SI-body": true, + "A-Proposed-FS:large_TEXT-1_SI-div": true, + "A-Proposed-CB:name_TEXT-1_SI-dM": true, + "A-Proposed-CB:name_TEXT-1_SI-body": true, + "A-Proposed-CB:name_TEXT-1_SI-div": true, + "AC-Proposed-SUB_TEXT-1_SI-dM": true, + "AC-Proposed-SUB_TEXT-1_SI-body": true, + "AC-Proposed-SUB_TEXT-1_SI-div": true, + "AC-Proposed-SUP_TEXT-1_SI-dM": true, + "AC-Proposed-SUP_TEXT-1_SI-body": true, + "AC-Proposed-SUP_TEXT-1_SI-div": true, + "AC-Proposed-FS:2_TEXT-1_SI-dM": true, + "AC-Proposed-FS:2_TEXT-1_SI-body": true, + "AC-Proposed-FS:2_TEXT-1_SI-div": true, + "AC-Proposed-FS:18px_TEXT-1_SI-dM": true, + "AC-Proposed-FS:18px_TEXT-1_SI-body": true, + "AC-Proposed-FS:18px_TEXT-1_SI-div": true, + "AC-Proposed-FS:large_TEXT-1_SI-dM": true, + "AC-Proposed-FS:large_TEXT-1_SI-body": true, + "AC-Proposed-FS:large_TEXT-1_SI-div": true, + "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-dM": true, + "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-body": true, + "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-div": true, + "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-dM": true, + "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-body": true, + "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-div": true, + "C-Proposed-FN:c_FONTf:a-1_SI-dM": true, + "C-Proposed-FN:c_FONTf:a-1_SI-body": true, + "C-Proposed-FN:c_FONTf:a-1_SI-div": true, + "C-Proposed-FN:c_FONTf:a-2_SL-dM": true, + "C-Proposed-FN:c_FONTf:a-2_SL-body": true, + "C-Proposed-FN:c_FONTf:a-2_SL-div": true, + "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-dM": true, + "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-body": true, + "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-div": true, + "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-dM": true, + "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-body": true, + "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-div": true, + "C-Proposed-FS:larger_FONTsz:4-dM": true, + "C-Proposed-FS:larger_FONTsz:4-body": true, + "C-Proposed-FS:larger_FONTsz:4-div": true, + "C-Proposed-FS:smaller_FONTsz:4-dM": true, + "C-Proposed-FS:smaller_FONTsz:4-body": true, + "C-Proposed-FS:smaller_FONTsz:4-div": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-dM": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-body": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-div": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-dM": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-body": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-div": true, + "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-dM": true, + "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-body": true, + "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-div": true, + "CC-Proposed-I_B-1_SW-dM": true, + "CC-Proposed-I_B-1_SW-body": true, + "CC-Proposed-I_B-1_SW-div": true, + "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-dM": true, + "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-body": true, + "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-div": true, + "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-dM": true, + "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-body": true, + "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-div": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-dM": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-body": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-div": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-dM": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-body": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-div": true, + "CC-Proposed-FN:c_FONTf:a-1_SI-dM": true, + "CC-Proposed-FN:c_FONTf:a-1_SI-body": true, + "CC-Proposed-FN:c_FONTf:a-1_SI-div": true, + "CC-Proposed-FN:c_FONTf:a-2_SL-dM": true, + "CC-Proposed-FN:c_FONTf:a-2_SL-body": true, + "CC-Proposed-FN:c_FONTf:a-2_SL-div": true, + "CC-Proposed-FS:1_SPANs:fs:l-1_SW-dM": true, + "CC-Proposed-FS:1_SPANs:fs:l-1_SW-body": true, + "CC-Proposed-FS:1_SPANs:fs:l-1_SW-div": true, + "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-dM": true, + "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-body": true, + "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-div": true, + "CC-Proposed-FS:4_SPANs:fs:l-1_SW-dM": true, + "CC-Proposed-FS:4_SPANs:fs:l-1_SW-body": true, + "CC-Proposed-FS:4_SPANs:fs:l-1_SW-div": true, + "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-dM": true, + "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-body": true, + "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-div": true, + "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-dM": true, + "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-body": true, + "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-div": true, + "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-dM": true, + "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-body": true, + "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-div": true, + "U-RFC-UNLINK_A-1_SO-dM": true, + "U-RFC-UNLINK_A-1_SO-body": true, + "U-RFC-UNLINK_A-1_SO-div": true, + "U-RFC-UNLINK_A-1_SW-dM": true, + "U-RFC-UNLINK_A-1_SW-body": true, + "U-RFC-UNLINK_A-1_SW-div": true, + "U-RFC-UNLINK_A-2_SO-dM": true, + "U-RFC-UNLINK_A-2_SO-body": true, + "U-RFC-UNLINK_A-2_SO-div": true, + "U-RFC-UNLINK_A2-1_SO-dM": true, + "U-RFC-UNLINK_A2-1_SO-body": true, + "U-RFC-UNLINK_A2-1_SO-div": true, + "U-Proposed-B_B-P-I..P-1_SO-I-dM": true, + "U-Proposed-B_B-P-I..P-1_SO-I-body": true, + "U-Proposed-B_B-P-I..P-1_SO-I-div": true, + "U-Proposed-B_B-2_SL-dM": true, + "U-Proposed-B_B-2_SL-body": true, + "U-Proposed-B_B-2_SL-div": true, + "U-Proposed-B_B-2_SR-dM": true, + "U-Proposed-B_B-2_SR-body": true, + "U-Proposed-B_B-2_SR-div": true, + "U-Proposed-U_U-S-2_SI-dM": true, + "U-Proposed-U_U-S-2_SI-body": true, + "U-Proposed-U_U-S-2_SI-div": true, + "U-Proposed-S_DEL-1_SW-dM": true, + "U-Proposed-S_DEL-1_SW-body": true, + "U-Proposed-S_DEL-1_SW-div": true, + "U-Proposed-SUB_SPANs:va:sub-1_SW-dM": true, + "U-Proposed-SUB_SPANs:va:sub-1_SW-body": true, + "U-Proposed-SUB_SPANs:va:sub-1_SW-div": true, + "U-Proposed-SUP_SPANs:va:super-1_SW-dM": true, + "U-Proposed-SUP_SPANs:va:super-1_SW-body": true, + "U-Proposed-SUP_SPANs:va:super-1_SW-div": true, + "U-Proposed-UNLINK_A-1_SC-dM": true, + "U-Proposed-UNLINK_A-1_SC-body": true, + "U-Proposed-UNLINK_A-1_SC-div": true, + "U-Proposed-UNLINK_A-1_SI-dM": true, + "U-Proposed-UNLINK_A-1_SI-body": true, + "U-Proposed-UNLINK_A-1_SI-div": true, + "U-Proposed-UNLINK_A-2_SL-dM": true, + "U-Proposed-UNLINK_A-2_SL-body": true, + "U-Proposed-UNLINK_A-2_SL-div": true, + "U-Proposed-UNLINK_A-3_SR-dM": true, + "U-Proposed-UNLINK_A-3_SR-body": true, + "U-Proposed-UNLINK_A-3_SR-div": true, + "U-Proposed-OUTDENT_BQ-1_SW-dM": true, + "U-Proposed-OUTDENT_BQ-1_SW-body": true, + "U-Proposed-OUTDENT_BQ-1_SW-div": true, + "U-Proposed-OUTDENT_BQ.wibq.s:m:00040.b:n.p:0-1_SW-dM": true, + "U-Proposed-OUTDENT_BQ.wibq.s:m:00040.b:n.p:0-1_SW-body": true, + "U-Proposed-OUTDENT_BQ.wibq.s:m:00040.b:n.p:0-1_SW-div": true, + "U-Proposed-OUTDENT_OL-LI-1_SW-dM": true, + "U-Proposed-OUTDENT_OL-LI-1_SW-body": true, + "U-Proposed-OUTDENT_OL-LI-1_SW-div": true, + "U-Proposed-OUTDENT_UL-LI-1_SW-dM": true, + "U-Proposed-OUTDENT_UL-LI-1_SW-body": true, + "U-Proposed-OUTDENT_UL-LI-1_SW-div": true, + "U-Proposed-OUTDENT_DIV-1_SW-dM": true, + "U-Proposed-OUTDENT_DIV-1_SW-body": true, + "U-Proposed-OUTDENT_DIV-1_SW-div": true, + "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-dM": true, + "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-body": true, + "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-div": true, + "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-dM": true, + "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-body": true, + "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-div": true, + "U-Proposed-UNBOOKMARK_An:name-1_SW-dM": true, + "U-Proposed-UNBOOKMARK_An:name-1_SW-body": true, + "U-Proposed-UNBOOKMARK_An:name-1_SW-div": true, + "UC-Proposed-S_SPANc:s-1_SW-dM": true, + "UC-Proposed-S_SPANc:s-1_SW-body": true, + "UC-Proposed-S_SPANc:s-1_SW-div": true, + "UC-Proposed-S_SPANc:s-2_SI-dM": true, + "UC-Proposed-S_SPANc:s-2_SI-body": true, + "UC-Proposed-S_SPANc:s-2_SI-div": true, + "D-Proposed-CHAR-3_SC-dM": true, + "D-Proposed-CHAR-3_SC-body": true, + "D-Proposed-CHAR-3_SC-div": true, + "D-Proposed-CHAR-4_SC-dM": true, + "D-Proposed-CHAR-4_SC-body": true, + "D-Proposed-CHAR-4_SC-div": true, + "D-Proposed-CHAR-5_SC-dM": true, + "D-Proposed-CHAR-5_SC-body": true, + "D-Proposed-CHAR-5_SC-div": true, + "D-Proposed-CHAR-5_SI-1-dM": true, + "D-Proposed-CHAR-5_SI-1-body": true, + "D-Proposed-CHAR-5_SI-1-div": true, + "D-Proposed-CHAR-5_SI-2-dM": true, + "D-Proposed-CHAR-5_SI-2-body": true, + "D-Proposed-CHAR-5_SI-2-div": true, + "D-Proposed-CHAR-5_SR-dM": true, + "D-Proposed-CHAR-5_SR-body": true, + "D-Proposed-CHAR-5_SR-div": true, + "D-Proposed-CHAR-6_SC-dM": true, + "D-Proposed-CHAR-6_SC-body": true, + "D-Proposed-CHAR-6_SC-div": true, + "D-Proposed-CHAR-7_SC-dM": true, + "D-Proposed-CHAR-7_SC-body": true, + "D-Proposed-CHAR-7_SC-div": true, + "D-Proposed-OL-LI-1_SW-dM": true, + "D-Proposed-OL-LI-1_SW-body": true, + "D-Proposed-OL-LI-1_SW-div": true, + "D-Proposed-TR2rs:2-1_SO1-dM": true, + "D-Proposed-TR2rs:2-1_SO1-body": true, + "D-Proposed-TR2rs:2-1_SO1-div": true, + "D-Proposed-TR2rs:2-1_SO2-dM": true, + "D-Proposed-TR2rs:2-1_SO2-body": true, + "D-Proposed-TR2rs:2-1_SO2-div": true, + "D-Proposed-TR3rs:3-1_SO1-dM": true, + "D-Proposed-TR3rs:3-1_SO1-body": true, + "D-Proposed-TR3rs:3-1_SO1-div": true, + "D-Proposed-TR3rs:3-1_SO2-dM": true, + "D-Proposed-TR3rs:3-1_SO2-body": true, + "D-Proposed-TR3rs:3-1_SO2-div": true, + "D-Proposed-TR3rs:3-1_SO3-dM": true, + "D-Proposed-TR3rs:3-1_SO3-body": true, + "D-Proposed-TR3rs:3-1_SO3-div": true, + "D-Proposed-DIV:ce:false-1_SB-dM": true, + "D-Proposed-DIV:ce:false-1_SL-dM": true, + "D-Proposed-DIV:ce:false-1_SL-body": true, + "D-Proposed-DIV:ce:false-1_SL-div": true, + "D-Proposed-DIV:ce:false-1_SR-dM": true, + "D-Proposed-DIV:ce:false-1_SR-body": true, + "D-Proposed-DIV:ce:false-1_SR-div": true, + "D-Proposed-DIV:ce:false-1_SI-dM": true, + "FD-Proposed-OL-LI-1_SW-dM": true, + "FD-Proposed-OL-LI-1_SW-body": true, + "FD-Proposed-OL-LI-1_SW-div": true, + "FD-Proposed-TR2rs:2-1_SO1-dM": true, + "FD-Proposed-TR2rs:2-1_SO1-body": true, + "FD-Proposed-TR2rs:2-1_SO1-div": true, + "FD-Proposed-TR2rs:2-1_SO2-dM": true, + "FD-Proposed-TR2rs:2-1_SO2-body": true, + "FD-Proposed-TR2rs:2-1_SO2-div": true, + "FD-Proposed-TR3rs:3-1_SO1-dM": true, + "FD-Proposed-TR3rs:3-1_SO1-body": true, + "FD-Proposed-TR3rs:3-1_SO1-div": true, + "FD-Proposed-TR3rs:3-1_SO2-dM": true, + "FD-Proposed-TR3rs:3-1_SO2-body": true, + "FD-Proposed-TR3rs:3-1_SO2-div": true, + "FD-Proposed-TR3rs:3-1_SO3-dM": true, + "FD-Proposed-TR3rs:3-1_SO3-body": true, + "FD-Proposed-TR3rs:3-1_SO3-div": true, + "FD-Proposed-DIV:ce:false-1_SB-dM": true, + "FD-Proposed-DIV:ce:false-1_SB-body": true, + "FD-Proposed-DIV:ce:false-1_SB-div": true, + "FD-Proposed-DIV:ce:false-1_SL-dM": true, + "FD-Proposed-DIV:ce:false-1_SL-body": true, + "FD-Proposed-DIV:ce:false-1_SL-div": true, + "FD-Proposed-DIV:ce:false-1_SR-dM": true, + "FD-Proposed-DIV:ce:false-1_SR-body": true, + "FD-Proposed-DIV:ce:false-1_SR-div": true, + "FD-Proposed-DIV:ce:false-1_SI-dM": true, + "I-Proposed-IIMG:._SPAN-IMG-1_SO-dM": true, + "I-Proposed-IIMG:._SPAN-IMG-1_SO-body": true, + "I-Proposed-IIMG:._SPAN-IMG-1_SO-div": true, + "I-Proposed-IIMG:._IMG-1_SO-dM": true, + "I-Proposed-IIMG:._IMG-1_SO-body": true, + "I-Proposed-IIMG:._IMG-1_SO-div": true, + "Q-Proposed-UNSELECT_TEXT-1-dM": true, + "Q-Proposed-UNSELECT_TEXT-1-body": true, + "Q-Proposed-UNSELECT_TEXT-1-div": true, + "Q-Proposed-CREATEBOOKMARK_TEXT-1-dM": true, + "Q-Proposed-CREATEBOOKMARK_TEXT-1-body": true, + "Q-Proposed-CREATEBOOKMARK_TEXT-1-div": true, + "Q-Proposed-UNBOOKMARK_TEXT-1-dM": true, + "Q-Proposed-UNBOOKMARK_TEXT-1-body": true, + "Q-Proposed-UNBOOKMARK_TEXT-1-div": true, + "Q-Proposed-PASTE_TEXT-1-dM": true, + "Q-Proposed-PASTE_TEXT-1-body": true, + "Q-Proposed-PASTE_TEXT-1-div": true, + "QE-Proposed-UNSELECT_TEXT-1-dM": true, + "QE-Proposed-UNSELECT_TEXT-1-body": true, + "QE-Proposed-UNSELECT_TEXT-1-div": true, + "QE-Proposed-REDO_TEXT-1-dM": true, + "QE-Proposed-REDO_TEXT-1-body": true, + "QE-Proposed-REDO_TEXT-1-div": true, + "QE-Proposed-CREATEBOOKMARK_TEXT-1-dM": true, + "QE-Proposed-CREATEBOOKMARK_TEXT-1-body": true, + "QE-Proposed-CREATEBOOKMARK_TEXT-1-div": true, + "QE-Proposed-UNBOOKMARK_TEXT-1-dM": true, + "QE-Proposed-UNBOOKMARK_TEXT-1-body": true, + "QE-Proposed-UNBOOKMARK_TEXT-1-div": true, + "QE-Proposed-COPY_TEXT-1-dM": true, + "QE-Proposed-COPY_TEXT-1-body": true, + "QE-Proposed-COPY_TEXT-1-div": true, + "QE-Proposed-CUT_TEXT-1-dM": true, + "QE-Proposed-CUT_TEXT-1-body": true, + "QE-Proposed-CUT_TEXT-1-div": true, + "QE-Proposed-PASTE_TEXT-1-dM": true, + "QE-Proposed-PASTE_TEXT-1-body": true, + "QE-Proposed-PASTE_TEXT-1-div": true, + "QS-Proposed-SUB_SPAN.sub-1-SI-dM": true, + "QS-Proposed-SUB_SPAN.sub-1-SI-body": true, + "QS-Proposed-SUB_SPAN.sub-1-SI-div": true, + "QS-Proposed-SUB_MYSUB-1-SI-dM": true, + "QS-Proposed-SUB_MYSUB-1-SI-body": true, + "QS-Proposed-SUB_MYSUB-1-SI-div": true, + "QS-Proposed-SUP_SPAN.sup-1-SI-dM": true, + "QS-Proposed-SUP_SPAN.sup-1-SI-body": true, + "QS-Proposed-SUP_SPAN.sup-1-SI-div": true, + "QS-Proposed-SUP_MYSUP-1-SI-dM": true, + "QS-Proposed-SUP_MYSUP-1-SI-body": true, + "QS-Proposed-SUP_MYSUP-1-SI-div": true, + "QS-Proposed-JC_SPAN.jc-1-SI-dM": true, + "QS-Proposed-JC_SPAN.jc-1-SI-body": true, + "QS-Proposed-JC_SPAN.jc-1-SI-div": true, + "QS-Proposed-JC_MYJC-1-SI-dM": true, + "QS-Proposed-JC_MYJC-1-SI-body": true, + "QS-Proposed-JC_MYJC-1-SI-div": true, + "QS-Proposed-JF_SPANs:ta:j-1_SI-dM": true, + "QS-Proposed-JF_SPANs:ta:j-1_SI-body": true, + "QS-Proposed-JF_SPANs:ta:j-1_SI-div": true, + "QS-Proposed-JF_SPAN.jf-1-SI-dM": true, + "QS-Proposed-JF_SPAN.jf-1-SI-body": true, + "QS-Proposed-JF_SPAN.jf-1-SI-div": true, + "QS-Proposed-JF_MYJF-1-SI-dM": true, + "QS-Proposed-JF_MYJF-1-SI-body": true, + "QS-Proposed-JF_MYJF-1-SI-div": true, + "QS-Proposed-JL_TEXT_SI-dM": true, + "QS-Proposed-JL_TEXT_SI-body": true, + "QS-Proposed-JL_TEXT_SI-div": true, + "QS-Proposed-JR_SPANs:ta:r-1_SI-dM": true, + "QS-Proposed-JR_SPANs:ta:r-1_SI-body": true, + "QS-Proposed-JR_SPANs:ta:r-1_SI-div": true, + "QS-Proposed-JR_SPAN.jr-1-SI-dM": true, + "QS-Proposed-JR_SPAN.jr-1-SI-body": true, + "QS-Proposed-JR_SPAN.jr-1-SI-div": true, + "QS-Proposed-JR_MYJR-1-SI-dM": true, + "QS-Proposed-JR_MYJR-1-SI-body": true, + "QS-Proposed-JR_MYJR-1-SI-div": true, + "QV-Proposed-B_TEXT_SI-dM": true, + "QV-Proposed-B_TEXT_SI-body": true, + "QV-Proposed-B_TEXT_SI-div": true, + "QV-Proposed-B_B-1_SI-dM": true, + "QV-Proposed-B_B-1_SI-body": true, + "QV-Proposed-B_B-1_SI-div": true, + "QV-Proposed-B_STRONG-1_SI-dM": true, + "QV-Proposed-B_STRONG-1_SI-body": true, + "QV-Proposed-B_STRONG-1_SI-div": true, + "QV-Proposed-B_SPANs:fw:b-1_SI-dM": true, + "QV-Proposed-B_SPANs:fw:b-1_SI-body": true, + "QV-Proposed-B_SPANs:fw:b-1_SI-div": true, + "QV-Proposed-B_SPANs:fw:n-1_SI-dM": true, + "QV-Proposed-B_SPANs:fw:n-1_SI-body": true, + "QV-Proposed-B_SPANs:fw:n-1_SI-div": true, + "QV-Proposed-B_Bs:fw:n-1_SI-dM": true, + "QV-Proposed-B_Bs:fw:n-1_SI-body": true, + "QV-Proposed-B_Bs:fw:n-1_SI-div": true, + "QV-Proposed-B_SPAN.b-1_SI-dM": true, + "QV-Proposed-B_SPAN.b-1_SI-body": true, + "QV-Proposed-B_SPAN.b-1_SI-div": true, + "QV-Proposed-B_MYB-1-SI-dM": true, + "QV-Proposed-B_MYB-1-SI-body": true, + "QV-Proposed-B_MYB-1-SI-div": true, + "QV-Proposed-I_TEXT_SI-dM": true, + "QV-Proposed-I_TEXT_SI-body": true, + "QV-Proposed-I_TEXT_SI-div": true, + "QV-Proposed-I_I-1_SI-dM": true, + "QV-Proposed-I_I-1_SI-body": true, + "QV-Proposed-I_I-1_SI-div": true, + "QV-Proposed-I_EM-1_SI-dM": true, + "QV-Proposed-I_EM-1_SI-body": true, + "QV-Proposed-I_EM-1_SI-div": true, + "QV-Proposed-I_SPANs:fs:i-1_SI-dM": true, + "QV-Proposed-I_SPANs:fs:i-1_SI-body": true, + "QV-Proposed-I_SPANs:fs:i-1_SI-div": true, + "QV-Proposed-I_SPANs:fs:n-1_SI-dM": true, + "QV-Proposed-I_SPANs:fs:n-1_SI-body": true, + "QV-Proposed-I_SPANs:fs:n-1_SI-div": true, + "QV-Proposed-I_I-SPANs:fs:n-1_SI-dM": true, + "QV-Proposed-I_I-SPANs:fs:n-1_SI-body": true, + "QV-Proposed-I_I-SPANs:fs:n-1_SI-div": true, + "QV-Proposed-I_SPAN.i-1_SI-dM": true, + "QV-Proposed-I_SPAN.i-1_SI-body": true, + "QV-Proposed-I_SPAN.i-1_SI-div": true, + "QV-Proposed-I_MYI-1-SI-dM": true, + "QV-Proposed-I_MYI-1-SI-body": true, + "QV-Proposed-I_MYI-1-SI-div": true, + "QV-Proposed-FB_BQ-1_SC-dM": true, + "QV-Proposed-FB_BQ-1_SC-body": true, + "QV-Proposed-FB_BQ-1_SC-div": true, + "QV-Proposed-FB_H1-H2-1_SL-dM": true, + "QV-Proposed-FB_H1-H2-1_SL-body": true, + "QV-Proposed-FB_H1-H2-1_SL-div": true, + "QV-Proposed-FB_H1-H2-1_SR-dM": true, + "QV-Proposed-FB_H1-H2-1_SR-body": true, + "QV-Proposed-FB_H1-H2-1_SR-div": true, + "QV-Proposed-FB_TEXT-ADDRESS-1_SL-dM": true, + "QV-Proposed-FB_TEXT-ADDRESS-1_SL-body": true, + "QV-Proposed-FB_TEXT-ADDRESS-1_SL-div": true, + "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-dM": true, + "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-body": true, + "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-div": true, + "QV-Proposed-H_P-1_SC-dM": true, + "QV-Proposed-H_P-1_SC-body": true, + "QV-Proposed-H_P-1_SC-div": true, + "QV-Proposed-FS_FONTs:fs:l-1_SI-dM": true, + "QV-Proposed-FS_FONTs:fs:l-1_SI-body": true, + "QV-Proposed-FS_FONTs:fs:l-1_SI-div": true, + "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-dM": true, + "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-body": true, + "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-div": true, + "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-dM": true, + "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-body": true, + "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-div": true, + "QV-Proposed-FS_SPAN.large-1_SI-dM": true, + "QV-Proposed-FS_SPAN.large-1_SI-body": true, + "QV-Proposed-FS_SPAN.large-1_SI-div": true, + "QV-Proposed-FS_SPAN.fs18px-1_SI-dM": true, + "QV-Proposed-FS_SPAN.fs18px-1_SI-body": true, + "QV-Proposed-FS_SPAN.fs18px-1_SI-div": true, + "QV-Proposed-FA_MYLARGE-1-SI-dM": true, + "QV-Proposed-FA_MYLARGE-1-SI-body": true, + "QV-Proposed-FA_MYLARGE-1-SI-div": true, + "QV-Proposed-FA_MYFS18PX-1-SI-dM": true, + "QV-Proposed-FA_MYFS18PX-1-SI-body": true, + "QV-Proposed-FA_MYFS18PX-1-SI-div": true, + "QV-Proposed-BC_FONTs:bc:fca-1_SI-dM": true, + "QV-Proposed-BC_FONTs:bc:fca-1_SI-body": true, + "QV-Proposed-BC_FONTs:bc:fca-1_SI-div": true, + "QV-Proposed-BC_SPANs:bc:abc-1_SI-dM": true, + "QV-Proposed-BC_SPANs:bc:abc-1_SI-body": true, + "QV-Proposed-BC_SPANs:bc:abc-1_SI-div": true, + "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-dM": true, + "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-body": true, + "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-div": true, + "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-dM": true, + "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-body": true, + "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-div": true, + "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-dM": true, + "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-body": true, + "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-div": true, + "QV-Proposed-BC_SPAN.bcred-1_SI-dM": true, + "QV-Proposed-BC_SPAN.bcred-1_SI-body": true, + "QV-Proposed-BC_SPAN.bcred-1_SI-div": true, + "QV-Proposed-BC_MYBCRED-1-SI-dM": true, + "QV-Proposed-BC_MYBCRED-1-SI-body": true, + "QV-Proposed-BC_MYBCRED-1-SI-div": true, + "QV-Proposed-HC_FONTs:bc:fc0-1_SI-dM": true, + "QV-Proposed-HC_FONTs:bc:fc0-1_SI-body": true, + "QV-Proposed-HC_FONTs:bc:fc0-1_SI-div": true, + "QV-Proposed-HC_SPANs:bc:a0c-1_SI-dM": true, + "QV-Proposed-HC_SPANs:bc:a0c-1_SI-body": true, + "QV-Proposed-HC_SPANs:bc:a0c-1_SI-div": true, + "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-dM": true, + "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-body": true, + "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-div": true, + "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-dM": true, + "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-body": true, + "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-div": true, + "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-dM": true, + "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-body": true, + "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-div": true, + "QV-Proposed-HC_SPAN.bcred-1_SI-dM": true, + "QV-Proposed-HC_SPAN.bcred-1_SI-body": true, + "QV-Proposed-HC_SPAN.bcred-1_SI-div": true, + "QV-Proposed-HC_MYBCRED-1-SI-dM": true, + "QV-Proposed-HC_MYBCRED-1-SI-body": true, + "QV-Proposed-HC_MYBCRED-1-SI-div": true, + }, + select: { + "S-Proposed-UNSEL_TEXT-1_SI-dM": true, + "S-Proposed-UNSEL_TEXT-1_SI-body": true, + "S-Proposed-UNSEL_TEXT-1_SI-div": true, + "S-Proposed-SM:m.f.c_TEXT-1_SI-1-dM": true, + "S-Proposed-SM:m.f.c_TEXT-1_SI-1-body": true, + "S-Proposed-SM:m.f.c_TEXT-1_SI-1-div": true, + "S-Proposed-SM:m.b.c_TEXT-1_SI-1-dM": true, + "S-Proposed-SM:m.b.c_TEXT-1_SI-1-body": true, + "S-Proposed-SM:m.b.c_TEXT-1_SI-1-div": true, + "S-Proposed-SM:m.b.w_TEXT-1_SI-1-dM": true, + "S-Proposed-SM:m.b.w_TEXT-1_SI-1-body": true, + "S-Proposed-SM:m.b.w_TEXT-1_SI-1-div": true, + "S-Proposed-SM:m.f.c_CHAR-5_SI-2-dM": true, + "S-Proposed-SM:m.f.c_CHAR-5_SI-2-body": true, + "S-Proposed-SM:m.f.c_CHAR-5_SI-2-div": true, + "S-Proposed-SM:m.f.c_CHAR-5_SR-dM": true, + "S-Proposed-SM:m.f.c_CHAR-5_SR-body": true, + "S-Proposed-SM:m.f.c_CHAR-5_SR-div": true, + "S-Proposed-SM:m.b.c_CHAR-5_SR-dM": true, + "S-Proposed-SM:m.b.c_CHAR-5_SR-body": true, + "S-Proposed-SM:m.b.c_CHAR-5_SR-div": true, + "S-Proposed-SM:m.f.w_TEXT-jp_SC-1-dM": true, + "S-Proposed-SM:m.f.w_TEXT-jp_SC-1-body": true, + "S-Proposed-SM:m.f.w_TEXT-jp_SC-1-div": true, + "S-Proposed-SM:m.f.w_TEXT-jp_SC-2-dM": true, + "S-Proposed-SM:m.f.w_TEXT-jp_SC-2-body": true, + "S-Proposed-SM:m.f.w_TEXT-jp_SC-2-div": true, + "S-Proposed-SM:m.f.w_TEXT-jp_SC-5-dM": true, + "S-Proposed-SM:m.f.w_TEXT-jp_SC-5-body": true, + "S-Proposed-SM:m.f.w_TEXT-jp_SC-5-div": true, + "S-Proposed-SM:e.b.w_TEXT-1_SI-3-dM": true, + "S-Proposed-SM:e.b.w_TEXT-1_SI-3-body": true, + "S-Proposed-SM:e.b.w_TEXT-1_SI-3-div": true, + "S-Proposed-SM:e.b.w_TEXT-1_SI-4-dM": true, + "S-Proposed-SM:e.b.w_TEXT-1_SI-4-body": true, + "S-Proposed-SM:e.b.w_TEXT-1_SI-4-div": true, + "S-Proposed-SM:e.b.w_TEXT-1_SI-5-dM": true, + "S-Proposed-SM:e.b.w_TEXT-1_SI-5-body": true, + "S-Proposed-SM:e.b.w_TEXT-1_SI-5-div": true, + "S-Proposed-SM:e.f.w_TEXT-1_SIR-1-dM": true, + "S-Proposed-SM:e.f.w_TEXT-1_SIR-1-body": true, + "S-Proposed-SM:e.f.w_TEXT-1_SIR-1-div": true, + "S-Proposed-SM:e.f.w_TEXT-1_SIR-3-dM": true, + "S-Proposed-SM:e.f.w_TEXT-1_SIR-3-body": true, + "S-Proposed-SM:e.f.w_TEXT-1_SIR-3-div": true, + "S-Proposed-SM:e.f.lb_BR.BR-1_SI-1-dM": true, + "S-Proposed-SM:e.f.lb_BR.BR-1_SI-1-body": true, + "S-Proposed-SM:e.f.lb_BR.BR-1_SI-1-div": true, + "S-Proposed-SM:e.f.lb_P.P.P-1_SI-1-dM": true, + "S-Proposed-SM:e.f.lb_P.P.P-1_SI-1-body": true, + "S-Proposed-SM:e.f.lb_P.P.P-1_SI-1-div": true, + "S-Proposed-SM:e.b.lb_BR.BR-1_SIR-2-dM": true, + "S-Proposed-SM:e.b.lb_BR.BR-1_SIR-2-body": true, + "S-Proposed-SM:e.b.lb_BR.BR-1_SIR-2-div": true, + "S-Proposed-SM:e.b.lb_P.P.P-1_SIR-2-dM": true, + "S-Proposed-SM:e.b.lb_P.P.P-1_SIR-2-body": true, + "S-Proposed-SM:e.b.lb_P.P.P-1_SIR-2-div": true, + "S-Proposed-SM:e.f.l_BR.BR-2_SI-1-dM": true, + "S-Proposed-SM:e.f.l_BR.BR-2_SI-1-body": true, + "S-Proposed-SM:e.f.l_BR.BR-2_SI-1-div": true, + "A-Proposed-B_TEXT-1_SI-dM": true, + "A-Proposed-B_TEXT-1_SI-body": true, + "A-Proposed-B_TEXT-1_SI-div": true, + "A-Proposed-B_TEXT-1_SIR-dM": true, + "A-Proposed-B_TEXT-1_SIR-body": true, + "A-Proposed-B_TEXT-1_SIR-div": true, + "A-Proposed-B_I-1_SL-dM": true, + "A-Proposed-B_I-1_SL-body": true, + "A-Proposed-B_I-1_SL-div": true, + "A-Proposed-I_TEXT-1_SI-dM": true, + "A-Proposed-I_TEXT-1_SI-body": true, + "A-Proposed-I_TEXT-1_SI-div": true, + "A-Proposed-U_TEXT-1_SI-dM": true, + "A-Proposed-U_TEXT-1_SI-body": true, + "A-Proposed-U_TEXT-1_SI-div": true, + "A-Proposed-S_TEXT-1_SI-dM": true, + "A-Proposed-S_TEXT-1_SI-body": true, + "A-Proposed-S_TEXT-1_SI-div": true, + "A-Proposed-SUB_TEXT-1_SI-dM": true, + "A-Proposed-SUB_TEXT-1_SI-body": true, + "A-Proposed-SUB_TEXT-1_SI-div": true, + "A-Proposed-SUP_TEXT-1_SI-dM": true, + "A-Proposed-SUP_TEXT-1_SI-body": true, + "A-Proposed-SUP_TEXT-1_SI-div": true, + "A-Proposed-CL:url_TEXT-1_SI-dM": true, + "A-Proposed-CL:url_TEXT-1_SI-body": true, + "A-Proposed-CL:url_TEXT-1_SI-div": true, + "A-Proposed-BC:blue_TEXT-1_SI-dM": true, + "A-Proposed-BC:blue_TEXT-1_SI-body": true, + "A-Proposed-BC:blue_TEXT-1_SI-div": true, + "A-Proposed-FC:blue_TEXT-1_SI-dM": true, + "A-Proposed-FC:blue_TEXT-1_SI-body": true, + "A-Proposed-FC:blue_TEXT-1_SI-div": true, + "A-Proposed-HC:blue_TEXT-1_SI-dM": true, + "A-Proposed-HC:blue_TEXT-1_SI-body": true, + "A-Proposed-HC:blue_TEXT-1_SI-div": true, + "A-Proposed-FN:a_TEXT-1_SI-dM": true, + "A-Proposed-FN:a_TEXT-1_SI-body": true, + "A-Proposed-FN:a_TEXT-1_SI-div": true, + "A-Proposed-FS:2_TEXT-1_SI-dM": true, + "A-Proposed-FS:2_TEXT-1_SI-body": true, + "A-Proposed-FS:2_TEXT-1_SI-div": true, + "A-Proposed-FS:18px_TEXT-1_SI-dM": true, + "A-Proposed-FS:18px_TEXT-1_SI-body": true, + "A-Proposed-FS:18px_TEXT-1_SI-div": true, + "A-Proposed-FS:large_TEXT-1_SI-dM": true, + "A-Proposed-FS:large_TEXT-1_SI-body": true, + "A-Proposed-FS:large_TEXT-1_SI-div": true, + "A-Proposed-INCFS:2_TEXT-1_SI-dM": true, + "A-Proposed-INCFS:2_TEXT-1_SI-body": true, + "A-Proposed-INCFS:2_TEXT-1_SI-div": true, + "A-Proposed-DECFS:2_TEXT-1_SI-dM": true, + "A-Proposed-DECFS:2_TEXT-1_SI-body": true, + "A-Proposed-DECFS:2_TEXT-1_SI-div": true, + "A-Proposed-CB:name_TEXT-1_SI-dM": true, + "A-Proposed-CB:name_TEXT-1_SI-body": true, + "A-Proposed-CB:name_TEXT-1_SI-div": true, + "AC-Proposed-B_TEXT-1_SI-dM": true, + "AC-Proposed-B_TEXT-1_SI-body": true, + "AC-Proposed-B_TEXT-1_SI-div": true, + "AC-Proposed-I_TEXT-1_SI-dM": true, + "AC-Proposed-I_TEXT-1_SI-body": true, + "AC-Proposed-I_TEXT-1_SI-div": true, + "AC-Proposed-U_TEXT-1_SI-dM": true, + "AC-Proposed-U_TEXT-1_SI-body": true, + "AC-Proposed-U_TEXT-1_SI-div": true, + "AC-Proposed-S_TEXT-1_SI-dM": true, + "AC-Proposed-S_TEXT-1_SI-body": true, + "AC-Proposed-S_TEXT-1_SI-div": true, + "AC-Proposed-SUB_TEXT-1_SI-dM": true, + "AC-Proposed-SUB_TEXT-1_SI-body": true, + "AC-Proposed-SUB_TEXT-1_SI-div": true, + "AC-Proposed-SUP_TEXT-1_SI-dM": true, + "AC-Proposed-SUP_TEXT-1_SI-body": true, + "AC-Proposed-SUP_TEXT-1_SI-div": true, + "AC-Proposed-BC:blue_TEXT-1_SI-dM": true, + "AC-Proposed-BC:blue_TEXT-1_SI-body": true, + "AC-Proposed-BC:blue_TEXT-1_SI-div": true, + "AC-Proposed-FC:blue_TEXT-1_SI-dM": true, + "AC-Proposed-FC:blue_TEXT-1_SI-body": true, + "AC-Proposed-FC:blue_TEXT-1_SI-div": true, + "AC-Proposed-HC:blue_TEXT-1_SI-dM": true, + "AC-Proposed-HC:blue_TEXT-1_SI-body": true, + "AC-Proposed-HC:blue_TEXT-1_SI-div": true, + "AC-Proposed-FN:a_TEXT-1_SI-dM": true, + "AC-Proposed-FN:a_TEXT-1_SI-body": true, + "AC-Proposed-FN:a_TEXT-1_SI-div": true, + "AC-Proposed-FS:2_TEXT-1_SI-dM": true, + "AC-Proposed-FS:2_TEXT-1_SI-body": true, + "AC-Proposed-FS:2_TEXT-1_SI-div": true, + "AC-Proposed-FS:18px_TEXT-1_SI-dM": true, + "AC-Proposed-FS:18px_TEXT-1_SI-body": true, + "AC-Proposed-FS:18px_TEXT-1_SI-div": true, + "AC-Proposed-FS:large_TEXT-1_SI-dM": true, + "AC-Proposed-FS:large_TEXT-1_SI-body": true, + "AC-Proposed-FS:large_TEXT-1_SI-div": true, + "C-Proposed-I_I-1_SL-dM": true, + "C-Proposed-I_I-1_SL-body": true, + "C-Proposed-I_I-1_SL-div": true, + "C-Proposed-I_B-I-1_SO-dM": true, + "C-Proposed-I_B-I-1_SO-body": true, + "C-Proposed-I_B-I-1_SO-div": true, + "C-Proposed-U_U-1_SO-dM": true, + "C-Proposed-U_U-1_SO-body": true, + "C-Proposed-U_U-1_SO-div": true, + "C-Proposed-U_U-1_SL-dM": true, + "C-Proposed-U_U-1_SL-body": true, + "C-Proposed-U_U-1_SL-div": true, + "C-Proposed-U_S-U-1_SO-dM": true, + "C-Proposed-U_S-U-1_SO-body": true, + "C-Proposed-U_S-U-1_SO-div": true, + "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-dM": true, + "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-body": true, + "C-Proposed-BC:ace_FONT.ass.s:bc:rgb-1_SW-div": true, + "C-Proposed-FC:g_FONTc:b.sz:6-1_SI-dM": true, + "C-Proposed-FC:g_FONTc:b.sz:6-1_SI-body": true, + "C-Proposed-FC:g_FONTc:b.sz:6-1_SI-div": true, + "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-dM": true, + "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-body": true, + "C-Proposed-HC:g_SPAN.ass.s:c:rgb-1_SW-div": true, + "C-Proposed-FN:c_FONTf:a-1_SI-dM": true, + "C-Proposed-FN:c_FONTf:a-1_SI-body": true, + "C-Proposed-FN:c_FONTf:a-1_SI-div": true, + "C-Proposed-FN:c_FONTf:a-2_SL-dM": true, + "C-Proposed-FN:c_FONTf:a-2_SL-body": true, + "C-Proposed-FN:c_FONTf:a-2_SL-div": true, + "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-dM": true, + "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-body": true, + "C-Proposed-FS:1_SPAN.ass.s:fs:large-1_SW-div": true, + "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-dM": true, + "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-body": true, + "C-Proposed-FS:5_FONTsz:1.s:fs:xs-1_SW-div": true, + "C-Proposed-FS:2_FONTc:b.sz:6-1_SI-dM": true, + "C-Proposed-FS:2_FONTc:b.sz:6-1_SI-body": true, + "C-Proposed-FS:2_FONTc:b.sz:6-1_SI-div": true, + "C-Proposed-FS:larger_FONTsz:4-dM": true, + "C-Proposed-FS:larger_FONTsz:4-body": true, + "C-Proposed-FS:larger_FONTsz:4-div": true, + "C-Proposed-FS:smaller_FONTsz:4-dM": true, + "C-Proposed-FS:smaller_FONTsz:4-body": true, + "C-Proposed-FS:smaller_FONTsz:4-div": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-dM": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-body": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SO-div": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-dM": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-body": true, + "C-Proposed-FB:h1_ADDRESS-FONTsz:4-1_SW-div": true, + "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-dM": true, + "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-body": true, + "C-Proposed-FB:h1_ADDRESS-FONT.ass.sz:4-1_SW-div": true, + "CC-Proposed-I_I-1_SL-dM": true, + "CC-Proposed-I_I-1_SL-body": true, + "CC-Proposed-I_I-1_SL-div": true, + "CC-Proposed-I_B-1_SL-dM": true, + "CC-Proposed-I_B-1_SL-body": true, + "CC-Proposed-I_B-1_SL-div": true, + "CC-Proposed-I_B-1_SW-dM": true, + "CC-Proposed-I_B-1_SW-body": true, + "CC-Proposed-I_B-1_SW-div": true, + "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-dM": true, + "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-body": true, + "CC-Proposed-BC:gray_SPANs:bc:b-1_SI-div": true, + "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-dM": true, + "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-body": true, + "CC-Proposed-BC:gray_P-SPANs:bc:b-3_SL-div": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-dM": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-body": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SL-div": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-dM": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-body": true, + "CC-Proposed-BC:gray_SPANs:bc:b-2_SR-div": true, + "CC-Proposed-FN:c_FONTf:a-1_SI-dM": true, + "CC-Proposed-FN:c_FONTf:a-1_SI-body": true, + "CC-Proposed-FN:c_FONTf:a-1_SI-div": true, + "CC-Proposed-FN:c_FONTf:a-2_SL-dM": true, + "CC-Proposed-FN:c_FONTf:a-2_SL-body": true, + "CC-Proposed-FN:c_FONTf:a-2_SL-div": true, + "CC-Proposed-FS:1_SPANs:fs:l-1_SW-dM": true, + "CC-Proposed-FS:1_SPANs:fs:l-1_SW-body": true, + "CC-Proposed-FS:1_SPANs:fs:l-1_SW-div": true, + "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-dM": true, + "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-body": true, + "CC-Proposed-FS:18px_SPANs:fs:l-1_SW-div": true, + "CC-Proposed-FS:4_SPANs:fs:l-1_SW-dM": true, + "CC-Proposed-FS:4_SPANs:fs:l-1_SW-body": true, + "CC-Proposed-FS:4_SPANs:fs:l-1_SW-div": true, + "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-dM": true, + "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-body": true, + "CC-Proposed-FS:4_SPANs:fs:18px-1_SW-div": true, + "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-dM": true, + "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-body": true, + "CC-Proposed-FS:larger_SPANs:fs:l-1_SI-div": true, + "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-dM": true, + "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-body": true, + "CC-Proposed-FS:smaller_SPANs:fs:l-1_SI-div": true, + "U-RFC-UNLINK_A-1_SO-dM": true, + "U-RFC-UNLINK_A-1_SO-body": true, + "U-RFC-UNLINK_A-1_SO-div": true, + "U-RFC-UNLINK_A-1_SW-dM": true, + "U-RFC-UNLINK_A-1_SW-body": true, + "U-RFC-UNLINK_A-1_SW-div": true, + "U-RFC-UNLINK_A-2_SO-dM": true, + "U-RFC-UNLINK_A-2_SO-body": true, + "U-RFC-UNLINK_A-2_SO-div": true, + "U-RFC-UNLINK_A2-1_SO-dM": true, + "U-RFC-UNLINK_A2-1_SO-body": true, + "U-RFC-UNLINK_A2-1_SO-div": true, + "U-Proposed-B_B-P3-1_SO12-dM": true, + "U-Proposed-B_B-P3-1_SO12-body": true, + "U-Proposed-B_B-P3-1_SO12-div": true, + "U-Proposed-B_B-P-I..P-1_SO-I-dM": true, + "U-Proposed-B_B-P-I..P-1_SO-I-body": true, + "U-Proposed-B_B-P-I..P-1_SO-I-div": true, + "U-Proposed-B_B-2_SL-dM": true, + "U-Proposed-B_B-2_SL-body": true, + "U-Proposed-B_B-2_SL-div": true, + "U-Proposed-B_B-2_SR-dM": true, + "U-Proposed-B_B-2_SR-body": true, + "U-Proposed-B_B-2_SR-div": true, + "U-Proposed-I_I-P3-1_SO2-dM": true, + "U-Proposed-I_I-P3-1_SO2-body": true, + "U-Proposed-I_I-P3-1_SO2-div": true, + "U-Proposed-U_U-S-1_SO-dM": true, + "U-Proposed-U_U-S-1_SO-body": true, + "U-Proposed-U_U-S-1_SO-div": true, + "U-Proposed-U_U-S-2_SI-dM": true, + "U-Proposed-U_U-S-2_SI-body": true, + "U-Proposed-U_U-S-2_SI-div": true, + "U-Proposed-U_U-P3-1_SO-dM": true, + "U-Proposed-U_U-P3-1_SO-body": true, + "U-Proposed-U_U-P3-1_SO-div": true, + "U-Proposed-S_DEL-1_SW-dM": true, + "U-Proposed-S_DEL-1_SW-body": true, + "U-Proposed-S_DEL-1_SW-div": true, + "U-Proposed-S_S-U-1_SI-dM": true, + "U-Proposed-S_S-U-1_SI-body": true, + "U-Proposed-S_S-U-1_SI-div": true, + "U-Proposed-S_U-S-1_SI-dM": true, + "U-Proposed-S_U-S-1_SI-body": true, + "U-Proposed-S_U-S-1_SI-div": true, + "U-Proposed-SUB_SPANs:va:sub-1_SW-dM": true, + "U-Proposed-SUB_SPANs:va:sub-1_SW-body": true, + "U-Proposed-SUB_SPANs:va:sub-1_SW-div": true, + "U-Proposed-SUP_SPANs:va:super-1_SW-dM": true, + "U-Proposed-SUP_SPANs:va:super-1_SW-body": true, + "U-Proposed-SUP_SPANs:va:super-1_SW-div": true, + "U-Proposed-UNLINK_A-1_SC-dM": true, + "U-Proposed-UNLINK_A-1_SC-body": true, + "U-Proposed-UNLINK_A-1_SC-div": true, + "U-Proposed-UNLINK_A-1_SI-dM": true, + "U-Proposed-UNLINK_A-1_SI-body": true, + "U-Proposed-UNLINK_A-1_SI-div": true, + "U-Proposed-UNLINK_A-2_SL-dM": true, + "U-Proposed-UNLINK_A-2_SL-body": true, + "U-Proposed-UNLINK_A-2_SL-div": true, + "U-Proposed-UNLINK_A-3_SR-dM": true, + "U-Proposed-UNLINK_A-3_SR-body": true, + "U-Proposed-UNLINK_A-3_SR-div": true, + "U-Proposed-OUTDENT_DIV-1_SW-dM": true, + "U-Proposed-OUTDENT_DIV-1_SW-body": true, + "U-Proposed-OUTDENT_DIV-1_SW-div": true, + "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-dM": true, + "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-body": true, + "U-Proposed-REMOVEFORMAT_Ahref:url-1_SW-div": true, + "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-dM": true, + "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-body": true, + "U-Proposed-REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW-div": true, + "U-Proposed-UNBOOKMARK_An:name-1_SW-dM": true, + "U-Proposed-UNBOOKMARK_An:name-1_SW-body": true, + "U-Proposed-UNBOOKMARK_An:name-1_SW-div": true, + "UC-Proposed-S_SPANc:s-1_SW-dM": true, + "UC-Proposed-S_SPANc:s-1_SW-body": true, + "UC-Proposed-S_SPANc:s-1_SW-div": true, + "UC-Proposed-S_SPANc:s-2_SI-dM": true, + "UC-Proposed-S_SPANc:s-2_SI-body": true, + "UC-Proposed-S_SPANc:s-2_SI-div": true, + "D-Proposed-CHAR-3_SC-dM": true, + "D-Proposed-CHAR-3_SC-body": true, + "D-Proposed-CHAR-3_SC-div": true, + "D-Proposed-CHAR-4_SC-dM": true, + "D-Proposed-CHAR-4_SC-body": true, + "D-Proposed-CHAR-4_SC-div": true, + "D-Proposed-CHAR-5_SC-dM": true, + "D-Proposed-CHAR-5_SC-body": true, + "D-Proposed-CHAR-5_SC-div": true, + "D-Proposed-CHAR-5_SI-1-dM": true, + "D-Proposed-CHAR-5_SI-1-body": true, + "D-Proposed-CHAR-5_SI-1-div": true, + "D-Proposed-CHAR-5_SI-2-dM": true, + "D-Proposed-CHAR-5_SI-2-body": true, + "D-Proposed-CHAR-5_SI-2-div": true, + "D-Proposed-CHAR-5_SR-dM": true, + "D-Proposed-CHAR-5_SR-body": true, + "D-Proposed-CHAR-5_SR-div": true, + "D-Proposed-CHAR-6_SC-dM": true, + "D-Proposed-CHAR-6_SC-body": true, + "D-Proposed-CHAR-6_SC-div": true, + "D-Proposed-CHAR-7_SC-dM": true, + "D-Proposed-CHAR-7_SC-body": true, + "D-Proposed-CHAR-7_SC-div": true, + "D-Proposed-B-1_SW-div": true, + "D-Proposed-B-1_SL-dM": true, + "D-Proposed-B-1_SL-body": true, + "D-Proposed-B-1_SL-div": true, + "D-Proposed-B-1_SR-dM": true, + "D-Proposed-B-1_SR-body": true, + "D-Proposed-B-1_SR-div": true, + "D-Proposed-B.I-1_SM-dM": true, + "D-Proposed-B.I-1_SM-body": true, + "D-Proposed-B.I-1_SM-div": true, + "D-Proposed-OL-LI2-1_SO1-dM": true, + "D-Proposed-OL-LI2-1_SO1-body": true, + "D-Proposed-OL-LI2-1_SO1-div": true, + "D-Proposed-OL-LI-1_SW-dM": true, + "D-Proposed-OL-LI-1_SW-body": true, + "D-Proposed-OL-LI-1_SW-div": true, + "D-Proposed-OL-LI-1_SO-dM": true, + "D-Proposed-OL-LI-1_SO-body": true, + "D-Proposed-OL-LI-1_SO-div": true, + "D-Proposed-HR.BR-1_SM-dM": true, + "D-Proposed-HR.BR-1_SM-body": true, + "D-Proposed-HR.BR-1_SM-div": true, + "D-Proposed-TR2rs:2-1_SO1-dM": true, + "D-Proposed-TR2rs:2-1_SO1-body": true, + "D-Proposed-TR2rs:2-1_SO1-div": true, + "D-Proposed-TR2rs:2-1_SO2-dM": true, + "D-Proposed-TR2rs:2-1_SO2-body": true, + "D-Proposed-TR2rs:2-1_SO2-div": true, + "D-Proposed-TR3rs:3-1_SO1-dM": true, + "D-Proposed-TR3rs:3-1_SO1-body": true, + "D-Proposed-TR3rs:3-1_SO1-div": true, + "D-Proposed-TR3rs:3-1_SO2-dM": true, + "D-Proposed-TR3rs:3-1_SO2-body": true, + "D-Proposed-TR3rs:3-1_SO2-div": true, + "D-Proposed-TR3rs:3-1_SO3-dM": true, + "D-Proposed-TR3rs:3-1_SO3-body": true, + "D-Proposed-TR3rs:3-1_SO3-div": true, + "D-Proposed-DIV:ce:false-1_SB-dM": true, + "D-Proposed-DIV:ce:false-1_SL-dM": true, + "D-Proposed-DIV:ce:false-1_SL-body": true, + "D-Proposed-DIV:ce:false-1_SL-div": true, + "D-Proposed-DIV:ce:false-1_SR-dM": true, + "D-Proposed-DIV:ce:false-1_SR-body": true, + "D-Proposed-DIV:ce:false-1_SR-div": true, + "D-Proposed-DIV:ce:false-1_SI-dM": true, + "D-Proposed-SPAN:d:ib-2_SL-dM": true, + "D-Proposed-SPAN:d:ib-2_SL-body": true, + "D-Proposed-SPAN:d:ib-2_SL-div": true, + "D-Proposed-SPAN:d:ib-3_SR-dM": true, + "D-Proposed-SPAN:d:ib-3_SR-body": true, + "D-Proposed-SPAN:d:ib-3_SR-div": true, + "FD-Proposed-B-1_SW-div": true, + "FD-Proposed-OL-LI-1_SW-dM": true, + "FD-Proposed-OL-LI-1_SW-body": true, + "FD-Proposed-OL-LI-1_SW-div": true, + "FD-Proposed-OL-LI-1_SO-dM": true, + "FD-Proposed-OL-LI-1_SO-body": true, + "FD-Proposed-OL-LI-1_SO-div": true, + "FD-Proposed-TABLE-1_SB-dM": true, + "FD-Proposed-TABLE-1_SB-body": true, + "FD-Proposed-TABLE-1_SB-div": true, + "FD-Proposed-TD-1_SE-dM": true, + "FD-Proposed-TD-1_SE-body": true, + "FD-Proposed-TD-1_SE-div": true, + "FD-Proposed-TD2-1_SE1-dM": true, + "FD-Proposed-TD2-1_SE1-body": true, + "FD-Proposed-TD2-1_SE1-div": true, + "FD-Proposed-TD2-1_SM-dM": true, + "FD-Proposed-TD2-1_SM-body": true, + "FD-Proposed-TD2-1_SM-div": true, + "FD-Proposed-TR2rs:2-1_SO1-dM": true, + "FD-Proposed-TR2rs:2-1_SO1-body": true, + "FD-Proposed-TR2rs:2-1_SO1-div": true, + "FD-Proposed-TR2rs:2-1_SO2-dM": true, + "FD-Proposed-TR2rs:2-1_SO2-body": true, + "FD-Proposed-TR2rs:2-1_SO2-div": true, + "FD-Proposed-TR3rs:3-1_SO1-dM": true, + "FD-Proposed-TR3rs:3-1_SO1-body": true, + "FD-Proposed-TR3rs:3-1_SO1-div": true, + "FD-Proposed-TR3rs:3-1_SO2-dM": true, + "FD-Proposed-TR3rs:3-1_SO2-body": true, + "FD-Proposed-TR3rs:3-1_SO2-div": true, + "FD-Proposed-TR3rs:3-1_SO3-dM": true, + "FD-Proposed-TR3rs:3-1_SO3-body": true, + "FD-Proposed-TR3rs:3-1_SO3-div": true, + "FD-Proposed-DIV:ce:false-1_SB-dM": true, + "FD-Proposed-DIV:ce:false-1_SB-body": true, + "FD-Proposed-DIV:ce:false-1_SB-div": true, + "FD-Proposed-DIV:ce:false-1_SL-dM": true, + "FD-Proposed-DIV:ce:false-1_SL-body": true, + "FD-Proposed-DIV:ce:false-1_SL-div": true, + "FD-Proposed-DIV:ce:false-1_SR-dM": true, + "FD-Proposed-DIV:ce:false-1_SR-body": true, + "FD-Proposed-DIV:ce:false-1_SR-div": true, + "FD-Proposed-DIV:ce:false-1_SI-dM": true, + "I-Proposed-IHR_TEXT-1_SC-dM": true, + "I-Proposed-IHR_TEXT-1_SC-body": true, + "I-Proposed-IHR_TEXT-1_SC-div": true, + "I-Proposed-IHR_TEXT-1_SI-dM": true, + "I-Proposed-IHR_TEXT-1_SI-body": true, + "I-Proposed-IHR_TEXT-1_SI-div": true, + "I-Proposed-IHR_B-1_SC-dM": true, + "I-Proposed-IHR_B-1_SC-body": true, + "I-Proposed-IHR_B-1_SC-div": true, + "I-Proposed-IHR_B-1_SS-dM": true, + "I-Proposed-IHR_B-1_SS-body": true, + "I-Proposed-IHR_B-1_SS-div": true, + "I-Proposed-IHR_B-I-1_SMR-dM": true, + "I-Proposed-IHR_B-I-1_SMR-body": true, + "I-Proposed-IHR_B-I-1_SMR-div": true, + "I-Proposed-IBR_LI-1_SC-dM": true, + "I-Proposed-IBR_LI-1_SC-body": true, + "I-Proposed-IBR_LI-1_SC-div": true, + "I-Proposed-IIMG:._SPAN-IMG-1_SO-dM": true, + "I-Proposed-IIMG:._SPAN-IMG-1_SO-body": true, + "I-Proposed-IIMG:._SPAN-IMG-1_SO-div": true, + "I-Proposed-IIMG:._IMG-1_SO-dM": true, + "I-Proposed-IIMG:._IMG-1_SO-body": true, + "I-Proposed-IIMG:._IMG-1_SO-div": true, + "I-Proposed-IHTML:BR_TEXT-1_SC-dM": true, + "I-Proposed-IHTML:BR_TEXT-1_SC-body": true, + "I-Proposed-IHTML:BR_TEXT-1_SC-div": true, + "I-Proposed-IHTML:S_TEXT-1_SI-dM": true, + "I-Proposed-IHTML:S_TEXT-1_SI-body": true, + "I-Proposed-IHTML:S_TEXT-1_SI-div": true, + "I-Proposed-IHTML:H1.H2_TEXT-1_SI-dM": true, + "I-Proposed-IHTML:H1.H2_TEXT-1_SI-body": true, + "I-Proposed-IHTML:H1.H2_TEXT-1_SI-div": true, + "I-Proposed-IHTML:P-B_TEXT-1_SI-dM": true, + "I-Proposed-IHTML:P-B_TEXT-1_SI-body": true, + "I-Proposed-IHTML:P-B_TEXT-1_SI-div": true, + "Q-Proposed-SELECTALL_TEXT-1-dM": true, + "Q-Proposed-SELECTALL_TEXT-1-body": true, + "Q-Proposed-SELECTALL_TEXT-1-div": true, + "Q-Proposed-UNSELECT_TEXT-1-dM": true, + "Q-Proposed-UNSELECT_TEXT-1-body": true, + "Q-Proposed-UNSELECT_TEXT-1-div": true, + "Q-Proposed-UNDO_TEXT-1-dM": true, + "Q-Proposed-UNDO_TEXT-1-body": true, + "Q-Proposed-UNDO_TEXT-1-div": true, + "Q-Proposed-REDO_TEXT-1-dM": true, + "Q-Proposed-REDO_TEXT-1-body": true, + "Q-Proposed-REDO_TEXT-1-div": true, + "Q-Proposed-BOLD_TEXT-1-dM": true, + "Q-Proposed-BOLD_TEXT-1-body": true, + "Q-Proposed-BOLD_TEXT-1-div": true, + "Q-Proposed-BOLD_B-dM": true, + "Q-Proposed-BOLD_B-body": true, + "Q-Proposed-BOLD_B-div": true, + "Q-Proposed-ITALIC_TEXT-1-dM": true, + "Q-Proposed-ITALIC_TEXT-1-body": true, + "Q-Proposed-ITALIC_TEXT-1-div": true, + "Q-Proposed-ITALIC_I-dM": true, + "Q-Proposed-ITALIC_I-body": true, + "Q-Proposed-ITALIC_I-div": true, + "Q-Proposed-UNDERLINE_TEXT-1-dM": true, + "Q-Proposed-UNDERLINE_TEXT-1-body": true, + "Q-Proposed-UNDERLINE_TEXT-1-div": true, + "Q-Proposed-STRIKETHROUGH_TEXT-1-dM": true, + "Q-Proposed-STRIKETHROUGH_TEXT-1-body": true, + "Q-Proposed-STRIKETHROUGH_TEXT-1-div": true, + "Q-Proposed-SUBSCRIPT_TEXT-1-dM": true, + "Q-Proposed-SUBSCRIPT_TEXT-1-body": true, + "Q-Proposed-SUBSCRIPT_TEXT-1-div": true, + "Q-Proposed-SUPERSCRIPT_TEXT-1-dM": true, + "Q-Proposed-SUPERSCRIPT_TEXT-1-body": true, + "Q-Proposed-SUPERSCRIPT_TEXT-1-div": true, + "Q-Proposed-FORMATBLOCK_TEXT-1-dM": true, + "Q-Proposed-FORMATBLOCK_TEXT-1-body": true, + "Q-Proposed-FORMATBLOCK_TEXT-1-div": true, + "Q-Proposed-CREATELINK_TEXT-1-dM": true, + "Q-Proposed-CREATELINK_TEXT-1-body": true, + "Q-Proposed-CREATELINK_TEXT-1-div": true, + "Q-Proposed-UNLINK_TEXT-1-dM": true, + "Q-Proposed-UNLINK_TEXT-1-body": true, + "Q-Proposed-UNLINK_TEXT-1-div": true, + "Q-Proposed-INSERTHTML_TEXT-1-dM": true, + "Q-Proposed-INSERTHTML_TEXT-1-body": true, + "Q-Proposed-INSERTHTML_TEXT-1-div": true, + "Q-Proposed-INSERTHORIZONTALRULE_TEXT-1-dM": true, + "Q-Proposed-INSERTHORIZONTALRULE_TEXT-1-body": true, + "Q-Proposed-INSERTHORIZONTALRULE_TEXT-1-div": true, + "Q-Proposed-INSERTIMAGE_TEXT-1-dM": true, + "Q-Proposed-INSERTIMAGE_TEXT-1-body": true, + "Q-Proposed-INSERTIMAGE_TEXT-1-div": true, + "Q-Proposed-INSERTLINEBREAK_TEXT-1-dM": true, + "Q-Proposed-INSERTLINEBREAK_TEXT-1-body": true, + "Q-Proposed-INSERTLINEBREAK_TEXT-1-div": true, + "Q-Proposed-INSERTPARAGRAPH_TEXT-1-dM": true, + "Q-Proposed-INSERTPARAGRAPH_TEXT-1-body": true, + "Q-Proposed-INSERTPARAGRAPH_TEXT-1-div": true, + "Q-Proposed-INSERTORDEREDLIST_TEXT-1-dM": true, + "Q-Proposed-INSERTORDEREDLIST_TEXT-1-body": true, + "Q-Proposed-INSERTORDEREDLIST_TEXT-1-div": true, + "Q-Proposed-INSERTUNORDEREDLIST_TEXT-1-dM": true, + "Q-Proposed-INSERTUNORDEREDLIST_TEXT-1-body": true, + "Q-Proposed-INSERTUNORDEREDLIST_TEXT-1-div": true, + "Q-Proposed-INSERTTEXT_TEXT-1-dM": true, + "Q-Proposed-INSERTTEXT_TEXT-1-body": true, + "Q-Proposed-INSERTTEXT_TEXT-1-div": true, + "Q-Proposed-DELETE_TEXT-1-dM": true, + "Q-Proposed-DELETE_TEXT-1-body": true, + "Q-Proposed-DELETE_TEXT-1-div": true, + "Q-Proposed-FORWARDDELETE_TEXT-1-dM": true, + "Q-Proposed-FORWARDDELETE_TEXT-1-body": true, + "Q-Proposed-FORWARDDELETE_TEXT-1-div": true, + "Q-Proposed-STYLEWITHCSS_TEXT-1-dM": true, + "Q-Proposed-STYLEWITHCSS_TEXT-1-body": true, + "Q-Proposed-STYLEWITHCSS_TEXT-1-div": true, + "Q-Proposed-CONTENTREADONLY_TEXT-1-dM": true, + "Q-Proposed-CONTENTREADONLY_TEXT-1-body": true, + "Q-Proposed-CONTENTREADONLY_TEXT-1-div": true, + "Q-Proposed-BACKCOLOR_TEXT-1-dM": true, + "Q-Proposed-BACKCOLOR_TEXT-1-body": true, + "Q-Proposed-BACKCOLOR_TEXT-1-div": true, + "Q-Proposed-FORECOLOR_TEXT-1-dM": true, + "Q-Proposed-FORECOLOR_TEXT-1-body": true, + "Q-Proposed-FORECOLOR_TEXT-1-div": true, + "Q-Proposed-HILITECOLOR_TEXT-1-dM": true, + "Q-Proposed-HILITECOLOR_TEXT-1-body": true, + "Q-Proposed-HILITECOLOR_TEXT-1-div": true, + "Q-Proposed-FONTNAME_TEXT-1-dM": true, + "Q-Proposed-FONTNAME_TEXT-1-body": true, + "Q-Proposed-FONTNAME_TEXT-1-div": true, + "Q-Proposed-FONTSIZE_TEXT-1-dM": true, + "Q-Proposed-FONTSIZE_TEXT-1-body": true, + "Q-Proposed-FONTSIZE_TEXT-1-div": true, + "Q-Proposed-INCREASEFONTSIZE_TEXT-1-dM": true, + "Q-Proposed-INCREASEFONTSIZE_TEXT-1-body": true, + "Q-Proposed-INCREASEFONTSIZE_TEXT-1-div": true, + "Q-Proposed-DECREASEFONTSIZE_TEXT-1-dM": true, + "Q-Proposed-DECREASEFONTSIZE_TEXT-1-body": true, + "Q-Proposed-DECREASEFONTSIZE_TEXT-1-div": true, + "Q-Proposed-HEADING_TEXT-1-dM": true, + "Q-Proposed-HEADING_TEXT-1-body": true, + "Q-Proposed-HEADING_TEXT-1-div": true, + "Q-Proposed-INDENT_TEXT-1-dM": true, + "Q-Proposed-INDENT_TEXT-1-body": true, + "Q-Proposed-INDENT_TEXT-1-div": true, + "Q-Proposed-OUTDENT_TEXT-1-dM": true, + "Q-Proposed-OUTDENT_TEXT-1-body": true, + "Q-Proposed-OUTDENT_TEXT-1-div": true, + "Q-Proposed-CREATEBOOKMARK_TEXT-1-dM": true, + "Q-Proposed-CREATEBOOKMARK_TEXT-1-body": true, + "Q-Proposed-CREATEBOOKMARK_TEXT-1-div": true, + "Q-Proposed-UNBOOKMARK_TEXT-1-dM": true, + "Q-Proposed-UNBOOKMARK_TEXT-1-body": true, + "Q-Proposed-UNBOOKMARK_TEXT-1-div": true, + "Q-Proposed-JUSTIFYCENTER_TEXT-1-dM": true, + "Q-Proposed-JUSTIFYCENTER_TEXT-1-body": true, + "Q-Proposed-JUSTIFYCENTER_TEXT-1-div": true, + "Q-Proposed-JUSTIFYFULL_TEXT-1-dM": true, + "Q-Proposed-JUSTIFYFULL_TEXT-1-body": true, + "Q-Proposed-JUSTIFYFULL_TEXT-1-div": true, + "Q-Proposed-JUSTIFYLEFT_TEXT-1-dM": true, + "Q-Proposed-JUSTIFYLEFT_TEXT-1-body": true, + "Q-Proposed-JUSTIFYLEFT_TEXT-1-div": true, + "Q-Proposed-JUSTIFYRIGHT_TEXT-1-dM": true, + "Q-Proposed-JUSTIFYRIGHT_TEXT-1-body": true, + "Q-Proposed-JUSTIFYRIGHT_TEXT-1-div": true, + "Q-Proposed-REMOVEFORMAT_TEXT-1-dM": true, + "Q-Proposed-REMOVEFORMAT_TEXT-1-body": true, + "Q-Proposed-REMOVEFORMAT_TEXT-1-div": true, + "Q-Proposed-COPY_TEXT-1-dM": true, + "Q-Proposed-COPY_TEXT-1-body": true, + "Q-Proposed-COPY_TEXT-1-div": true, + "Q-Proposed-CUT_TEXT-1-dM": true, + "Q-Proposed-CUT_TEXT-1-body": true, + "Q-Proposed-CUT_TEXT-1-div": true, + "Q-Proposed-PASTE_TEXT-1-dM": true, + "Q-Proposed-PASTE_TEXT-1-body": true, + "Q-Proposed-PASTE_TEXT-1-div": true, + "Q-Proposed-garbage-1_TEXT-1-dM": true, + "Q-Proposed-garbage-1_TEXT-1-body": true, + "Q-Proposed-garbage-1_TEXT-1-div": true, + "QE-Proposed-SELECTALL_TEXT-1-dM": true, + "QE-Proposed-SELECTALL_TEXT-1-body": true, + "QE-Proposed-SELECTALL_TEXT-1-div": true, + "QE-Proposed-UNSELECT_TEXT-1-dM": true, + "QE-Proposed-UNSELECT_TEXT-1-body": true, + "QE-Proposed-UNSELECT_TEXT-1-div": true, + "QE-Proposed-UNDO_TEXT-1-dM": true, + "QE-Proposed-UNDO_TEXT-1-body": true, + "QE-Proposed-UNDO_TEXT-1-div": true, + "QE-Proposed-REDO_TEXT-1-dM": true, + "QE-Proposed-REDO_TEXT-1-body": true, + "QE-Proposed-REDO_TEXT-1-div": true, + "QE-Proposed-BOLD_TEXT-1-dM": true, + "QE-Proposed-BOLD_TEXT-1-body": true, + "QE-Proposed-BOLD_TEXT-1-div": true, + "QE-Proposed-ITALIC_TEXT-1-dM": true, + "QE-Proposed-ITALIC_TEXT-1-body": true, + "QE-Proposed-ITALIC_TEXT-1-div": true, + "QE-Proposed-UNDERLINE_TEXT-1-dM": true, + "QE-Proposed-UNDERLINE_TEXT-1-body": true, + "QE-Proposed-UNDERLINE_TEXT-1-div": true, + "QE-Proposed-STRIKETHROUGH_TEXT-1-dM": true, + "QE-Proposed-STRIKETHROUGH_TEXT-1-body": true, + "QE-Proposed-STRIKETHROUGH_TEXT-1-div": true, + "QE-Proposed-SUBSCRIPT_TEXT-1-dM": true, + "QE-Proposed-SUBSCRIPT_TEXT-1-body": true, + "QE-Proposed-SUBSCRIPT_TEXT-1-div": true, + "QE-Proposed-SUPERSCRIPT_TEXT-1-dM": true, + "QE-Proposed-SUPERSCRIPT_TEXT-1-body": true, + "QE-Proposed-SUPERSCRIPT_TEXT-1-div": true, + "QE-Proposed-FORMATBLOCK_TEXT-1-dM": true, + "QE-Proposed-FORMATBLOCK_TEXT-1-body": true, + "QE-Proposed-FORMATBLOCK_TEXT-1-div": true, + "QE-Proposed-CREATELINK_TEXT-1-dM": true, + "QE-Proposed-CREATELINK_TEXT-1-body": true, + "QE-Proposed-CREATELINK_TEXT-1-div": true, + "QE-Proposed-UNLINK_TEXT-1-dM": true, + "QE-Proposed-UNLINK_TEXT-1-body": true, + "QE-Proposed-UNLINK_TEXT-1-div": true, + "QE-Proposed-INSERTHTML_TEXT-1-dM": true, + "QE-Proposed-INSERTHTML_TEXT-1-body": true, + "QE-Proposed-INSERTHTML_TEXT-1-div": true, + "QE-Proposed-INSERTHORIZONTALRULE_TEXT-1-dM": true, + "QE-Proposed-INSERTHORIZONTALRULE_TEXT-1-body": true, + "QE-Proposed-INSERTHORIZONTALRULE_TEXT-1-div": true, + "QE-Proposed-INSERTIMAGE_TEXT-1-dM": true, + "QE-Proposed-INSERTIMAGE_TEXT-1-body": true, + "QE-Proposed-INSERTIMAGE_TEXT-1-div": true, + "QE-Proposed-INSERTLINEBREAK_TEXT-1-dM": true, + "QE-Proposed-INSERTLINEBREAK_TEXT-1-body": true, + "QE-Proposed-INSERTLINEBREAK_TEXT-1-div": true, + "QE-Proposed-INSERTPARAGRAPH_TEXT-1-dM": true, + "QE-Proposed-INSERTPARAGRAPH_TEXT-1-body": true, + "QE-Proposed-INSERTPARAGRAPH_TEXT-1-div": true, + "QE-Proposed-INSERTORDEREDLIST_TEXT-1-dM": true, + "QE-Proposed-INSERTORDEREDLIST_TEXT-1-body": true, + "QE-Proposed-INSERTORDEREDLIST_TEXT-1-div": true, + "QE-Proposed-INSERTUNORDEREDLIST_TEXT-1-dM": true, + "QE-Proposed-INSERTUNORDEREDLIST_TEXT-1-body": true, + "QE-Proposed-INSERTUNORDEREDLIST_TEXT-1-div": true, + "QE-Proposed-INSERTTEXT_TEXT-1-dM": true, + "QE-Proposed-INSERTTEXT_TEXT-1-body": true, + "QE-Proposed-INSERTTEXT_TEXT-1-div": true, + "QE-Proposed-DELETE_TEXT-1-dM": true, + "QE-Proposed-DELETE_TEXT-1-body": true, + "QE-Proposed-DELETE_TEXT-1-div": true, + "QE-Proposed-FORWARDDELETE_TEXT-1-dM": true, + "QE-Proposed-FORWARDDELETE_TEXT-1-body": true, + "QE-Proposed-FORWARDDELETE_TEXT-1-div": true, + "QE-Proposed-STYLEWITHCSS_TEXT-1-dM": true, + "QE-Proposed-STYLEWITHCSS_TEXT-1-body": true, + "QE-Proposed-STYLEWITHCSS_TEXT-1-div": true, + "QE-Proposed-CONTENTREADONLY_TEXT-1-dM": true, + "QE-Proposed-CONTENTREADONLY_TEXT-1-body": true, + "QE-Proposed-CONTENTREADONLY_TEXT-1-div": true, + "QE-Proposed-BACKCOLOR_TEXT-1-dM": true, + "QE-Proposed-BACKCOLOR_TEXT-1-body": true, + "QE-Proposed-BACKCOLOR_TEXT-1-div": true, + "QE-Proposed-FORECOLOR_TEXT-1-dM": true, + "QE-Proposed-FORECOLOR_TEXT-1-body": true, + "QE-Proposed-FORECOLOR_TEXT-1-div": true, + "QE-Proposed-HILITECOLOR_TEXT-1-dM": true, + "QE-Proposed-HILITECOLOR_TEXT-1-body": true, + "QE-Proposed-HILITECOLOR_TEXT-1-div": true, + "QE-Proposed-FONTNAME_TEXT-1-dM": true, + "QE-Proposed-FONTNAME_TEXT-1-body": true, + "QE-Proposed-FONTNAME_TEXT-1-div": true, + "QE-Proposed-FONTSIZE_TEXT-1-dM": true, + "QE-Proposed-FONTSIZE_TEXT-1-body": true, + "QE-Proposed-FONTSIZE_TEXT-1-div": true, + "QE-Proposed-INCREASEFONTSIZE_TEXT-1-dM": true, + "QE-Proposed-INCREASEFONTSIZE_TEXT-1-body": true, + "QE-Proposed-INCREASEFONTSIZE_TEXT-1-div": true, + "QE-Proposed-DECREASEFONTSIZE_TEXT-1-dM": true, + "QE-Proposed-DECREASEFONTSIZE_TEXT-1-body": true, + "QE-Proposed-DECREASEFONTSIZE_TEXT-1-div": true, + "QE-Proposed-HEADING_TEXT-1-dM": true, + "QE-Proposed-HEADING_TEXT-1-body": true, + "QE-Proposed-HEADING_TEXT-1-div": true, + "QE-Proposed-INDENT_TEXT-1-dM": true, + "QE-Proposed-INDENT_TEXT-1-body": true, + "QE-Proposed-INDENT_TEXT-1-div": true, + "QE-Proposed-OUTDENT_TEXT-1-dM": true, + "QE-Proposed-OUTDENT_TEXT-1-body": true, + "QE-Proposed-OUTDENT_TEXT-1-div": true, + "QE-Proposed-CREATEBOOKMARK_TEXT-1-dM": true, + "QE-Proposed-CREATEBOOKMARK_TEXT-1-body": true, + "QE-Proposed-CREATEBOOKMARK_TEXT-1-div": true, + "QE-Proposed-UNBOOKMARK_TEXT-1-dM": true, + "QE-Proposed-UNBOOKMARK_TEXT-1-body": true, + "QE-Proposed-UNBOOKMARK_TEXT-1-div": true, + "QE-Proposed-JUSTIFYCENTER_TEXT-1-dM": true, + "QE-Proposed-JUSTIFYCENTER_TEXT-1-body": true, + "QE-Proposed-JUSTIFYCENTER_TEXT-1-div": true, + "QE-Proposed-JUSTIFYFULL_TEXT-1-dM": true, + "QE-Proposed-JUSTIFYFULL_TEXT-1-body": true, + "QE-Proposed-JUSTIFYFULL_TEXT-1-div": true, + "QE-Proposed-JUSTIFYLEFT_TEXT-1-dM": true, + "QE-Proposed-JUSTIFYLEFT_TEXT-1-body": true, + "QE-Proposed-JUSTIFYLEFT_TEXT-1-div": true, + "QE-Proposed-JUSTIFYRIGHT_TEXT-1-dM": true, + "QE-Proposed-JUSTIFYRIGHT_TEXT-1-body": true, + "QE-Proposed-JUSTIFYRIGHT_TEXT-1-div": true, + "QE-Proposed-REMOVEFORMAT_TEXT-1-dM": true, + "QE-Proposed-REMOVEFORMAT_TEXT-1-body": true, + "QE-Proposed-REMOVEFORMAT_TEXT-1-div": true, + "QE-Proposed-COPY_TEXT-1-dM": true, + "QE-Proposed-COPY_TEXT-1-body": true, + "QE-Proposed-COPY_TEXT-1-div": true, + "QE-Proposed-CUT_TEXT-1-dM": true, + "QE-Proposed-CUT_TEXT-1-body": true, + "QE-Proposed-CUT_TEXT-1-div": true, + "QE-Proposed-PASTE_TEXT-1-dM": true, + "QE-Proposed-PASTE_TEXT-1-body": true, + "QE-Proposed-PASTE_TEXT-1-div": true, + "QE-Proposed-garbage-1_TEXT-1-dM": true, + "QE-Proposed-garbage-1_TEXT-1-body": true, + "QE-Proposed-garbage-1_TEXT-1-div": true, + "QI-Proposed-SELECTALL_TEXT-1-dM": true, + "QI-Proposed-SELECTALL_TEXT-1-body": true, + "QI-Proposed-SELECTALL_TEXT-1-div": true, + "QI-Proposed-UNSELECT_TEXT-1-dM": true, + "QI-Proposed-UNSELECT_TEXT-1-body": true, + "QI-Proposed-UNSELECT_TEXT-1-div": true, + "QI-Proposed-UNDO_TEXT-1-dM": true, + "QI-Proposed-UNDO_TEXT-1-body": true, + "QI-Proposed-UNDO_TEXT-1-div": true, + "QI-Proposed-REDO_TEXT-1-dM": true, + "QI-Proposed-REDO_TEXT-1-body": true, + "QI-Proposed-REDO_TEXT-1-div": true, + "QI-Proposed-BOLD_TEXT-1-dM": true, + "QI-Proposed-BOLD_TEXT-1-body": true, + "QI-Proposed-BOLD_TEXT-1-div": true, + "QI-Proposed-ITALIC_TEXT-1-dM": true, + "QI-Proposed-ITALIC_TEXT-1-body": true, + "QI-Proposed-ITALIC_TEXT-1-div": true, + "QI-Proposed-UNDERLINE_TEXT-1-dM": true, + "QI-Proposed-UNDERLINE_TEXT-1-body": true, + "QI-Proposed-UNDERLINE_TEXT-1-div": true, + "QI-Proposed-STRIKETHROUGH_TEXT-1-dM": true, + "QI-Proposed-STRIKETHROUGH_TEXT-1-body": true, + "QI-Proposed-STRIKETHROUGH_TEXT-1-div": true, + "QI-Proposed-SUBSCRIPT_TEXT-1-dM": true, + "QI-Proposed-SUBSCRIPT_TEXT-1-body": true, + "QI-Proposed-SUBSCRIPT_TEXT-1-div": true, + "QI-Proposed-SUPERSCRIPT_TEXT-1-dM": true, + "QI-Proposed-SUPERSCRIPT_TEXT-1-body": true, + "QI-Proposed-SUPERSCRIPT_TEXT-1-div": true, + "QI-Proposed-FORMATBLOCK_TEXT-1-dM": true, + "QI-Proposed-FORMATBLOCK_TEXT-1-body": true, + "QI-Proposed-FORMATBLOCK_TEXT-1-div": true, + "QI-Proposed-CREATELINK_TEXT-1-dM": true, + "QI-Proposed-CREATELINK_TEXT-1-body": true, + "QI-Proposed-CREATELINK_TEXT-1-div": true, + "QI-Proposed-UNLINK_TEXT-1-dM": true, + "QI-Proposed-UNLINK_TEXT-1-body": true, + "QI-Proposed-UNLINK_TEXT-1-div": true, + "QI-Proposed-INSERTHTML_TEXT-1-dM": true, + "QI-Proposed-INSERTHTML_TEXT-1-body": true, + "QI-Proposed-INSERTHTML_TEXT-1-div": true, + "QI-Proposed-INSERTHORIZONTALRULE_TEXT-1-dM": true, + "QI-Proposed-INSERTHORIZONTALRULE_TEXT-1-body": true, + "QI-Proposed-INSERTHORIZONTALRULE_TEXT-1-div": true, + "QI-Proposed-INSERTIMAGE_TEXT-1-dM": true, + "QI-Proposed-INSERTIMAGE_TEXT-1-body": true, + "QI-Proposed-INSERTIMAGE_TEXT-1-div": true, + "QI-Proposed-INSERTLINEBREAK_TEXT-1-dM": true, + "QI-Proposed-INSERTLINEBREAK_TEXT-1-body": true, + "QI-Proposed-INSERTLINEBREAK_TEXT-1-div": true, + "QI-Proposed-INSERTPARAGRAPH_TEXT-1-dM": true, + "QI-Proposed-INSERTPARAGRAPH_TEXT-1-body": true, + "QI-Proposed-INSERTPARAGRAPH_TEXT-1-div": true, + "QI-Proposed-INSERTORDEREDLIST_TEXT-1-dM": true, + "QI-Proposed-INSERTORDEREDLIST_TEXT-1-body": true, + "QI-Proposed-INSERTORDEREDLIST_TEXT-1-div": true, + "QI-Proposed-INSERTUNORDEREDLIST_TEXT-1-dM": true, + "QI-Proposed-INSERTUNORDEREDLIST_TEXT-1-body": true, + "QI-Proposed-INSERTUNORDEREDLIST_TEXT-1-div": true, + "QI-Proposed-INSERTTEXT_TEXT-1-dM": true, + "QI-Proposed-INSERTTEXT_TEXT-1-body": true, + "QI-Proposed-INSERTTEXT_TEXT-1-div": true, + "QI-Proposed-DELETE_TEXT-1-dM": true, + "QI-Proposed-DELETE_TEXT-1-body": true, + "QI-Proposed-DELETE_TEXT-1-div": true, + "QI-Proposed-FORWARDDELETE_TEXT-1-dM": true, + "QI-Proposed-FORWARDDELETE_TEXT-1-body": true, + "QI-Proposed-FORWARDDELETE_TEXT-1-div": true, + "QI-Proposed-STYLEWITHCSS_TEXT-1-dM": true, + "QI-Proposed-STYLEWITHCSS_TEXT-1-body": true, + "QI-Proposed-STYLEWITHCSS_TEXT-1-div": true, + "QI-Proposed-CONTENTREADONLY_TEXT-1-dM": true, + "QI-Proposed-CONTENTREADONLY_TEXT-1-body": true, + "QI-Proposed-CONTENTREADONLY_TEXT-1-div": true, + "QI-Proposed-BACKCOLOR_TEXT-1-dM": true, + "QI-Proposed-BACKCOLOR_TEXT-1-body": true, + "QI-Proposed-BACKCOLOR_TEXT-1-div": true, + "QI-Proposed-FORECOLOR_TEXT-1-dM": true, + "QI-Proposed-FORECOLOR_TEXT-1-body": true, + "QI-Proposed-FORECOLOR_TEXT-1-div": true, + "QI-Proposed-HILITECOLOR_TEXT-1-dM": true, + "QI-Proposed-HILITECOLOR_TEXT-1-body": true, + "QI-Proposed-HILITECOLOR_TEXT-1-div": true, + "QI-Proposed-FONTNAME_TEXT-1-dM": true, + "QI-Proposed-FONTNAME_TEXT-1-body": true, + "QI-Proposed-FONTNAME_TEXT-1-div": true, + "QI-Proposed-FONTSIZE_TEXT-1-dM": true, + "QI-Proposed-FONTSIZE_TEXT-1-body": true, + "QI-Proposed-FONTSIZE_TEXT-1-div": true, + "QI-Proposed-INCREASEFONTSIZE_TEXT-1-dM": true, + "QI-Proposed-INCREASEFONTSIZE_TEXT-1-body": true, + "QI-Proposed-INCREASEFONTSIZE_TEXT-1-div": true, + "QI-Proposed-DECREASEFONTSIZE_TEXT-1-dM": true, + "QI-Proposed-DECREASEFONTSIZE_TEXT-1-body": true, + "QI-Proposed-DECREASEFONTSIZE_TEXT-1-div": true, + "QI-Proposed-HEADING_TEXT-1-dM": true, + "QI-Proposed-HEADING_TEXT-1-body": true, + "QI-Proposed-HEADING_TEXT-1-div": true, + "QI-Proposed-INDENT_TEXT-1-dM": true, + "QI-Proposed-INDENT_TEXT-1-body": true, + "QI-Proposed-INDENT_TEXT-1-div": true, + "QI-Proposed-OUTDENT_TEXT-1-dM": true, + "QI-Proposed-OUTDENT_TEXT-1-body": true, + "QI-Proposed-OUTDENT_TEXT-1-div": true, + "QI-Proposed-CREATEBOOKMARK_TEXT-1-dM": true, + "QI-Proposed-CREATEBOOKMARK_TEXT-1-body": true, + "QI-Proposed-CREATEBOOKMARK_TEXT-1-div": true, + "QI-Proposed-UNBOOKMARK_TEXT-1-dM": true, + "QI-Proposed-UNBOOKMARK_TEXT-1-body": true, + "QI-Proposed-UNBOOKMARK_TEXT-1-div": true, + "QI-Proposed-JUSTIFYCENTER_TEXT-1-dM": true, + "QI-Proposed-JUSTIFYCENTER_TEXT-1-body": true, + "QI-Proposed-JUSTIFYCENTER_TEXT-1-div": true, + "QI-Proposed-JUSTIFYFULL_TEXT-1-dM": true, + "QI-Proposed-JUSTIFYFULL_TEXT-1-body": true, + "QI-Proposed-JUSTIFYFULL_TEXT-1-div": true, + "QI-Proposed-JUSTIFYLEFT_TEXT-1-dM": true, + "QI-Proposed-JUSTIFYLEFT_TEXT-1-body": true, + "QI-Proposed-JUSTIFYLEFT_TEXT-1-div": true, + "QI-Proposed-JUSTIFYRIGHT_TEXT-1-dM": true, + "QI-Proposed-JUSTIFYRIGHT_TEXT-1-body": true, + "QI-Proposed-JUSTIFYRIGHT_TEXT-1-div": true, + "QI-Proposed-REMOVEFORMAT_TEXT-1-dM": true, + "QI-Proposed-REMOVEFORMAT_TEXT-1-body": true, + "QI-Proposed-REMOVEFORMAT_TEXT-1-div": true, + "QI-Proposed-COPY_TEXT-1-dM": true, + "QI-Proposed-COPY_TEXT-1-body": true, + "QI-Proposed-COPY_TEXT-1-div": true, + "QI-Proposed-CUT_TEXT-1-dM": true, + "QI-Proposed-CUT_TEXT-1-body": true, + "QI-Proposed-CUT_TEXT-1-div": true, + "QI-Proposed-PASTE_TEXT-1-dM": true, + "QI-Proposed-PASTE_TEXT-1-body": true, + "QI-Proposed-PASTE_TEXT-1-div": true, + "QI-Proposed-garbage-1_TEXT-1-dM": true, + "QI-Proposed-garbage-1_TEXT-1-body": true, + "QI-Proposed-garbage-1_TEXT-1-div": true, + "QS-Proposed-B_TEXT_SI-dM": true, + "QS-Proposed-B_TEXT_SI-body": true, + "QS-Proposed-B_TEXT_SI-div": true, + "QS-Proposed-B_B-1_SI-dM": true, + "QS-Proposed-B_B-1_SI-body": true, + "QS-Proposed-B_B-1_SI-div": true, + "QS-Proposed-B_STRONG-1_SI-dM": true, + "QS-Proposed-B_STRONG-1_SI-body": true, + "QS-Proposed-B_STRONG-1_SI-div": true, + "QS-Proposed-B_SPANs:fw:b-1_SI-dM": true, + "QS-Proposed-B_SPANs:fw:b-1_SI-body": true, + "QS-Proposed-B_SPANs:fw:b-1_SI-div": true, + "QS-Proposed-B_SPANs:fw:n-1_SI-dM": true, + "QS-Proposed-B_SPANs:fw:n-1_SI-body": true, + "QS-Proposed-B_SPANs:fw:n-1_SI-div": true, + "QS-Proposed-B_Bs:fw:n-1_SI-dM": true, + "QS-Proposed-B_Bs:fw:n-1_SI-body": true, + "QS-Proposed-B_Bs:fw:n-1_SI-div": true, + "QS-Proposed-B_B-SPANs:fw:n-1_SI-dM": true, + "QS-Proposed-B_B-SPANs:fw:n-1_SI-body": true, + "QS-Proposed-B_B-SPANs:fw:n-1_SI-div": true, + "QS-Proposed-B_SPAN.b-1-SI-dM": true, + "QS-Proposed-B_SPAN.b-1-SI-body": true, + "QS-Proposed-B_SPAN.b-1-SI-div": true, + "QS-Proposed-B_MYB-1-SI-dM": true, + "QS-Proposed-B_MYB-1-SI-body": true, + "QS-Proposed-B_MYB-1-SI-div": true, + "QS-Proposed-B_B-I-1_SC-dM": true, + "QS-Proposed-B_B-I-1_SC-body": true, + "QS-Proposed-B_B-I-1_SC-div": true, + "QS-Proposed-B_B-I-1_SL-dM": true, + "QS-Proposed-B_B-I-1_SL-body": true, + "QS-Proposed-B_B-I-1_SL-div": true, + "QS-Proposed-B_B-I-1_SR-dM": true, + "QS-Proposed-B_B-I-1_SR-body": true, + "QS-Proposed-B_B-I-1_SR-div": true, + "QS-Proposed-B_STRONG-I-1_SC-dM": true, + "QS-Proposed-B_STRONG-I-1_SC-body": true, + "QS-Proposed-B_STRONG-I-1_SC-div": true, + "QS-Proposed-B_B-I-U-1_SC-dM": true, + "QS-Proposed-B_B-I-U-1_SC-body": true, + "QS-Proposed-B_B-I-U-1_SC-div": true, + "QS-Proposed-B_B-I-U-1_SM-dM": true, + "QS-Proposed-B_B-I-U-1_SM-body": true, + "QS-Proposed-B_B-I-U-1_SM-div": true, + "QS-Proposed-B_TEXT-B-1_SO-1-dM": true, + "QS-Proposed-B_TEXT-B-1_SO-1-body": true, + "QS-Proposed-B_TEXT-B-1_SO-1-div": true, + "QS-Proposed-B_TEXT-B-1_SO-2-dM": true, + "QS-Proposed-B_TEXT-B-1_SO-2-body": true, + "QS-Proposed-B_TEXT-B-1_SO-2-div": true, + "QS-Proposed-B_TEXT-B-1_SL-dM": true, + "QS-Proposed-B_TEXT-B-1_SL-body": true, + "QS-Proposed-B_TEXT-B-1_SL-div": true, + "QS-Proposed-B_TEXT-B-1_SR-dM": true, + "QS-Proposed-B_TEXT-B-1_SR-body": true, + "QS-Proposed-B_TEXT-B-1_SR-div": true, + "QS-Proposed-B_TEXT-B-1_SO-3-dM": true, + "QS-Proposed-B_TEXT-B-1_SO-3-body": true, + "QS-Proposed-B_TEXT-B-1_SO-3-div": true, + "QS-Proposed-B_B.TEXT.B-1_SM-dM": true, + "QS-Proposed-B_B.TEXT.B-1_SM-body": true, + "QS-Proposed-B_B.TEXT.B-1_SM-div": true, + "QS-Proposed-B_B.B.B-1_SM-dM": true, + "QS-Proposed-B_B.B.B-1_SM-body": true, + "QS-Proposed-B_B.B.B-1_SM-div": true, + "QS-Proposed-B_B.STRONG.B-1_SM-dM": true, + "QS-Proposed-B_B.STRONG.B-1_SM-body": true, + "QS-Proposed-B_B.STRONG.B-1_SM-div": true, + "QS-Proposed-B_SPAN.b.MYB.SPANs:fw:b-1_SM-dM": true, + "QS-Proposed-B_SPAN.b.MYB.SPANs:fw:b-1_SM-body": true, + "QS-Proposed-B_SPAN.b.MYB.SPANs:fw:b-1_SM-div": true, + "QS-Proposed-I_TEXT_SI-dM": true, + "QS-Proposed-I_TEXT_SI-body": true, + "QS-Proposed-I_TEXT_SI-div": true, + "QS-Proposed-I_I-1_SI-dM": true, + "QS-Proposed-I_I-1_SI-body": true, + "QS-Proposed-I_I-1_SI-div": true, + "QS-Proposed-I_EM-1_SI-dM": true, + "QS-Proposed-I_EM-1_SI-body": true, + "QS-Proposed-I_EM-1_SI-div": true, + "QS-Proposed-I_SPANs:fs:i-1_SI-dM": true, + "QS-Proposed-I_SPANs:fs:i-1_SI-body": true, + "QS-Proposed-I_SPANs:fs:i-1_SI-div": true, + "QS-Proposed-I_SPANs:fs:n-1_SI-dM": true, + "QS-Proposed-I_SPANs:fs:n-1_SI-body": true, + "QS-Proposed-I_SPANs:fs:n-1_SI-div": true, + "QS-Proposed-I_I-SPANs:fs:n-1_SI-dM": true, + "QS-Proposed-I_I-SPANs:fs:n-1_SI-body": true, + "QS-Proposed-I_I-SPANs:fs:n-1_SI-div": true, + "QS-Proposed-I_SPAN.i-1-SI-dM": true, + "QS-Proposed-I_SPAN.i-1-SI-body": true, + "QS-Proposed-I_SPAN.i-1-SI-div": true, + "QS-Proposed-I_MYI-1-SI-dM": true, + "QS-Proposed-I_MYI-1-SI-body": true, + "QS-Proposed-I_MYI-1-SI-div": true, + "QS-Proposed-U_TEXT_SI-dM": true, + "QS-Proposed-U_TEXT_SI-body": true, + "QS-Proposed-U_TEXT_SI-div": true, + "QS-Proposed-U_U-1_SI-dM": true, + "QS-Proposed-U_U-1_SI-body": true, + "QS-Proposed-U_U-1_SI-div": true, + "QS-Proposed-U_Us:td:n-1_SI-dM": true, + "QS-Proposed-U_Us:td:n-1_SI-body": true, + "QS-Proposed-U_Us:td:n-1_SI-div": true, + "QS-Proposed-U_Ah:url-1_SI-dM": true, + "QS-Proposed-U_Ah:url-1_SI-body": true, + "QS-Proposed-U_Ah:url-1_SI-div": true, + "QS-Proposed-U_Ah:url.s:td:n-1_SI-dM": true, + "QS-Proposed-U_Ah:url.s:td:n-1_SI-body": true, + "QS-Proposed-U_Ah:url.s:td:n-1_SI-div": true, + "QS-Proposed-U_SPANs:td:u-1_SI-dM": true, + "QS-Proposed-U_SPANs:td:u-1_SI-body": true, + "QS-Proposed-U_SPANs:td:u-1_SI-div": true, + "QS-Proposed-U_SPAN.u-1-SI-dM": true, + "QS-Proposed-U_SPAN.u-1-SI-body": true, + "QS-Proposed-U_SPAN.u-1-SI-div": true, + "QS-Proposed-U_MYU-1-SI-dM": true, + "QS-Proposed-U_MYU-1-SI-body": true, + "QS-Proposed-U_MYU-1-SI-div": true, + "QS-Proposed-S_TEXT_SI-dM": true, + "QS-Proposed-S_TEXT_SI-body": true, + "QS-Proposed-S_TEXT_SI-div": true, + "QS-Proposed-S_S-1_SI-dM": true, + "QS-Proposed-S_S-1_SI-body": true, + "QS-Proposed-S_S-1_SI-div": true, + "QS-Proposed-S_STRIKE-1_SI-dM": true, + "QS-Proposed-S_STRIKE-1_SI-body": true, + "QS-Proposed-S_STRIKE-1_SI-div": true, + "QS-Proposed-S_STRIKEs:td:n-1_SI-dM": true, + "QS-Proposed-S_STRIKEs:td:n-1_SI-body": true, + "QS-Proposed-S_STRIKEs:td:n-1_SI-div": true, + "QS-Proposed-S_DEL-1_SI-dM": true, + "QS-Proposed-S_DEL-1_SI-body": true, + "QS-Proposed-S_DEL-1_SI-div": true, + "QS-Proposed-S_SPANs:td:lt-1_SI-dM": true, + "QS-Proposed-S_SPANs:td:lt-1_SI-body": true, + "QS-Proposed-S_SPANs:td:lt-1_SI-div": true, + "QS-Proposed-S_SPAN.s-1-SI-dM": true, + "QS-Proposed-S_SPAN.s-1-SI-body": true, + "QS-Proposed-S_SPAN.s-1-SI-div": true, + "QS-Proposed-S_MYS-1-SI-dM": true, + "QS-Proposed-S_MYS-1-SI-body": true, + "QS-Proposed-S_MYS-1-SI-div": true, + "QS-Proposed-S_S.STRIKE.DEL-1_SM-dM": true, + "QS-Proposed-S_S.STRIKE.DEL-1_SM-body": true, + "QS-Proposed-S_S.STRIKE.DEL-1_SM-div": true, + "QS-Proposed-SUB_TEXT_SI-dM": true, + "QS-Proposed-SUB_TEXT_SI-body": true, + "QS-Proposed-SUB_TEXT_SI-div": true, + "QS-Proposed-SUB_SUB-1_SI-dM": true, + "QS-Proposed-SUB_SUB-1_SI-body": true, + "QS-Proposed-SUB_SUB-1_SI-div": true, + "QS-Proposed-SUB_SPAN.sub-1-SI-dM": true, + "QS-Proposed-SUB_SPAN.sub-1-SI-body": true, + "QS-Proposed-SUB_SPAN.sub-1-SI-div": true, + "QS-Proposed-SUB_MYSUB-1-SI-dM": true, + "QS-Proposed-SUB_MYSUB-1-SI-body": true, + "QS-Proposed-SUB_MYSUB-1-SI-div": true, + "QS-Proposed-SUP_TEXT_SI-dM": true, + "QS-Proposed-SUP_TEXT_SI-body": true, + "QS-Proposed-SUP_TEXT_SI-div": true, + "QS-Proposed-SUP_SUP-1_SI-dM": true, + "QS-Proposed-SUP_SUP-1_SI-body": true, + "QS-Proposed-SUP_SUP-1_SI-div": true, + "QS-Proposed-IOL_TEXT_SI-dM": true, + "QS-Proposed-IOL_TEXT_SI-body": true, + "QS-Proposed-IOL_TEXT_SI-div": true, + "QS-Proposed-SUP_SPAN.sup-1-SI-dM": true, + "QS-Proposed-SUP_SPAN.sup-1-SI-body": true, + "QS-Proposed-SUP_SPAN.sup-1-SI-div": true, + "QS-Proposed-SUP_MYSUP-1-SI-dM": true, + "QS-Proposed-SUP_MYSUP-1-SI-body": true, + "QS-Proposed-SUP_MYSUP-1-SI-div": true, + "QS-Proposed-IOL_TEXT-1_SI-dM": true, + "QS-Proposed-IOL_TEXT-1_SI-body": true, + "QS-Proposed-IOL_TEXT-1_SI-div": true, + "QS-Proposed-IOL_OL-LI-1_SI-dM": true, + "QS-Proposed-IOL_OL-LI-1_SI-body": true, + "QS-Proposed-IOL_OL-LI-1_SI-div": true, + "QS-Proposed-IOL_UL_LI-1_SI-dM": true, + "QS-Proposed-IOL_UL_LI-1_SI-body": true, + "QS-Proposed-IOL_UL_LI-1_SI-div": true, + "QS-Proposed-IUL_TEXT_SI-dM": true, + "QS-Proposed-IUL_TEXT_SI-body": true, + "QS-Proposed-IUL_TEXT_SI-div": true, + "QS-Proposed-IUL_OL-LI-1_SI-dM": true, + "QS-Proposed-IUL_OL-LI-1_SI-body": true, + "QS-Proposed-IUL_OL-LI-1_SI-div": true, + "QS-Proposed-IUL_UL-LI-1_SI-dM": true, + "QS-Proposed-IUL_UL-LI-1_SI-body": true, + "QS-Proposed-IUL_UL-LI-1_SI-div": true, + "QS-Proposed-JC_TEXT_SI-dM": true, + "QS-Proposed-JC_TEXT_SI-body": true, + "QS-Proposed-JC_TEXT_SI-div": true, + "QS-Proposed-JC_DIVa:c-1_SI-dM": true, + "QS-Proposed-JC_DIVa:c-1_SI-body": true, + "QS-Proposed-JC_DIVa:c-1_SI-div": true, + "QS-Proposed-JC_Pa:c-1_SI-dM": true, + "QS-Proposed-JC_Pa:c-1_SI-body": true, + "QS-Proposed-JC_Pa:c-1_SI-div": true, + "QS-Proposed-JC_SPANs:ta:c-1_SI-dM": true, + "QS-Proposed-JC_SPANs:ta:c-1_SI-body": true, + "QS-Proposed-JC_SPANs:ta:c-1_SI-div": true, + "QS-Proposed-JC_SPAN.jc-1-SI-dM": true, + "QS-Proposed-JC_SPAN.jc-1-SI-body": true, + "QS-Proposed-JC_SPAN.jc-1-SI-div": true, + "QS-Proposed-JC_MYJC-1-SI-dM": true, + "QS-Proposed-JC_MYJC-1-SI-body": true, + "QS-Proposed-JC_MYJC-1-SI-div": true, + "QS-Proposed-JF_TEXT_SI-dM": true, + "QS-Proposed-JF_TEXT_SI-body": true, + "QS-Proposed-JF_TEXT_SI-div": true, + "QS-Proposed-JF_DIVa:j-1_SI-dM": true, + "QS-Proposed-JF_DIVa:j-1_SI-body": true, + "QS-Proposed-JF_DIVa:j-1_SI-div": true, + "QS-Proposed-JF_Pa:j-1_SI-dM": true, + "QS-Proposed-JF_Pa:j-1_SI-body": true, + "QS-Proposed-JF_Pa:j-1_SI-div": true, + "QS-Proposed-JF_SPANs:ta:j-1_SI-dM": true, + "QS-Proposed-JF_SPANs:ta:j-1_SI-body": true, + "QS-Proposed-JF_SPANs:ta:j-1_SI-div": true, + "QS-Proposed-JF_SPAN.jf-1-SI-dM": true, + "QS-Proposed-JF_SPAN.jf-1-SI-body": true, + "QS-Proposed-JF_SPAN.jf-1-SI-div": true, + "QS-Proposed-JF_MYJF-1-SI-dM": true, + "QS-Proposed-JF_MYJF-1-SI-body": true, + "QS-Proposed-JF_MYJF-1-SI-div": true, + "QS-Proposed-JL_TEXT_SI-dM": true, + "QS-Proposed-JL_TEXT_SI-body": true, + "QS-Proposed-JL_TEXT_SI-div": true, + "QS-Proposed-JL_DIVa:l-1_SI-dM": true, + "QS-Proposed-JL_DIVa:l-1_SI-body": true, + "QS-Proposed-JL_DIVa:l-1_SI-div": true, + "QS-Proposed-JL_Pa:l-1_SI-dM": true, + "QS-Proposed-JL_Pa:l-1_SI-body": true, + "QS-Proposed-JL_Pa:l-1_SI-div": true, + "QS-Proposed-JL_SPANs:ta:l-1_SI-dM": true, + "QS-Proposed-JL_SPANs:ta:l-1_SI-body": true, + "QS-Proposed-JL_SPANs:ta:l-1_SI-div": true, + "QS-Proposed-JL_SPAN.jl-1-SI-dM": true, + "QS-Proposed-JL_SPAN.jl-1-SI-body": true, + "QS-Proposed-JL_SPAN.jl-1-SI-div": true, + "QS-Proposed-JL_MYJL-1-SI-dM": true, + "QS-Proposed-JL_MYJL-1-SI-body": true, + "QS-Proposed-JL_MYJL-1-SI-div": true, + "QS-Proposed-JR_TEXT_SI-dM": true, + "QS-Proposed-JR_TEXT_SI-body": true, + "QS-Proposed-JR_TEXT_SI-div": true, + "QS-Proposed-JR_DIVa:r-1_SI-dM": true, + "QS-Proposed-JR_DIVa:r-1_SI-body": true, + "QS-Proposed-JR_DIVa:r-1_SI-div": true, + "QS-Proposed-JR_Pa:r-1_SI-dM": true, + "QS-Proposed-JR_Pa:r-1_SI-body": true, + "QS-Proposed-JR_Pa:r-1_SI-div": true, + "QS-Proposed-JR_SPANs:ta:r-1_SI-dM": true, + "QS-Proposed-JR_SPANs:ta:r-1_SI-body": true, + "QS-Proposed-JR_SPANs:ta:r-1_SI-div": true, + "QS-Proposed-JR_SPAN.jr-1-SI-dM": true, + "QS-Proposed-JR_SPAN.jr-1-SI-body": true, + "QS-Proposed-JR_SPAN.jr-1-SI-div": true, + "QS-Proposed-JR_MYJR-1-SI-dM": true, + "QS-Proposed-JR_MYJR-1-SI-body": true, + "QS-Proposed-JR_MYJR-1-SI-div": true, + "QV-Proposed-B_TEXT_SI-dM": true, + "QV-Proposed-B_TEXT_SI-body": true, + "QV-Proposed-B_TEXT_SI-div": true, + "QV-Proposed-B_B-1_SI-dM": true, + "QV-Proposed-B_B-1_SI-body": true, + "QV-Proposed-B_B-1_SI-div": true, + "QV-Proposed-B_STRONG-1_SI-dM": true, + "QV-Proposed-B_STRONG-1_SI-body": true, + "QV-Proposed-B_STRONG-1_SI-div": true, + "QV-Proposed-B_SPANs:fw:b-1_SI-dM": true, + "QV-Proposed-B_SPANs:fw:b-1_SI-body": true, + "QV-Proposed-B_SPANs:fw:b-1_SI-div": true, + "QV-Proposed-B_SPANs:fw:n-1_SI-dM": true, + "QV-Proposed-B_SPANs:fw:n-1_SI-body": true, + "QV-Proposed-B_SPANs:fw:n-1_SI-div": true, + "QV-Proposed-B_Bs:fw:n-1_SI-dM": true, + "QV-Proposed-B_Bs:fw:n-1_SI-body": true, + "QV-Proposed-B_Bs:fw:n-1_SI-div": true, + "QV-Proposed-B_SPAN.b-1_SI-dM": true, + "QV-Proposed-B_SPAN.b-1_SI-body": true, + "QV-Proposed-B_SPAN.b-1_SI-div": true, + "QV-Proposed-B_MYB-1-SI-dM": true, + "QV-Proposed-B_MYB-1-SI-body": true, + "QV-Proposed-B_MYB-1-SI-div": true, + "QV-Proposed-I_TEXT_SI-dM": true, + "QV-Proposed-I_TEXT_SI-body": true, + "QV-Proposed-I_TEXT_SI-div": true, + "QV-Proposed-I_I-1_SI-dM": true, + "QV-Proposed-I_I-1_SI-body": true, + "QV-Proposed-I_I-1_SI-div": true, + "QV-Proposed-I_EM-1_SI-dM": true, + "QV-Proposed-I_EM-1_SI-body": true, + "QV-Proposed-I_EM-1_SI-div": true, + "QV-Proposed-I_SPANs:fs:i-1_SI-dM": true, + "QV-Proposed-I_SPANs:fs:i-1_SI-body": true, + "QV-Proposed-I_SPANs:fs:i-1_SI-div": true, + "QV-Proposed-I_SPANs:fs:n-1_SI-dM": true, + "QV-Proposed-I_SPANs:fs:n-1_SI-body": true, + "QV-Proposed-I_SPANs:fs:n-1_SI-div": true, + "QV-Proposed-I_I-SPANs:fs:n-1_SI-dM": true, + "QV-Proposed-I_I-SPANs:fs:n-1_SI-body": true, + "QV-Proposed-I_I-SPANs:fs:n-1_SI-div": true, + "QV-Proposed-I_SPAN.i-1_SI-dM": true, + "QV-Proposed-I_SPAN.i-1_SI-body": true, + "QV-Proposed-I_SPAN.i-1_SI-div": true, + "QV-Proposed-I_MYI-1-SI-dM": true, + "QV-Proposed-I_MYI-1-SI-body": true, + "QV-Proposed-I_MYI-1-SI-div": true, + "QV-Proposed-FB_TEXT-1_SC-dM": true, + "QV-Proposed-FB_TEXT-1_SC-body": true, + "QV-Proposed-FB_TEXT-1_SC-div": true, + "QV-Proposed-FB_H1-1_SC-dM": true, + "QV-Proposed-FB_H1-1_SC-body": true, + "QV-Proposed-FB_H1-1_SC-div": true, + "QV-Proposed-FB_PRE-1_SC-dM": true, + "QV-Proposed-FB_PRE-1_SC-body": true, + "QV-Proposed-FB_PRE-1_SC-div": true, + "QV-Proposed-FB_BQ-1_SC-dM": true, + "QV-Proposed-FB_BQ-1_SC-body": true, + "QV-Proposed-FB_BQ-1_SC-div": true, + "QV-Proposed-FB_ADDRESS-1_SC-dM": true, + "QV-Proposed-FB_ADDRESS-1_SC-body": true, + "QV-Proposed-FB_ADDRESS-1_SC-div": true, + "QV-Proposed-FB_H1-H2-1_SC-dM": true, + "QV-Proposed-FB_H1-H2-1_SC-body": true, + "QV-Proposed-FB_H1-H2-1_SC-div": true, + "QV-Proposed-FB_H1-H2-1_SL-dM": true, + "QV-Proposed-FB_H1-H2-1_SL-body": true, + "QV-Proposed-FB_H1-H2-1_SL-div": true, + "QV-Proposed-FB_H1-H2-1_SR-dM": true, + "QV-Proposed-FB_H1-H2-1_SR-body": true, + "QV-Proposed-FB_H1-H2-1_SR-div": true, + "QV-Proposed-FB_TEXT-ADDRESS-1_SL-dM": true, + "QV-Proposed-FB_TEXT-ADDRESS-1_SL-body": true, + "QV-Proposed-FB_TEXT-ADDRESS-1_SL-div": true, + "QV-Proposed-FB_TEXT-ADDRESS-1_SR-dM": true, + "QV-Proposed-FB_TEXT-ADDRESS-1_SR-body": true, + "QV-Proposed-FB_TEXT-ADDRESS-1_SR-div": true, + "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-dM": true, + "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-body": true, + "QV-Proposed-FB_H1-H2.TEXT.H2-1_SM-div": true, + "QV-Proposed-H_H1-1_SC-dM": true, + "QV-Proposed-H_H1-1_SC-body": true, + "QV-Proposed-H_H1-1_SC-div": true, + "QV-Proposed-H_H3-1_SC-dM": true, + "QV-Proposed-H_H3-1_SC-body": true, + "QV-Proposed-H_H3-1_SC-div": true, + "QV-Proposed-H_H1-H2-H3-H4-1_SC-dM": true, + "QV-Proposed-H_H1-H2-H3-H4-1_SC-body": true, + "QV-Proposed-H_H1-H2-H3-H4-1_SC-div": true, + "QV-Proposed-H_P-1_SC-dM": true, + "QV-Proposed-H_P-1_SC-body": true, + "QV-Proposed-H_P-1_SC-div": true, + "QV-Proposed-FN_FONTf:a-1_SI-dM": true, + "QV-Proposed-FN_FONTf:a-1_SI-body": true, + "QV-Proposed-FN_FONTf:a-1_SI-div": true, + "QV-Proposed-FN_SPANs:ff:a-1_SI-dM": true, + "QV-Proposed-FN_SPANs:ff:a-1_SI-body": true, + "QV-Proposed-FN_SPANs:ff:a-1_SI-div": true, + "QV-Proposed-FN_FONTf:a.s:ff:c-1_SI-dM": true, + "QV-Proposed-FN_FONTf:a.s:ff:c-1_SI-body": true, + "QV-Proposed-FN_FONTf:a.s:ff:c-1_SI-div": true, + "QV-Proposed-FN_FONTf:a-FONTf:c-1_SI-dM": true, + "QV-Proposed-FN_FONTf:a-FONTf:c-1_SI-body": true, + "QV-Proposed-FN_FONTf:a-FONTf:c-1_SI-div": true, + "QV-Proposed-FN_SPANs:ff:c-FONTf:a-1_SI-dM": true, + "QV-Proposed-FN_SPANs:ff:c-FONTf:a-1_SI-body": true, + "QV-Proposed-FN_SPANs:ff:c-FONTf:a-1_SI-div": true, + "QV-Proposed-FN_SPAN.fs18px-1_SI-dM": true, + "QV-Proposed-FN_SPAN.fs18px-1_SI-body": true, + "QV-Proposed-FN_SPAN.fs18px-1_SI-div": true, + "QV-Proposed-FN_MYCOURIER-1-SI-dM": true, + "QV-Proposed-FN_MYCOURIER-1-SI-body": true, + "QV-Proposed-FN_MYCOURIER-1-SI-div": true, + "QV-Proposed-FS_FONTsz:4-1_SI-dM": true, + "QV-Proposed-FS_FONTsz:4-1_SI-body": true, + "QV-Proposed-FS_FONTsz:4-1_SI-div": true, + "QV-Proposed-FS_FONTs:fs:l-1_SI-dM": true, + "QV-Proposed-FS_FONTs:fs:l-1_SI-body": true, + "QV-Proposed-FS_FONTs:fs:l-1_SI-div": true, + "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-dM": true, + "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-body": true, + "QV-Proposed-FS_FONT.ass.s:fs:l-1_SI-div": true, + "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-dM": true, + "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-body": true, + "QV-Proposed-FS_FONTsz:1.s:fs:xl-1_SI-div": true, + "QV-Proposed-FS_SPAN.large-1_SI-dM": true, + "QV-Proposed-FS_SPAN.large-1_SI-body": true, + "QV-Proposed-FS_SPAN.large-1_SI-div": true, + "QV-Proposed-FS_SPAN.fs18px-1_SI-dM": true, + "QV-Proposed-FS_SPAN.fs18px-1_SI-body": true, + "QV-Proposed-FS_SPAN.fs18px-1_SI-div": true, + "QV-Proposed-FA_MYLARGE-1-SI-dM": true, + "QV-Proposed-FA_MYLARGE-1-SI-body": true, + "QV-Proposed-FA_MYLARGE-1-SI-div": true, + "QV-Proposed-FA_MYFS18PX-1-SI-dM": true, + "QV-Proposed-FA_MYFS18PX-1-SI-body": true, + "QV-Proposed-FA_MYFS18PX-1-SI-div": true, + "QV-Proposed-BC_FONTs:bc:fca-1_SI-dM": true, + "QV-Proposed-BC_FONTs:bc:fca-1_SI-body": true, + "QV-Proposed-BC_FONTs:bc:fca-1_SI-div": true, + "QV-Proposed-BC_SPANs:bc:abc-1_SI-dM": true, + "QV-Proposed-BC_SPANs:bc:abc-1_SI-body": true, + "QV-Proposed-BC_SPANs:bc:abc-1_SI-div": true, + "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-dM": true, + "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-body": true, + "QV-Proposed-BC_FONTs:bc:084-SPAN-1_SI-div": true, + "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-dM": true, + "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-body": true, + "QV-Proposed-BC_SPANs:bc:cde-SPAN-1_SI-div": true, + "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-dM": true, + "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-body": true, + "QV-Proposed-BC_SPAN.ass.s:bc:rgb-1_SI-div": true, + "QV-Proposed-BC_SPAN.bcred-1_SI-dM": true, + "QV-Proposed-BC_SPAN.bcred-1_SI-body": true, + "QV-Proposed-BC_SPAN.bcred-1_SI-div": true, + "QV-Proposed-BC_MYBCRED-1-SI-dM": true, + "QV-Proposed-BC_MYBCRED-1-SI-body": true, + "QV-Proposed-BC_MYBCRED-1-SI-div": true, + "QV-Proposed-FC_FONTc:f00-1_SI-dM": true, + "QV-Proposed-FC_FONTc:f00-1_SI-body": true, + "QV-Proposed-FC_FONTc:f00-1_SI-div": true, + "QV-Proposed-FC_SPANs:c:0f0-1_SI-dM": true, + "QV-Proposed-FC_SPANs:c:0f0-1_SI-body": true, + "QV-Proposed-FC_SPANs:c:0f0-1_SI-div": true, + "QV-Proposed-FC_FONTc:333.s:c:999-1_SI-dM": true, + "QV-Proposed-FC_FONTc:333.s:c:999-1_SI-body": true, + "QV-Proposed-FC_FONTc:333.s:c:999-1_SI-div": true, + "QV-Proposed-FC_FONTc:641-SPAN-1_SI-dM": true, + "QV-Proposed-FC_FONTc:641-SPAN-1_SI-body": true, + "QV-Proposed-FC_FONTc:641-SPAN-1_SI-div": true, + "QV-Proposed-FC_SPANs:c:d95-SPAN-1_SI-dM": true, + "QV-Proposed-FC_SPANs:c:d95-SPAN-1_SI-body": true, + "QV-Proposed-FC_SPANs:c:d95-SPAN-1_SI-div": true, + "QV-Proposed-FC_SPAN.red-1_SI-dM": true, + "QV-Proposed-FC_SPAN.red-1_SI-body": true, + "QV-Proposed-FC_SPAN.red-1_SI-div": true, + "QV-Proposed-FC_MYRED-1-SI-dM": true, + "QV-Proposed-FC_MYRED-1-SI-body": true, + "QV-Proposed-FC_MYRED-1-SI-div": true, + "QV-Proposed-HC_FONTs:bc:fc0-1_SI-dM": true, + "QV-Proposed-HC_FONTs:bc:fc0-1_SI-body": true, + "QV-Proposed-HC_FONTs:bc:fc0-1_SI-div": true, + "QV-Proposed-HC_SPANs:bc:a0c-1_SI-dM": true, + "QV-Proposed-HC_SPANs:bc:a0c-1_SI-body": true, + "QV-Proposed-HC_SPANs:bc:a0c-1_SI-div": true, + "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-dM": true, + "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-body": true, + "QV-Proposed-HC_SPAN.ass.s:bc:rgb-1_SI-div": true, + "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-dM": true, + "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-body": true, + "QV-Proposed-HC_FONTs:bc:83e-SPAN-1_SI-div": true, + "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-dM": true, + "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-body": true, + "QV-Proposed-HC_SPANs:bc:b12-SPAN-1_SI-div": true, + "QV-Proposed-HC_SPAN.bcred-1_SI-dM": true, + "QV-Proposed-HC_SPAN.bcred-1_SI-body": true, + "QV-Proposed-HC_SPAN.bcred-1_SI-div": true, + "QV-Proposed-HC_MYBCRED-1-SI-dM": true, + "QV-Proposed-HC_MYBCRED-1-SI-body": true, + "QV-Proposed-HC_MYBCRED-1-SI-div": true, + }, +}; diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/current_revision b/editor/libeditor/tests/browserscope/lib/richtext2/current_revision new file mode 100644 index 0000000000..cc34bb3975 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/current_revision @@ -0,0 +1 @@ +805 diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/platformFailures.js b/editor/libeditor/tests/browserscope/lib/richtext2/platformFailures.js new file mode 100644 index 0000000000..61e1dad671 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/platformFailures.js @@ -0,0 +1,28 @@ +/** + * Platform-specific failures not included in the main currentStatus.js list. + */ +var platformFailures; +if (navigator.appVersion.includes("Android")) { + platformFailures = { + "value": {}, + "select": { + "S-Proposed-SM:m.f.w_TEXT-th_SC-1-dM": true, + "S-Proposed-SM:m.f.w_TEXT-th_SC-1-body": true, + "S-Proposed-SM:m.f.w_TEXT-th_SC-1-div": true, + "S-Proposed-SM:m.f.w_TEXT-th_SC-2-dM": true, + "S-Proposed-SM:m.f.w_TEXT-th_SC-2-body": true, + "S-Proposed-SM:m.f.w_TEXT-th_SC-2-div": true, + "S-Proposed-SM:m.b.w_TEXT-th_SC-1-dM": true, + "S-Proposed-SM:m.b.w_TEXT-th_SC-1-body": true, + "S-Proposed-SM:m.b.w_TEXT-th_SC-1-div": true, + "S-Proposed-SM:m.b.w_TEXT-th_SC-2-dM": true, + "S-Proposed-SM:m.b.w_TEXT-th_SC-2-body": true, + "S-Proposed-SM:m.b.w_TEXT-th_SC-2-div": true + } + } +} else { + platformFailures = { + "value": {}, + "select": {} + } +} diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/__init__.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/common.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/common.py new file mode 100644 index 0000000000..345f9bbb00 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/common.py @@ -0,0 +1,25 @@ +#!/usr/bin/python2.5 +# +# Copyright 2010 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the 'License') +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Common constants""" + +__author__ = 'rolandsteiner@google.com (Roland Steiner)' + +CATEGORY = 'richtext2' + +TEST_ID_PREFIX = 'RTE2' + +CLASSES = ['Finalized', 'RFC', 'Proposed'] \ No newline at end of file diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/handlers.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/handlers.py new file mode 100644 index 0000000000..2ee1e79ad3 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/handlers.py @@ -0,0 +1,107 @@ +#!/usr/bin/python2.5 +# +# Copyright 2010 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the 'License') +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Handlers for New Rich Text Tests""" + +__author__ = 'rolandsteiner@google.com (Roland Steiner)' + +from google.appengine.api import users +from google.appengine.ext import db +from google.appengine.api import memcache +from google.appengine.ext import webapp +from google.appengine.ext.webapp import template + +import django +from django import http +from django import shortcuts + +from django.template import add_to_builtins +add_to_builtins('base.custom_filters') + +# Shared stuff +from categories import all_test_sets +from base import decorators +from base import util + +# common to the RichText2 suite +from categories.richtext2 import common + +# tests +from categories.richtext2.tests.apply import APPLY_TESTS +from categories.richtext2.tests.applyCSS import APPLY_TESTS_CSS +from categories.richtext2.tests.change import CHANGE_TESTS +from categories.richtext2.tests.changeCSS import CHANGE_TESTS_CSS +from categories.richtext2.tests.delete import DELETE_TESTS +from categories.richtext2.tests.forwarddelete import FORWARDDELETE_TESTS +from categories.richtext2.tests.insert import INSERT_TESTS +from categories.richtext2.tests.selection import SELECTION_TESTS +from categories.richtext2.tests.unapply import UNAPPLY_TESTS +from categories.richtext2.tests.unapplyCSS import UNAPPLY_TESTS_CSS + +from categories.richtext2.tests.querySupported import QUERYSUPPORTED_TESTS +from categories.richtext2.tests.queryEnabled import QUERYENABLED_TESTS +from categories.richtext2.tests.queryIndeterm import QUERYINDETERM_TESTS +from categories.richtext2.tests.queryState import QUERYSTATE_TESTS, QUERYSTATE_TESTS_CSS +from categories.richtext2.tests.queryValue import QUERYVALUE_TESTS, QUERYVALUE_TESTS_CSS + + +def About(request): + """About page.""" + overview = """These tests cover browers' implementations of + contenteditable + for basic rich text formatting commands. Most browser implementations do very + well at editing the HTML which is generated by their own execCommands. But a + big problem happens when developers try to make cross-browser web + applications using contenteditable - most browsers are not able to correctly + change formatting generated by other browsers. On top of that, most browsers + allow users to to paste arbitrary HTML from other webpages into a + contenteditable region, which is even harder for browsers to properly + format. These tests check how well the execCommand, queryCommandState, + and queryCommandValue functions work with different types of HTML.""" + return util.About(request, common.CATEGORY, category_title='Rich Text', + overview=overview, show_hidden=False) + + +def RunRichText2Tests(request): + params = { + 'classes': common.CLASSES, + 'commonIDPrefix': common.TEST_ID_PREFIX, + 'strict': False, + 'suites': [ + SELECTION_TESTS, + APPLY_TESTS, + APPLY_TESTS_CSS, + CHANGE_TESTS, + CHANGE_TESTS_CSS, + UNAPPLY_TESTS, + UNAPPLY_TESTS_CSS, + DELETE_TESTS, + FORWARDDELETE_TESTS, + INSERT_TESTS, + + QUERYSUPPORTED_TESTS, + QUERYENABLED_TESTS, + QUERYINDETERM_TESTS, + QUERYSTATE_TESTS, + QUERYSTATE_TESTS_CSS, + QUERYVALUE_TESTS, + QUERYVALUE_TESTS_CSS + ] + } + return shortcuts.render_to_response('%s/templates/richtext2.html' % common.CATEGORY, params) + + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/common.css b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/common.css new file mode 100644 index 0000000000..77c6bb8726 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/common.css @@ -0,0 +1,116 @@ +.framed { + vertical-align: top; + margin: 8px; + border: 1px solid black; +} + +.legend { + padding: 12px; + background-color: #f8f8ff; +} + +.legendHdr { + font-size: large; + text-decoration: underline; +} + +table.legend { + display: inline-table; +} + +.suite-thead { + text-align: left; +} + +.lo { + background-color: #dddddd; +} +.hi { + background-color: #eeeeee; +} + +.lo .grey { + background-color: #dddddd; +} +.lo .na { + background-color: #dddddd; +} +.lo .pass { + background-color: #d4ffc0; +} +.lo .canary { + background-color: #ffcccc; +} +.lo .fail { + background-color: #ffcccc; +} +.lo .accept { + background-color: #ffffc0; +} +.lo .exception { + background-color: #f0d0f4; +} +.lo .unsupported { + background-color: #f0d0f4; +} + +.hi .grey { + background-color: #eeeeee; +} +.hi .na { + background-color: #eeeeee; +} +.hi .pass { + background-color: #e0ffdc; +} +.hi .canary { + background-color: #ffd8d8; +} +.hi .fail { + background-color: #ffd8d8; +} +.hi .accept { + background-color: #ffffd8; +} +.hi .exception { + background-color: #f4dcf8; +} +.hi .unsupported { + background-color: #f4dcf8; +} + + +.sel { + color: blue; +} + +.txt { + padding: 1px; + margin: 1px; + border: 1px solid #b0b0b0; +} + +.idLabel { + font-size: small; +} + +.fade { + color: grey; +} +.accexp { + color: #606070; +} +.comment { + color: grey; +} + +.score { + color: #666666; +} + +.fatalerror { + color: red; + font-size: large; + font-weight: bold; +} + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-body.html b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-body.html new file mode 100644 index 0000000000..a254adc03e --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-body.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-dM.html b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-dM.html new file mode 100644 index 0000000000..e16de3ab9f --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-dM.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-div.html b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-div.html new file mode 100644 index 0000000000..7dd600dbd8 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable-div.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable.css b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable.css new file mode 100644 index 0000000000..99fec49506 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/editable.css @@ -0,0 +1,66 @@ +.b, myb { + font-weight: bold; +} + +.i, myi { + font-style: italic; +} + +.s, mys { + text-decoration: line-through; +} + +.u, myu { + text-decoration: underline; +} + +.sub, mysub { + vertical-align: sub; +} + +.sup, mysup { + vertical-align: super; +} + +.jc, myjc { + text-align: center; +} + +.jf, myjf { + text-align: justify; +} + +.jl, myjl { + text-align: left; +} + +.jr, myjr { + text-align: right; +} + +.red, myred { + color: red; +} + +.bcred, mybcred { + background-color: red; +} + +.large, mylarge { + font-size: large; +} + +.fs18px, myfs18px { + font-size: 18px; +} + +.courier, mycourier { + font-family: courier; +} + +gen::before { + content: "[BEFORE]"; +} +gen::after { + content: "[AFTER]"; +} diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/canonicalize.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/canonicalize.js new file mode 100644 index 0000000000..2236d9dfc5 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/canonicalize.js @@ -0,0 +1,436 @@ +/** + * @fileoverview + * Canonicalization functions used in the RTE test suite. + * + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the 'License') + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @version 0.1 + * @author rolandsteiner@google.com + */ + +/** + * Canonicalize HTML entities to their actual character + * + * @param str {String} the HTML string to be canonicalized + * @return {String} the canonicalized string + */ + +function canonicalizeEntities(str) { + // TODO(rolandsteiner): this function is very much not optimized, but that shouldn't + // theoretically matter too much - look into it at some point. + var match; + while (match = str.match(/&#x([0-9A-F]+);/i)) { + str = str.replace('&#x' + match[1] + ';', String.fromCharCode(parseInt(match[1], 16))); + } + while (match = str.match(/&#([0-9]+);/)) { + str = str.replace('&#' + match[1] + ';', String.fromCharCode(Number(match[1]))); + } + return str; +} + +/** + * Canonicalize the contents of the HTML 'style' attribute. + * I.e. sorts the CSS attributes alphabetically and canonicalizes the values + * CSS attributes where necessary. + * + * If this would return an empty string, return null instead to suppress the + * whole 'style' attribute. + * + * Avoid tests that contain {, } or : within CSS values! + * + * Note that this function relies on the spaces of the input string already + * having been normalized by canonicalizeSpaces! + * + * FIXME: does not canonicalize the contents of compound attributes + * (e.g., 'border'). + * + * @param str {String} contents of the 'style' attribute + * @param emitFlags {Object} flags used for this output + * @return {String/null} canonicalized string, null instead of the empty string + */ +function canonicalizeStyle(str, emitFlags) { + // Remove any enclosing curly brackets + str = str.replace(/ ?[\{\}] ?/g, ''); + + var attributes = str.split(';'); + var count = attributes.length; + var resultArr = []; + + for (var a = 0; a < count; ++a) { + // Retrieve "name: value" pair + // Note: may expectedly fail if the last pair was terminated with ';' + var avPair = attributes[a].match(/ ?([^ :]+) ?: ?(.+)/); + if (!avPair) + continue; + + var name = avPair[1]; + var value = avPair[2].replace(/ $/, ''); // Remove any trailing space. + + switch (name) { + case 'color': + case 'background-color': + case 'border-color': + if (emitFlags.canonicalizeUnits) { + resultArr.push(name + ': #' + new Color(value).toHexString()); + } else { + resultArr.push(name + ': ' + value); + } + break; + + case 'font-family': + if (emitFlags.canonicalizeUnits) { + resultArr.push(name + ': ' + new FontName(value).toString()); + } else { + resultArr.push(name + ': ' + value); + } + break; + + case 'font-size': + if (emitFlags.canonicalizeUnits) { + resultArr.push(name + ': ' + new FontSize(value).toString()); + } else { + resultArr.push(name + ': ' + value); + } + break; + + default: + resultArr.push(name + ': ' + value); + } + } + + // Sort by name, assuming no duplicate CSS attribute names. + resultArr.sort(); + + return resultArr.join('; ') || null; +} + +/** + * Canonicalize a single attribute value. + * + * Note that this function relies on the spaces of the input string already + * having been normalized by canonicalizeSpaces! + * + * @param elemName {String} the name of the element + * @param attrName {String} the name of the attribute + * @param attrValue {String} the value of the attribute + * @param emitFlags {Object} flags used for this output + * @return {String/null} the canonicalized value, or null if the attribute should be skipped. + */ +function canonicalizeSingleAttribute(elemName, attrName, attrValue, emitFlags) { + // We emit attributes as name="value", so change any contained apostrophes + // to quote marks. + attrValue = attrValue.replace(/\x22/, '\x27'); + + switch (attrName) { + case 'class': + return emitFlags.emitClass ? attrValue : null; + + case 'id': + if (!emitFlags.emitID) { + return null; + } + if (attrValue && attrValue.substr(0, 7) == 'editor-') { + return null; + } + return attrValue; + + // Remove empty style attributes, canonicalize the contents otherwise, + // provided the test cares for styles. + case 'style': + return (emitFlags.emitStyle && attrValue) + ? canonicalizeStyle(attrValue, emitFlags) + : null; + + // Never output onload handlers as they are set by the test environment. + case 'onload': + return null; + + // Canonicalize colors. + case 'bgcolor': + case 'color': + if (!attrValue) { + return null; + } + return emitFlags.canonicalizeUnits ? new Color(attrValue).toString() : attrValue; + + // Canonicalize font names. + case 'face': + return emitFlags.canonicalizeUnits ? new FontName(attrValue).toString() : attrValue; + + // Canonicalize font sizes (leave other 'size' attributes as-is). + case 'size': + if (!attrValue) { + return null; + } + switch (elemName) { + case 'basefont': + case 'font': + return emitFlags.canonicalizeUnits ? new FontSize(attrValue).toString() : attrValue; + } + return attrValue; + + // Remove spans with value 1. Retain spans with other values, even if + // empty or with a value 0, since those indicate a flawed implementation. + case 'colspan': + case 'rowspan': + case 'span': + return (attrValue == '1' || attrValue === '') ? null : attrValue; + + // Boolean attributes: presence equals true. If present, the value must be + // the empty string or the attribute's canonical name. + // (http://www.whatwg.org/specs/web-apps/current-work/#boolean-attributes) + // Below we only normalize empty string to the canonical name for + // comparison purposes. All other values are not touched and will therefore + // in all likelihood result in a failed test (even if they may be accepted + // by the UA). + case 'async': + case 'autofocus': + case 'checked': + case 'compact': + case 'declare': + case 'defer': + case 'disabled': + case 'formnovalidate': + case 'frameborder': + case 'ismap': + case 'loop': + case 'multiple': + case 'nohref': + case 'nosize': + case 'noshade': + case 'novalidate': + case 'nowrap': + case 'open': + case 'readonly': + case 'required': + case 'reversed': + case 'seamless': + case 'selected': + return attrValue ? attrValue : attrName; + + default: + return attrValue; + } +} + +/** + * Canonicalize the contents of an element tag. + * + * I.e. sorts the attributes alphabetically and canonicalizes their + * values where necessary. Also removes attributes we're not interested in. + * + * Note that this function relies on the spaces of the input string already + * having been normalized by canonicalizeSpaces! + * + * @param str {String} the contens of the element tag, excluding < and >. + * @param emitFlags {Object} flags used for this output + * @return {String} the canonicalized contents. + */ +function canonicalizeElementTag(str, emitFlags) { + // FIXME: lowercase only if emitFlags.lowercase is set + str = str.toLowerCase(); + + var pos = str.search(' '); + + // element name only + if (pos == -1) { + return str; + } + + var elemName = str.substr(0, pos); + str = str.substr(pos + 1); + + // Even if emitFlags.emitAttrs is not set, we must iterate over the + // attributes to catch the special selection attribute and/or selection + // markers. :( + + // Iterate over attributes, add them to an array, canonicalize their + // contents, and finally output the (remaining) attributes in sorted order. + // Note: We can't do a simple split on space here, because the value of, + // e.g., 'style' attributes may also contain spaces. + var attrs = []; + var selStartInTag = false; + var selEndInTag = false; + + while (str) { + var attrName; + var attrValue = ''; + + pos = str.search(/[ =]/); + if (pos >= 0) { + attrName = str.substr(0, pos); + if (str.charAt(pos) == ' ') { + ++pos; + } + if (str.charAt(pos) == '=') { + ++pos; + if (str.charAt(pos) == ' ') { + ++pos; + } + str = str.substr(pos); + switch (str.charAt(0)) { + case '"': + case "'": + pos = str.indexOf(str.charAt(0), 1); + pos = (pos < 0) ? str.length : pos; + attrValue = str.substring(1, pos); + ++pos; + break; + + default: + pos = str.indexOf(' ', 0); + pos = (pos < 0) ? str.length : pos; + attrValue = (pos == -1) ? str : str.substr(0, pos); + break; + } + attrValue = attrValue.replace(/^ /, ''); + attrValue = attrValue.replace(/ $/, ''); + } + } else { + attrName = str; + } + str = (pos == -1 || pos >= str.length) ? '' : str.substr(pos + 1); + + // Remove special selection attributes. + switch (attrName) { + case ATTRNAME_SEL_START: + selStartInTag = true; + continue; + + case ATTRNAME_SEL_END: + selEndInTag = true; + continue; + } + + switch (attrName) { + case '': + case 'onload': + case 'xmlns': + break; + + default: + if (!emitFlags.emitAttrs) { + break; + } + // >>> fall through >>> + + case 'contenteditable': + attrValue = canonicalizeEntities(attrValue); + attrValue = canonicalizeSingleAttribute(elemName, attrName, attrValue, emitFlags); + if (attrValue !== null) { + attrs.push(attrName + '="' + attrValue + '"'); + } + } + } + + var result = elemName; + + // Sort alphabetically (on full string rather than just attribute value for + // simplicity. Also, attribute names will differ when encountering the '='). + if (attrs.length > 0) { + attrs.sort(); + result += ' ' + attrs.join(' '); + } + + // Add intra-tag selection marker(s) or attribute(s), if any, at the end. + if (selStartInTag && selEndInTag) { + result += ' |'; + } else if (selStartInTag) { + result += ' {'; + } else if (selEndInTag) { + result += ' }'; + } + + return result; +} + +/** + * Canonicalize elements and attributes to facilitate comparison to the + * expectation string: sort attributes, canonicalize values and remove chaff. + * + * Note that this function relies on the spaces of the input string already + * having been normalized by canonicalizeSpaces! + * + * @param str {String} the HTML string to be canonicalized + * @param emitFlags {Object} flags used for this output + * @return {String} the canonicalized string + */ +function canonicalizeElementsAndAttributes(str, emitFlags) { + var tagStart = str.indexOf('<'); + var tagEnd = 0; + var result = ''; + + while (tagStart >= 0) { + ++tagStart; + if (str.charAt(tagStart) == '/') { + ++tagStart; + } + result = result + canonicalizeEntities(str.substring(tagEnd, tagStart)); + tagEnd = str.indexOf('>', tagStart); + if (tagEnd < 0) { + tagEnd = str.length - 1; + } + if (str.charAt(tagEnd - 1) == '/') { + --tagEnd; + } + var elemStr = str.substring(tagStart, tagEnd); + elemStr = canonicalizeElementTag(elemStr, emitFlags); + result = result + elemStr; + tagStart = str.indexOf('<', tagEnd); + } + return result + canonicalizeEntities(str.substring(tagEnd)); +} + +/** + * Canonicalize an innerHTML string to uniform single whitespaces. + * + * FIXME: running this prevents testing for pre-formatted content + * and the CSS 'white-space' attribute. + * + * @param str {String} the HTML string to be canonicalized + * @return {String} the canonicalized string + */ +function canonicalizeSpaces(str) { + // Collapse sequential whitespace. + str = str.replace(/\s+/g, ' '); + + // Remove spaces immediately inside angle brackets <, >, . + // While doing this also canonicalize <.../> to <...>. + str = str.replace(/\< ?/g, '<'); + str = str.replace(/\<\/ ?/g, '/g, '>'); + + return str; +} + +/** + * Canonicalize an innerHTML string to uniform single whitespaces. + * Also remove comments to retain only embedded selection markers, and + * remove
                  and if present. + * + * FIXME: running this prevents testing for pre-formatted content + * and the CSS 'white-space' attribute. + * + * @param str {String} the HTML string to be canonicalized + * @return {String} the canonicalized string + */ +function initialCanonicalizationOf(str) { + str = canonicalizeSpaces(str); + str = str.replace(/ ? ?/g, ''); + str = str.replace(/<\/[bh]r>/g, ''); + + return str; +} diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/compare.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/compare.js new file mode 100644 index 0000000000..be059cfc86 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/compare.js @@ -0,0 +1,489 @@ +/** + * @fileoverview + * Comparison functions used in the RTE test suite. + * + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the 'License') + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @version 0.1 + * @author rolandsteiner@google.com + */ + +/** + * constants used only in the compare functions. + */ +var RESULT_DIFF = 0; // actual result doesn't match expectation +var RESULT_SEL = 1; // actual result matches expectation in HTML only +var RESULT_EQUAL = 2; // actual result matches expectation in both HTML and selection + +/** + * Gets the test expectations as an array from the passed-in field. + * + * @param {Array|String} the test expectation(s) as string or array. + * @return {Array} test expectations as an array. + */ +function getExpectationArray(expected) { + if (expected === undefined) { + return []; + } + if (expected === null) { + return [null]; + } + switch (typeof expected) { + case 'string': + case 'boolean': + case 'number': + return [expected]; + } + // Assume it's already an array. + return expected; +} + +/** + * Compare a test result to a single expectation string. + * + * FIXME: add support for optional elements/attributes. + * + * @param expected {String} the already canonicalized (with the exception of selection marks) expectation string + * @param actual {String} the already canonicalized (with the exception of selection marks) actual result + * @return {Integer} one of the RESULT_... return values + * @see variables.js for return values + */ +function compareHTMLToSingleExpectation(expected, actual) { + // If the test checks the selection, then the actual string must match the + // expectation exactly. + if (expected == actual) { + return RESULT_EQUAL; + } + + // Remove selection markers and see if strings match then. + expected = expected.replace(/ [{}\|]>/g, '>'); // intra-tag + expected = expected.replace(/[\[\]\^{}\|]/g, ''); // outside tag + actual = actual.replace(/ [{}\|]>/g, '>'); // intra-tag + actual = actual.replace(/[\[\]\^{}\|]/g, ''); // outside tag + + return (expected == actual) ? RESULT_SEL : RESULT_DIFF; +} + +/** + * Compare the current HTMLtest result to the expectation string(s). + * + * @param actual {String/Boolean} actual value + * @param expected {String/Array} expectation(s) + * @param emitFlags {Object} flags to use for canonicalization + * @return {Integer} one of the RESULT_... return values + * @see variables.js for return values + */ +function compareHTMLToExpectation(actual, expected, emitFlags) { + // Find the most favorable result among the possible expectation strings. + var expectedArr = getExpectationArray(expected); + var count = expectedArr ? expectedArr.length : 0; + var best = RESULT_DIFF; + + for (var idx = 0; idx < count && best < RESULT_EQUAL; ++idx) { + var expected = expectedArr[idx]; + expected = canonicalizeSpaces(expected); + expected = canonicalizeElementsAndAttributes(expected, emitFlags); + + var singleResult = compareHTMLToSingleExpectation(expected, actual); + + best = Math.max(best, singleResult); + } + return best; +} + +/** + * Compare the current HTMLtest result to expected and acceptable results + * + * @param expected {String/Array} expected result(s) + * @param accepted {String/Array} accepted result(s) + * @param actual {String} actual result + * @param emitFlags {Object} how to canonicalize the HTML strings + * @param result {Object} [out] object recieving the result of the comparison. + */ +function compareHTMLTestResultTo(expected, accepted, actual, emitFlags, result) { + actual = actual.replace(/[\x60\xb4]/g, ''); + actual = canonicalizeElementsAndAttributes(actual, emitFlags); + + var bestExpected = compareHTMLToExpectation(actual, expected, emitFlags); + + if (bestExpected == RESULT_EQUAL) { + // Shortcut - it doesn't get any better + result.valresult = VALRESULT_EQUAL; + result.selresult = SELRESULT_EQUAL; + return; + } + + var bestAccepted = compareHTMLToExpectation(actual, accepted, emitFlags); + + switch (bestExpected) { + case RESULT_SEL: + switch (bestAccepted) { + case RESULT_EQUAL: + // The HTML was equal to the/an expected HTML result as well + // (just not the selection there), therefore the difference + // between expected and accepted can only lie in the selection. + result.valresult = VALRESULT_EQUAL; + result.selresult = SELRESULT_ACCEPT; + return; + + case RESULT_SEL: + case RESULT_DIFF: + // The acceptable expectations did not yield a better result + // -> stay with the original (i.e., comparison to 'expected') result. + result.valresult = VALRESULT_EQUAL; + result.selresult = SELRESULT_DIFF; + return; + } + break; + + case RESULT_DIFF: + switch (bestAccepted) { + case RESULT_EQUAL: + result.valresult = VALRESULT_ACCEPT; + result.selresult = SELRESULT_EQUAL; + return; + + case RESULT_SEL: + result.valresult = VALRESULT_ACCEPT; + result.selresult = SELRESULT_DIFF; + return; + + case RESULT_DIFF: + result.valresult = VALRESULT_DIFF; + result.selresult = SELRESULT_NA; + return; + } + break; + } + + throw INTERNAL_ERR + HTML_COMPARISON; +} + +/** + * Verify that the canaries are unviolated. + * + * @param container {Object} the test container descriptor as object reference + * @param result {Object} object reference that contains the result data + * @return {Boolean} whether the canaries' HTML is OK (selection flagged, but not fatal) + */ +function verifyCanaries(container, result) { + if (!container.canary) { + return true; + } + + var str = canonicalizeElementsAndAttributes(result.bodyInnerHTML, emitFlagsForCanary); + + if (str.length < 2 * container.canary.length) { + result.valresult = VALRESULT_CANARY; + result.selresult = SELRESULT_NA; + result.output = result.bodyOuterHTML; + return false; + } + + var strBefore = str.substr(0, container.canary.length); + var strAfter = str.substr(str.length - container.canary.length); + + // Verify that the canary stretch doesn't contain any selection markers + if (SELECTION_MARKERS.test(strBefore) || SELECTION_MARKERS.test(strAfter)) { + str = str.replace(SELECTION_MARKERS, ''); + if (str.length < 2 * container.canary.length) { + result.valresult = VALRESULT_CANARY; + result.selresult = SELRESULT_NA; + result.output = result.bodyOuterHTML; + return false; + } + + // Selection escaped contentEditable element, but HTML may still be ok. + result.selresult = SELRESULT_CANARY; + strBefore = str.substr(0, container.canary.length); + strAfter = str.substr(str.length - container.canary.length); + } + + if (strBefore !== container.canary || strAfter !== container.canary) { + result.valresult = VALRESULT_CANARY; + result.selresult = SELRESULT_NA; + result.output = result.bodyOuterHTML; + return false; + } + + return true; +} + +/** + * Compare the current HTMLtest result to the expectation string(s). + * Sets the global result variables. + * + * @param suite {Object} the test suite as object reference + * @param group {Object} group of tests within the suite the test belongs to + * @param test {Object} the test as object reference + * @param container {Object} the test container description + * @param result {Object} [in/out] the result description, incl. HTML strings + * @see variables.js for result values + */ +function compareHTMLTestResult(suite, group, test, container, result) { + if (!verifyCanaries(container, result)) { + return; + } + + var emitFlags = { + emitAttrs: getTestParameter(suite, group, test, PARAM_CHECK_ATTRIBUTES), + emitStyle: getTestParameter(suite, group, test, PARAM_CHECK_STYLE), + emitClass: getTestParameter(suite, group, test, PARAM_CHECK_CLASS), + emitID: getTestParameter(suite, group, test, PARAM_CHECK_ID), + lowercase: true, + canonicalizeUnits: true + }; + + // 2a.) Compare opening tag - + // decide whether to compare vs. outer or inner HTML based on this. + var openingTagEnd = result.outerHTML.indexOf('>') + 1; + var openingTag = result.outerHTML.substr(0, openingTagEnd); + + openingTag = canonicalizeElementsAndAttributes(openingTag, emitFlags); + var tagCmp = compareHTMLToExpectation(openingTag, container.tagOpen, emitFlags); + + if (tagCmp == RESULT_EQUAL) { + result.output = result.innerHTML; + compareHTMLTestResultTo( + getTestParameter(suite, group, test, PARAM_EXPECTED), + getTestParameter(suite, group, test, PARAM_ACCEPT), + result.innerHTML, + emitFlags, + result) + } else { + result.output = result.outerHTML; + compareHTMLTestResultTo( + getContainerParameter(suite, group, test, container, PARAM_EXPECTED_OUTER), + getContainerParameter(suite, group, test, container, PARAM_ACCEPT_OUTER), + result.outerHTML, + emitFlags, + result) + } +} + +/** + * Insert a selection position indicator. + * + * @param node {DOMNode} the node where to insert the selection indicator + * @param offs {Integer} the offset of the selection indicator + * @param textInd {String} the indicator to use if the node is a text node + * @param elemInd {String} the indicator to use if the node is an element node + */ +function insertSelectionIndicator(node, offs, textInd, elemInd) { + switch (node.nodeType) { + case DOM_NODE_TYPE_TEXT: + // Insert selection marker for text node into text content. + var text = node.data; + node.data = text.substring(0, offs) + textInd + text.substring(offs); + break; + + case DOM_NODE_TYPE_ELEMENT: + var child = node.firstChild; + try { + // node has other children: insert marker as comment node + var comment = document.createComment(elemInd); + while (child && offs) { + --offs; + child = child.nextSibling; + } + if (child) { + node.insertBefore(comment, child); + } else { + node.appendChild(comment); + } + } catch (ex) { + // can't append child comment -> insert as special attribute(s) + switch (elemInd) { + case '|': + node.setAttribute(ATTRNAME_SEL_START, '1'); + node.setAttribute(ATTRNAME_SEL_END, '1'); + break; + + case '{': + node.setAttribute(ATTRNAME_SEL_START, '1'); + break; + + case '}': + node.setAttribute(ATTRNAME_SEL_END, '1'); + break; + } + } + break; + } +} + +/** + * Adds quotes around all text nodes to show cases with non-normalized + * text nodes. Those are not a bug, but may still be usefil in helping to + * debug erroneous cases. + * + * @param node {DOMNode} root node from which to descend + */ +function encloseTextNodesWithQuotes(node) { + switch (node.nodeType) { + case DOM_NODE_TYPE_ELEMENT: + for (var i = 0; i < node.childNodes.length; ++i) { + encloseTextNodesWithQuotes(node.childNodes[i]); + } + break; + + case DOM_NODE_TYPE_TEXT: + node.data = '\x60' + node.data + '\xb4'; + break; + } +} + +/** + * Retrieve the result of a test run and do some preliminary canonicalization. + * + * @param container {Object} the container where to retrieve the result from as object reference + * @param result {Object} object reference that contains the result data + * @return {String} a preliminarily canonicalized innerHTML with selection markers + */ +function prepareHTMLTestResult(container, result) { + // Start with empty strings in case any of the below throws. + result.innerHTML = ''; + result.outerHTML = ''; + + // 1.) insert selection markers + var selRange = createFromWindow(container.win); + if (selRange) { + // save values, since range object gets auto-modified + var node1 = selRange.getAnchorNode(); + var offs1 = selRange.getAnchorOffset(); + var node2 = selRange.getFocusNode(); + var offs2 = selRange.getFocusOffset(); + + // add markers + if (node1 && node1 == node2 && offs1 == offs2) { + // collapsed selection + insertSelectionIndicator(node1, offs1, '^', '|'); + } else { + // Start point and end point are different + if (node1) { + insertSelectionIndicator(node1, offs1, '[', '{'); + } + + if (node2) { + if (node1 == node2 && offs1 < offs2) { + // Anchor indicator was inserted under the same node, so we need + // to shift the offset by 1 + ++offs2; + } + insertSelectionIndicator(node2, offs2, ']', '}'); + } + } + } + + // 2.) insert markers for text node boundaries; + encloseTextNodesWithQuotes(container.editor); + + // 3.) retrieve inner and outer HTML + result.innerHTML = initialCanonicalizationOf(container.editor.innerHTML); + result.bodyInnerHTML = initialCanonicalizationOf(container.body.innerHTML); + if (goog.userAgent.IE) { + result.outerHTML = initialCanonicalizationOf(container.editor.outerHTML); + result.bodyOuterHTML = initialCanonicalizationOf(container.body.outerHTML); + result.outerHTML = result.outerHTML.replace(/^\s+/, ''); + result.outerHTML = result.outerHTML.replace(/\s+$/, ''); + result.bodyOuterHTML = result.bodyOuterHTML.replace(/^\s+/, ''); + result.bodyOuterHTML = result.bodyOuterHTML.replace(/\s+$/, ''); + } else { + result.outerHTML = initialCanonicalizationOf(new XMLSerializer().serializeToString(container.editor)); + result.bodyOuterHTML = initialCanonicalizationOf(new XMLSerializer().serializeToString(container.body)); + } +} + +/** + * Compare a text test result to the expectation string(s). + * + * @param suite {Object} the test suite as object reference + * @param group {Object} group of tests within the suite the test belongs to + * @param test {Object} the test as object reference + * @param actual {String/Boolean} actual value + * @param expected {String/Array} expectation(s) + * @return {Boolean} whether we found a match + */ +function compareTextTestResultWith(suite, group, test, actual, expected) { + var expectedArr = getExpectationArray(expected); + // Find the most favorable result among the possible expectation strings. + var count = expectedArr.length; + + // If the value matches the expectation exactly, then we're fine. + for (var idx = 0; idx < count; ++idx) { + if (actual === expectedArr[idx]) + return true; + } + + // Otherwise see if we should canonicalize specific value types. + // + // We only need to look at font name, color and size units if the originating + // test was both a) queryCommandValue and b) querying a font name/color/size + // specific criterion. + // + // TODO(rolandsteiner): This is ugly! Refactor! + switch (getTestParameter(suite, group, test, PARAM_QUERYCOMMANDVALUE)) { + case 'backcolor': + case 'forecolor': + case 'hilitecolor': + for (var idx = 0; idx < count; ++idx) { + if (new Color(actual).compare(new Color(expectedArr[idx]))) + return true; + } + return false; + + case 'fontname': + for (var idx = 0; idx < count; ++idx) { + if (new FontName(actual).compare(new FontName(expectedArr[idx]))) + return true; + } + return false; + + case 'fontsize': + for (var idx = 0; idx < count; ++idx) { + if (new FontSize(actual).compare(new FontSize(expectedArr[idx]))) + return true; + } + return false; + } + + return false; +} + +/** + * Compare the passed-in text test result to the expectation string(s). + * Sets the global result variables. + * + * @param suite {Object} the test suite as object reference + * @param group {Object} group of tests within the suite the test belongs to + * @param test {Object} the test as object reference + * @param actual {String/Boolean} actual value + * @return {Integer} a RESUTLHTML... result value + * @see variables.js for result values + */ +function compareTextTestResult(suite, group, test, result) { + var expected = getTestParameter(suite, group, test, PARAM_EXPECTED); + if (compareTextTestResultWith(suite, group, test, result.output, expected)) { + result.valresult = VALRESULT_EQUAL; + return; + } + var accepted = getTestParameter(suite, group, test, PARAM_ACCEPT); + if (accepted && compareTextTestResultWith(suite, group, test, result.output, accepted)) { + result.valresult = VALRESULT_ACCEPT; + return; + } + result.valresult = VALRESULT_DIFF; +} + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/output.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/output.js new file mode 100644 index 0000000000..897efa0112 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/output.js @@ -0,0 +1,456 @@ +/** + * @fileoverview + * Functions used to format the test result output. + * + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the 'License') + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @version 0.1 + * @author rolandsteiner@google.com + */ + +/** + * Writes a fatal error to the output (replaces alert box) + * + * @param text {String} text to output + */ +function writeFatalError(text) { + var errorsStart = document.getElementById('errors'); + var divider = document.getElementById('divider'); + if (!errorsStart) { + errorsStart = document.createElement('hr'); + errorsStart.id = 'errors'; + divider.parentNode.insertBefore(errorsStart, divider); + } + var error = document.createElement('div'); + error.className = 'fatalerror'; + error.innerHTML = 'FATAL ERROR: ' + escapeOutput(text); + errorsStart.parentNode.insertBefore(error, divider); +} + +/** + * Generates a unique ID for a given single test out of the suite ID and + * test ID. + * + * @param suiteID {string} ID string of the suite + * @param testID {string} ID string of the individual tests + * @return {string} globally unique ID + */ +function generateOutputID(suiteID, testID) { + return commonIDPrefix + '-' + suiteID + '_' + testID; +} + +/** + * Function to highlight the selection markers + * + * @param str {String} a HTML string containing selection markers + * @return {String} the HTML string with highlighting tags around the markers + */ +function highlightSelectionMarkers(str) { + str = str.replace(/\[/g, '['); + str = str.replace(/\]/g, ']'); + str = str.replace(/\^/g, '^'); + str = str.replace(/{/g, '{'); + str = str.replace(/}/g, '}'); + str = str.replace(/\|/g, '|'); + return str; +} + +/** + * Function to highlight the selection markers + * + * @param str {String} a HTML string containing selection markers + * @return {String} the HTML string with highlighting tags around the markers + */ +function highlightSelectionMarkersAndTextNodes(str) { + str = highlightSelectionMarkers(str); + str = str.replace(/\x60/g, ''); + str = str.replace(/\xb4/g, ''); + return str; +} + +/** + * Function to format output according to type + * + * @param value {String/Boolean} string or value to format + * @return {String} HTML-formatted string + */ +function formatValueOrString(value) { + if (value === undefined) + return 'undefined'; + if (value === null) + return 'null'; + + switch (typeof value) { + case 'boolean': + return '' + value.toString() + ''; + + case 'number': + return value.toString(); + + case 'string': + return "'" + escapeOutput(value) + "'"; + + default: + return '(' + escapeOutput(value.toString()) + ')'; + } +} + +/** + * Function to highlight text nodes + * + * @param suite {Object} the suite the test belongs to + * @param group {Object} the group within the suite the test belongs to + * @param test {Object} the test description as object reference + * @param actual {String} a HTML string containing text nodes with markers + * @return {String} string with highlighting tags around the text node parts + */ +function formatActualResult(suite, group, test, actual) { + if (typeof actual != 'string') + return formatValueOrString(actual); + + actual = escapeOutput(actual); + + // Fade attributes (or just style) if not actually tested for + if (!getTestParameter(suite, group, test, PARAM_CHECK_ATTRIBUTES)) { + actual = actual.replace(/([^ =]+)=\x22([^\x22]*)\x22/g, '$1="$2"'); + } else { + // NOTE: convert 'class="..."' first, before adding other ... !!! + if (!getTestParameter(suite, group, test, PARAM_CHECK_CLASS)) { + actual = actual.replace(/class=\x22([^\x22]*)\x22/g, 'class="$1"'); + } + if (!getTestParameter(suite, group, test, PARAM_CHECK_STYLE)) { + actual = actual.replace(/style=\x22([^\x22]*)\x22/g, 'style="$1"'); + } + if (!getTestParameter(suite, group, test, PARAM_CHECK_ID)) { + actual = actual.replace(/id=\x22([^\x22]*)\x22/g, 'id="$1"'); + } else { + // fade out contenteditable host element's 'editor-' ID. + actual = actual.replace(/id=\x22editor-([^\x22]*)\x22/g, 'id="editor-$1"'); + } + // grey out 'xmlns' + actual = actual.replace(/xmlns=\x22([^\x22]*)\x22/g, 'xmlns="$1"'); + // remove 'onload' + actual = actual.replace(/onload=\x22[^\x22]*\x22 ?/g, ''); + } + // Highlight selection markers and text nodes. + actual = highlightSelectionMarkersAndTextNodes(actual); + + return actual; +} + +/** + * Escape text content for use with .innerHTML. + * + * @param str {String} HTML text to displayed + * @return {String} the escaped HTML + */ +function escapeOutput(str) { + return str ? str.replace(/\/g, '>') : ''; +} + +/** + * Fills in a single output table cell + * + * @param id {String} ID of the table cell + * @param val {String} inner HTML to set + * @param ttl {String, optional} value of the 'title' attribute + * @param cls {String, optional} class name for the cell + */ +function setTD(id, val, ttl, cls) { + var td = document.getElementById(id); + if (td) { + td.innerHTML = val; + if (ttl) { + td.title = ttl; + } + if (cls) { + td.className = cls; + } + } +} + +/** + * Outputs the results of a single test suite + * + * @param suite {Object} test suite as object reference + * @param clsID {String} test class ID ('Proposed', 'RFC', 'Final') + * @param group {Object} the group of tests within the suite the test belongs to + * @param testIdx {Object} the test as object reference + */ +function outputTestResults(suite, clsID, group, test) { + var suiteID = suite.id; + var cls = suite[clsID]; + var trID = generateOutputID(suiteID, test.id); + var testResult = results[suiteID][clsID][test.id]; + var testValOut = VALOUTPUT[testResult.valresult]; + var testSelOut = SELOUTPUT[testResult.selresult]; + + var suiteChecksSelOnly = !suiteChecksHTMLOrText(suite); + var testUsesHTML = !!getTestParameter(suite, group, test, PARAM_EXECCOMMAND) || + !!getTestParameter(suite, group, test, PARAM_FUNCTION); + + // Set background color for test ID + var td = document.getElementById(trID + IDOUT_TESTID); + if (td) { + td.className = (suiteChecksSelOnly && testResult.selresult != SELRESULT_NA) ? testSelOut.css : testValOut.css; + } + + // Fill in "Command" and "Value" cells + var cmd; + var cmdOutput = ' '; + var valOutput = ' '; + + if (cmd = getTestParameter(suite, group, test, PARAM_EXECCOMMAND)) { + cmdOutput = escapeOutput(cmd); + var val = getTestParameter(suite, group, test, PARAM_VALUE); + if (val !== undefined) { + valOutput = formatValueOrString(val); + } + } else if (cmd = getTestParameter(suite, group, test, PARAM_FUNCTION)) { + cmdOutput = '' + escapeOutput(cmd) + ''; + } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDSUPPORTED)) { + cmdOutput = 'queryCommandSupported'; + valOutput = escapeOutput(cmd); + } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDENABLED)) { + cmdOutput = 'queryCommandEnabled'; + valOutput = escapeOutput(cmd); + } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDINDETERM)) { + cmdOutput = 'queryCommandIndeterm'; + valOutput = escapeOutput(cmd); + } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDSTATE)) { + cmdOutput = 'queryCommandState'; + valOutput = escapeOutput(cmd); + } else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDVALUE)) { + cmdOutput = 'queryCommandValue'; + valOutput = escapeOutput(cmd); + } else { + cmdOutput = '(none)'; + } + setTD(trID + IDOUT_COMMAND, cmdOutput); + setTD(trID + IDOUT_VALUE, valOutput); + + // Fill in "Attribute checked?" and "Style checked?" cells + if (testUsesHTML) { + var checkAttrs = getTestParameter(suite, group, test, PARAM_CHECK_ATTRIBUTES); + var checkStyle = getTestParameter(suite, group, test, PARAM_CHECK_STYLE); + + setTD(trID + IDOUT_CHECKATTRS, + checkAttrs ? OUTSTR_YES : OUTSTR_NO, + checkAttrs ? 'attributes must match' : 'attributes are ignored'); + + if (checkAttrs && checkStyle) { + setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_YES, 'style attribute contents must match'); + } else if (checkAttrs) { + setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_NO, 'style attribute contents is ignored'); + } else { + setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_NO, 'all attributes (incl. style) are ignored'); + } + } else { + setTD(trID + IDOUT_CHECKATTRS, OUTSTR_NA, 'attributes not applicable'); + setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_NA, 'style not applicable'); + } + + // Fill in test pad specification cell (initial HTML + selection markers) + setTD(trID + IDOUT_PAD, highlightSelectionMarkers(escapeOutput(getTestParameter(suite, group, test, PARAM_PAD)))); + + // Fill in expected result(s) cell + var expectedOutput = ''; + var expectedArr = getExpectationArray(getTestParameter(suite, group, test, PARAM_EXPECTED)); + for (var idx = 0; idx < expectedArr.length; ++idx) { + if (expectedOutput) { + expectedOutput += '\xA0\xA0\xA0or
                  '; + } + expectedOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(expectedArr[idx])) + : formatValueOrString(expectedArr[idx]); + } + var acceptedArr = getExpectationArray(getTestParameter(suite, group, test, PARAM_ACCEPT)); + for (var idx = 0; idx < acceptedArr.length; ++idx) { + expectedOutput += '\xA0\xA0\xA0or
                  '; + expectedOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(acceptedArr[idx])) + : formatValueOrString(acceptedArr[idx]); + expectedOutput += ''; + } + // TODO(rolandsteiner): THIS IS UGLY, relying on 'div' container being index 2, + // AND not allowing other containers to have 'outer' results - change!!! + var outerOutput = ''; + expectedArr = getExpectationArray(getContainerParameter(suite, group, test, containers[2], PARAM_EXPECTED_OUTER)); + for (var idx = 0; idx < expectedArr.length; ++idx) { + if (outerOutput) { + outerOutput += '\xA0\xA0\xA0or
                  '; + } + outerOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(expectedArr[idx])) + : formatValueOrString(expectedArr[idx]); + } + acceptedArr = getExpectationArray(getContainerParameter(suite, group, test, containers[2], PARAM_ACCEPT_OUTER)); + for (var idx = 0; idx < acceptedArr.length; ++idx) { + if (outerOutput) { + outerOutput += '\xA0\xA0\xA0or
                  '; + } + outerOutput += ''; + outerOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(acceptedArr[idx])) + : formatValueOrString(acceptedArr[idx]); + outerOutput += ''; + } + if (outerOutput) { + expectedOutput += '
                  ' + outerOutput; + } + setTD(trID + IDOUT_EXPECTED, expectedOutput); + + // Iterate over the individual container results + for (var cntIdx = 0; cntIdx < containers.length; ++cntIdx) { + var cntID = containers[cntIdx].id; + var cntTD = document.getElementById(trID + IDOUT_CONTAINER + cntID); + var cntResult = testResult[cntID]; + var cntValOut = VALOUTPUT[cntResult.valresult]; + var cntSelOut = SELOUTPUT[cntResult.selresult]; + var cssVal = cntValOut.css; + var cssSel = (!suiteChecksSelOnly || cntResult.selresult != SELRESULT_NA) ? cntSelOut.css : cssVal; + var cssCnt = cssVal; + + // Fill in result status cell ("PASS", "ACC.", "FAIL", "EXC.", etc.) + setTD(trID + IDOUT_STATUSVAL + cntID, cntValOut.output, cntValOut.title, cssVal); + + // Fill in selection status cell ("PASS", "ACC.", "FAIL", "N/A") + setTD(trID + IDOUT_STATUSSEL + cntID, cntSelOut.output, cntSelOut.title, cssSel); + + // Fill in actual result + switch (cntResult.valresult) { + case VALRESULT_SETUP_EXCEPTION: + setTD(trID + IDOUT_ACTUAL + cntID, + SETUP_EXCEPTION + '(mouseover)', + escapeOutput(cntResult.output), + cssVal); + break; + + case VALRESULT_EXECUTION_EXCEPTION: + setTD(trID + IDOUT_ACTUAL + cntID, + EXECUTION_EXCEPTION + '(mouseover)', + escapeOutput(cntResult.output.toString()), + cssVal); + break; + + case VALRESULT_VERIFICATION_EXCEPTION: + setTD(trID + IDOUT_ACTUAL + cntID, + VERIFICATION_EXCEPTION + '(mouseover)', + escapeOutput(cntResult.output.toString()), + cssVal); + break; + + case VALRESULT_UNSUPPORTED: + setTD(trID + IDOUT_ACTUAL + cntID, + escapeOutput(cntResult.output), + '', + cssVal); + break; + + case VALRESULT_CANARY: + setTD(trID + IDOUT_ACTUAL + cntID, + highlightSelectionMarkersAndTextNodes(escapeOutput(cntResult.output)), + '', + cssVal); + break; + + case VALRESULT_DIFF: + case VALRESULT_ACCEPT: + case VALRESULT_EQUAL: + if (!testUsesHTML) { + setTD(trID + IDOUT_ACTUAL + cntID, + formatValueOrString(cntResult.output), + '', + cssVal); + } else if (cntResult.selresult == SELRESULT_CANARY) { + cssCnt = suiteChecksSelOnly ? cssSel : cssVal; + setTD(trID + IDOUT_ACTUAL + cntID, + highlightSelectionMarkersAndTextNodes(escapeOutput(cntResult.output)), + '', + cssCnt); + } else { + cssCnt = suiteChecksSelOnly ? cssSel : cssVal; + setTD(trID + IDOUT_ACTUAL + cntID, + formatActualResult(suite, group, test, cntResult.output), + '', + cssCnt); + } + break; + + default: + cssCnt = 'exception'; + setTD(trID + IDOUT_ACTUAL + cntID, + INTERNAL_ERR + 'UNKNOWN RESULT VALUE', + '', + cssCnt); + } + + if (cntTD) { + cntTD.className = cssCnt; + } + } +} + +/** + * Outputs the results of a single test suite + * + * @param {Object} suite as object reference + */ +function outputTestSuiteResults(suite) { + var suiteID = suite.id; + var span; + + span = document.getElementById(suiteID + '-score'); + if (span) { + span.innerHTML = results[suiteID].valscore + '/' + results[suiteID].count; + } + span = document.getElementById(suiteID + '-selscore'); + if (span) { + span.innerHTML = results[suiteID].selscore + '/' + results[suiteID].count; + } + span = document.getElementById(suiteID + '-time'); + if (span) { + span.innerHTML = results[suiteID].time; + } + span = document.getElementById(suiteID + '-progress'); + if (span) { + span.style.color = 'green'; + } + + for (var clsIdx = 0; clsIdx < testClassCount; ++clsIdx) { + var clsID = testClassIDs[clsIdx]; + var cls = suite[clsID]; + if (!cls) + continue; + + span = document.getElementById(suiteID + '-' + clsID + '-score'); + if (span) { + span.innerHTML = results[suiteID][clsID].valscore + '/' + results[suiteID][clsID].count; + } + span = document.getElementById(suiteID + '-' + clsID + '-selscore'); + if (span) { + span.innerHTML = results[suiteID][clsID].selscore + '/' + results[suiteID][clsID].count; + } + + var groupCount = cls.length; + + for (var groupIdx = 0; groupIdx < groupCount; ++groupIdx) { + var group = cls[groupIdx]; + var testCount = group.tests.length; + + for (var testIdx = 0; testIdx < testCount; ++testIdx) { + var test = group.tests[testIdx]; + + outputTestResults(suite, clsID, group, test); + } + } + } +} diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/pad.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/pad.js new file mode 100644 index 0000000000..282f0d907d --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/pad.js @@ -0,0 +1,269 @@ +/** + * @fileoverview + * Functions used to handle test and expectation strings. + * + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the 'License') + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @version 0.1 + * @author rolandsteiner@google.com + */ + +/** + * Normalize text selection indicators and convert inter-element selection + * indicators to comments. + * + * Note that this function relies on the spaces of the input string already + * having been normalized by canonicalizeSpaces! + * + * @param pad {String} HTML string that includes selection marker characters + * @return {String} the HTML string with the selection markers converted + */ +function convertSelectionIndicators(pad) { + // Sanity check: Markers { } | only directly before or after an element, + // or just before a closing > (i.e., not within a text node). + // Note that intra-tag selection markers have already been converted to the + // special selection attribute(s) above. + if (/[^>][{}\|][^<>]/.test(pad) || + /^[{}\|][^<]/.test(pad) || + /[^>][{}\|]$/.test(pad) || + /^[{}\|]*$/.test(pad)) { + throw SETUP_BAD_SELECTION_SPEC; + } + + // Convert intra-tag selection markers to special attributes. + pad = pad.replace(/\{\>/g, ATTRNAME_SEL_START + '="1">'); + pad = pad.replace(/\}\>/g, ATTRNAME_SEL_END + '="1">'); + pad = pad.replace(/\|\>/g, ATTRNAME_SEL_START + '="1" ' + + ATTRNAME_SEL_END + '="1">'); + + // Convert remaining {, }, | to comments with '[' and ']' data. + pad = pad.replace('{', ''); + pad = pad.replace('}', ''); + pad = pad.replace('|', ''); + + // Convert caret indicator ^ to empty selection indicator [] + // (this simplifies further processing). + pad = pad.replace(/\^/, '[]'); + + return pad; +} + +/** + * Derives one point of the selection from the indicators with the HTML tree: + * '[' or ']' within a text or comment node, or the special selection + * attributes within an element node. + * + * @param root {DOMNode} root node of the recursive search + * @param marker {String} which marker to look for: '[' or ']' + * @return {Object} a pair object: {node: {DOMNode}/null, offset: {Integer}} + */ +function deriveSelectionPoint(root, marker) { + switch (root.nodeType) { + case DOM_NODE_TYPE_ELEMENT: + if (root.attributes) { + // Note: getAttribute() is necessary for this to work on all browsers! + if (marker == '[' && root.getAttribute(ATTRNAME_SEL_START)) { + root.removeAttribute(ATTRNAME_SEL_START); + return {node: root, offs: 0}; + } + if (marker == ']' && root.getAttribute(ATTRNAME_SEL_END)) { + root.removeAttribute(ATTRNAME_SEL_END); + return {node: root, offs: 0}; + } + } + for (var i = 0; i < root.childNodes.length; ++i) { + var pair = deriveSelectionPoint(root.childNodes[i], marker); + if (pair.node) { + return pair; + } + } + break; + + case DOM_NODE_TYPE_TEXT: + var pos = root.data.indexOf(marker); + if (pos != -1) { + // Remove selection marker from text. + var nodeText = root.data; + root.data = nodeText.substr(0, pos) + nodeText.substr(pos + 1); + return {node: root, offs: pos }; + } + break; + + case DOM_NODE_TYPE_COMMENT: + var pos = root.data.indexOf(marker); + if (pos != -1) { + // Remove comment node from parent. + var helper = root.previousSibling; + + for (pos = 0; helper; ++pos ) { + helper = helper.previousSibling; + } + helper = root; + root = root.parentNode; + root.removeChild(helper); + return {node: root, offs: pos }; + } + break; + } + + return {node: null, offs: 0 }; +} + +/** + * Initialize the test HTML with the starting state specified in the test. + * + * The selection is specified "inline", using special characters: + * ^ a collapsed text caret selection (same as []) + * [ the selection start within a text node + * ] the selection end within a text node + * | collapsed selection between elements (same as {}) + * { selection starting with the following element + * } selection ending with the preceding element + * {, } and | can also be used within an element tag, just before the closing + * angle bracket > to specify a selection [element, 0] where the element + * doesn't otherwise have any children. Ex.:
                  foobarbaz
                  + * + * Explicit and implicit specification can also be mixed between the 2 points. + * + * A pad string must only contain at most ONE of the above that is suitable for + * that start or end point, respectively, and must contain either both or none. + * + * @param suite {Object} suite that test originates in as object reference + * @param group {Object} group of tests within the suite the test belongs to + * @param test {Object} test to be run as object reference + * @param container {Object} container descriptor as object reference + */ +function initContainer(suite, group, test, container) { + var pad = getTestParameter(suite, group, test, PARAM_PAD); + pad = canonicalizeSpaces(pad); + pad = convertSelectionIndicators(pad); + + if (container.editorID) { + container.body.innerHTML = container.canary + container.tagOpen + pad + container.tagClose + container.canary; + container.editor = container.doc.getElementById(container.editorID); + } else { + container.body.innerHTML = pad; + container.editor = container.body; + } + + win = container.win; + doc = container.doc; + body = container.body; + editor = container.editor; + sel = null; + + if (!editor) { + throw SETUP_CONTAINER; + } + + if (getTestParameter(suite, group, test, PARAM_STYLE_WITH_CSS)) { + try { + container.doc.execCommand('styleWithCSS', false, true); + } catch (ex) { + // ignore exception if unsupported + } + } + + var selAnchor = deriveSelectionPoint(editor, '['); + var selFocus = deriveSelectionPoint(editor, ']'); + + // sanity check + if (!selAnchor || !selFocus) { + throw SETUP_SELECTION; + } + + if (!selAnchor.node || !selFocus.node) { + if (selAnchor.node || selFocus.node) { + // Broken test: only one selection point was specified + throw SETUP_BAD_SELECTION_SPEC; + } + sel = null; + return; + } + + if (selAnchor.node === selFocus.node) { + if (selAnchor.offs > selFocus.offs) { + // Both selection points are within the same node, the selection was + // specified inline (thus the end indicator element or character was + // removed), and the end point is before the start (reversed selection). + // Start offset that was derived is now off by 1 and needs adjustment. + --selAnchor.offs; + } + + if (selAnchor.offs === selFocus.offs) { + createCaret(selAnchor.node, selAnchor.offs).select(); + try { + sel = win.getSelection(); + } catch (ex) { + sel = undefined; + } + return; + } + } + + createFromNodes(selAnchor.node, selAnchor.offs, selFocus.node, selFocus.offs).select(); + + try { + sel = win.getSelection(); + } catch (ex) { + sel = undefined; + } +} + +/** + * Reset the editor element after a test is run. + * + * @param container {Object} container descriptor as object reference + */ +function resetContainer(container) { + // Remove errant styles and attributes that may have been set on the . + container.body.removeAttribute('style'); + container.body.removeAttribute('color'); + container.body.removeAttribute('bgcolor'); + + try { + container.doc.execCommand('styleWithCSS', false, false); + } catch (ex) { + // Ignore exception if unsupported. + } +} + +/** + * Initialize the editor document. + */ +function initEditorDocs() { + for (var c = 0; c < containers.length; ++c) { + var container = containers[c]; + + container.iframe = document.getElementById('iframe-' + container.id); + container.win = container.iframe.contentWindow; + container.doc = container.win.document; + container.body = container.doc.body; + // container.editor is set per test (changes on embedded editor elements). + + // Some browsers require a selection to go with their 'styleWithCSS'. + try { + container.win.getSelection().selectAllChildren(editor); + } catch (ex) { + // ignore exception if unsupported + } + // Default styleWithCSS to false. + try { + container.doc.execCommand('styleWithCSS', false, false); + } catch (ex) { + // ignore exception if unsupported + } + } +} diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range-bootstrap.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range-bootstrap.js new file mode 100644 index 0000000000..24aef7ae9c --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range-bootstrap.js @@ -0,0 +1,5 @@ +goog.require('goog.dom.Range'); + +window.createFromWindow = goog.dom.Range.createFromWindow; +window.createFromNodes = goog.dom.Range.createFromNodes; +window.createCaret = goog.dom.Range.createCaret; diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range.js b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range.js new file mode 100644 index 0000000000..3266761115 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/static/js/range.js @@ -0,0 +1,6184 @@ +var COMPILED = false; +var goog = goog || {}; +goog.global = this; +goog.DEBUG = true; +goog.LOCALE = "en"; +goog.evalWorksForGlobals_ = null; +goog.provide = function(name) { + if(!COMPILED) { + if(goog.getObjectByName(name) && !goog.implicitNamespaces_[name]) { + throw Error('Namespace "' + name + '" already declared.'); + } + var namespace = name; + while(namespace = namespace.substring(0, namespace.lastIndexOf("."))) { + goog.implicitNamespaces_[namespace] = true + } + } + goog.exportPath_(name) +}; +if(!COMPILED) { + goog.implicitNamespaces_ = {} +} +goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) { + var parts = name.split("."); + var cur = opt_objectToExportTo || goog.global; + if(!(parts[0] in cur) && cur.execScript) { + cur.execScript("var " + parts[0]) + } + for(var part;parts.length && (part = parts.shift());) { + if(!parts.length && goog.isDef(opt_object)) { + cur[part] = opt_object + }else { + if(cur[part]) { + cur = cur[part] + }else { + cur = cur[part] = {} + } + } + } +}; +goog.getObjectByName = function(name, opt_obj) { + var parts = name.split("."); + var cur = opt_obj || goog.global; + for(var part;part = parts.shift();) { + if(cur[part]) { + cur = cur[part] + }else { + return null + } + } + return cur +}; +goog.globalize = function(obj, opt_global) { + var global = opt_global || goog.global; + for(var x in obj) { + global[x] = obj[x] + } +}; +goog.addDependency = function(relPath, provides, requires) { + if(!COMPILED) { + var provide, require; + var path = relPath.replace(/\\/g, "/"); + var deps = goog.dependencies_; + for(var i = 0;provide = provides[i];i++) { + deps.nameToPath[provide] = path; + if(!(path in deps.pathToNames)) { + deps.pathToNames[path] = {} + } + deps.pathToNames[path][provide] = true + } + for(var j = 0;require = requires[j];j++) { + if(!(path in deps.requires)) { + deps.requires[path] = {} + } + deps.requires[path][require] = true + } + } +}; +goog.require = function(rule) { + if(!COMPILED) { + if(goog.getObjectByName(rule)) { + return + } + var path = goog.getPathFromDeps_(rule); + if(path) { + goog.included_[path] = true; + goog.writeScripts_() + }else { + var errorMessage = "goog.require could not find: " + rule; + if(goog.global.console) { + goog.global.console["error"](errorMessage) + } + throw Error(errorMessage); + } + } +}; +goog.basePath = ""; +goog.global.CLOSURE_BASE_PATH; +goog.nullFunction = function() { +}; +goog.identityFunction = function(var_args) { + return arguments[0] +}; +goog.abstractMethod = function() { + throw Error("unimplemented abstract method"); +}; +goog.addSingletonGetter = function(ctor) { + ctor.getInstance = function() { + return ctor.instance_ || (ctor.instance_ = new ctor) + } +}; +if(!COMPILED) { + goog.included_ = {}; + goog.dependencies_ = {pathToNames:{}, nameToPath:{}, requires:{}, visited:{}, written:{}}; + goog.inHtmlDocument_ = function() { + var doc = goog.global.document; + return typeof doc != "undefined" && "write" in doc + }; + goog.findBasePath_ = function() { + if(!goog.inHtmlDocument_()) { + return + } + var doc = goog.global.document; + if(goog.global.CLOSURE_BASE_PATH) { + goog.basePath = goog.global.CLOSURE_BASE_PATH; + return + } + var scripts = doc.getElementsByTagName("script"); + for(var i = scripts.length - 1;i >= 0;--i) { + var src = scripts[i].src; + var l = src.length; + if(src.substr(l - 7) == "base.js") { + goog.basePath = src.substr(0, l - 7); + return + } + } + }; + goog.writeScriptTag_ = function(src) { + if(goog.inHtmlDocument_() && !goog.dependencies_.written[src]) { + goog.dependencies_.written[src] = true; + var doc = goog.global.document; + doc.write(' + + + + + + + + + + + + + + + + {% include "richtext2/templates/output.html" %} +
                  + + + + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/__init__.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/__init__.py new file mode 100644 index 0000000000..a1f5279ad5 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/__init__.py @@ -0,0 +1,17 @@ +__all__ = [ + 'apply', + 'applyCSS', + 'change', + 'changeCSS', + 'delete', + 'forwarddelete', + 'insert', + 'queryEnabled', + 'queryIndeterm', + 'queryState', + 'querySupported', + 'queryValue', + 'selection', + 'unapply', + 'unapplyCSS' +] \ No newline at end of file diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/apply.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/apply.py new file mode 100644 index 0000000000..3eb465c84c --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/apply.py @@ -0,0 +1,364 @@ + +APPLY_TESTS = { + 'id': 'A', + 'caption': 'Apply Formatting Tests', + 'checkAttrs': True, + 'checkStyle': True, + 'styleWithCSS': False, + + 'Proposed': [ + { 'desc': '', + 'command': '', + 'tests': [ + ] + }, + + { 'desc': '[HTML5] bold', + 'command': 'bold', + 'tests': [ + { 'id': 'B_TEXT-1_SI', + 'rte1-id': 'a-bold-0', + 'desc': 'Bold selection', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] }, + + { 'id': 'B_TEXT-1_SIR', + 'desc': 'Bold reversed selection', + 'pad': 'foo]bar[baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] }, + + { 'id': 'B_I-1_SL', + 'desc': 'Bold selection, partially including italic', + 'pad': 'foo[barbaz]qozquz', + 'expected': [ 'foo[barbaz]qozquz', + 'foo[barbaz]qozquz', + 'foo[barbaz]qozquz', + 'foo[barbaz]qozquz' ] } + ] + }, + + { 'desc': '[HTML5] italic', + 'command': 'italic', + 'tests': [ + { 'id': 'I_TEXT-1_SI', + 'rte1-id': 'a-italic-0', + 'desc': 'Italicize selection', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[HTML5] underline', + 'command': 'underline', + 'tests': [ + { 'id': 'U_TEXT-1_SI', + 'rte1-id': 'a-underline-0', + 'desc': 'Underline selection', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[HTML5] strikethrough', + 'command': 'strikethrough', + 'tests': [ + { 'id': 'S_TEXT-1_SI', + 'rte1-id': 'a-strikethrough-0', + 'desc': 'Strike-through selection', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[HTML5] subscript', + 'command': 'subscript', + 'tests': [ + { 'id': 'SUB_TEXT-1_SI', + 'rte1-id': 'a-subscript-0', + 'desc': 'Change selection to subscript', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[HTML5] superscript', + 'command': 'superscript', + 'tests': [ + { 'id': 'SUP_TEXT-1_SI', + 'rte1-id': 'a-superscript-0', + 'desc': 'Change selection to superscript', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[HTML5] createlink', + 'command': 'createlink', + 'tests': [ + { 'id': 'CL:url_TEXT-1_SI', + 'rte1-id': 'a-createlink-0', + 'desc': 'create a link around the selection', + 'value': '#foo', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[HTML5] formatBlock', + 'command': 'formatblock', + 'tests': [ + { 'id': 'FB:H1_TEXT-1_SI', + 'rte1-id': 'a-formatblock-0', + 'desc': 'format the selection into a block: use

                  ', + 'value': 'h1', + 'pad': 'foo[bar]baz', + 'expected': '

                  foo[bar]baz

                  ' }, + + { 'id': 'FB:P_TEXT-1_SI', + 'desc': 'format the selection into a block: use

                  ', + 'value': 'p', + 'pad': 'foo[bar]baz', + 'expected': '

                  foo[bar]baz

                  ' }, + + { 'id': 'FB:PRE_TEXT-1_SI', + 'desc': 'format the selection into a block: use
                  ',
                  +          'value':      'pre',
                  +          'pad':        'foo[bar]baz',
                  +          'expected':   '
                  foo[bar]baz
                  ' }, + + { 'id': 'FB:ADDRESS_TEXT-1_SI', + 'desc': 'format the selection into a block: use
                  ', + 'value': 'address', + 'pad': 'foo[bar]baz', + 'expected': '
                  foo[bar]baz
                  ' }, + + { 'id': 'FB:BQ_TEXT-1_SI', + 'desc': 'format the selection into a block: use
                  ', + 'value': 'blockquote', + 'pad': 'foo[bar]baz', + 'expected': '
                  foo[bar]baz
                  ' }, + + { 'id': 'FB:BQ_BR.BR-1_SM', + 'desc': 'format a multi-line selection into a block: use
                  ', + 'command': 'formatblock', + 'value': 'blockquote', + 'pad': 'fo[o
                  bar
                  b]az', + 'expected': '
                  fo[o
                  bar
                  b]az
                  ' } + ] + }, + + + { 'desc': '[MIDAS] backcolor', + 'command': 'backcolor', + 'tests': [ + { 'id': 'BC:blue_TEXT-1_SI', + 'rte1-id': 'a-backcolor-0', + 'desc': 'Change background color (note: no non-CSS variant available)', + 'value': 'blue', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[MIDAS] forecolor', + 'command': 'forecolor', + 'tests': [ + { 'id': 'FC:blue_TEXT-1_SI', + 'rte1-id': 'a-forecolor-0', + 'desc': 'Change the text color', + 'value': 'blue', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[MIDAS] hilitecolor', + 'command': 'hilitecolor', + 'tests': [ + { 'id': 'HC:blue_TEXT-1_SI', + 'rte1-id': 'a-hilitecolor-0', + 'desc': 'Change the hilite color', + 'value': 'blue', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[MIDAS] fontname', + 'command': 'fontname', + 'tests': [ + { 'id': 'FN:a_TEXT-1_SI', + 'rte1-id': 'a-fontname-0', + 'desc': 'Change the font name', + 'value': 'arial', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[MIDAS] fontsize', + 'command': 'fontsize', + 'tests': [ + { 'id': 'FS:2_TEXT-1_SI', + 'rte1-id': 'a-fontsize-0', + 'desc': 'Change the font size to "2"', + 'value': '2', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' }, + + { 'id': 'FS:18px_TEXT-1_SI', + 'desc': 'Change the font size to "18px"', + 'value': '18px', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' }, + + { 'id': 'FS:large_TEXT-1_SI', + 'desc': 'Change the font size to "large"', + 'value': 'large', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[MIDAS] increasefontsize', + 'command': 'increasefontsize', + 'tests': [ + { 'id': 'INCFS:2_TEXT-1_SI', + 'desc': 'Decrease the font size (to small)', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[MIDAS] decreasefontsize', + 'command': 'decreasefontsize', + 'tests': [ + { 'id': 'DECFS:2_TEXT-1_SI', + 'rte1-id': 'a-decreasefontsize-0', + 'desc': 'Decrease the font size (to small)', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[MIDAS] indent (note: accept the de-facto standard indent of 40px)', + 'command': 'indent', + 'tests': [ + { 'id': 'IND_TEXT-1_SI', + 'rte1-id': 'a-indent-0', + 'desc': 'Indent the text (accept the de-facto standard of 40px indent)', + 'pad': 'foo[bar]baz', + 'checkAttrs': False, + 'expected': [ '
                  foo[bar]baz
                  ', + '
                  foo[bar]baz
                  ' ], + 'div': { + 'accOuter': '
                  foo[bar]baz
                  ' } } + ] + }, + + { 'desc': '[MIDAS] outdent (-> unapply tests)', + 'command': 'outdent', + 'tests': [ + ] + }, + + { 'desc': '[MIDAS] justifycenter', + 'command': 'justifycenter', + 'tests': [ + { 'id': 'JC_TEXT-1_SC', + 'rte1-id': 'a-justifycenter-0', + 'desc': 'justify the text centrally', + 'pad': 'foo^bar', + 'expected': [ '
                  foo^bar
                  ', + '

                  foo^bar

                  ', + '

                  foo^bar

                  ', + '
                  foo^bar
                  ', + '
                  foo^bar
                  ' ], + 'div': { + 'accOuter': [ '
                  foo^bar
                  ', + '
                  foo^bar
                  ' ] } } + ] + }, + + { 'desc': '[MIDAS] justifyfull', + 'command': 'justifyfull', + 'tests': [ + { 'id': 'JF_TEXT-1_SC', + 'rte1-id': 'a-justifyfull-0', + 'desc': 'justify the text fully', + 'pad': 'foo^bar', + 'expected': [ '

                  foo^bar

                  ', + '
                  foo^bar
                  ' ], + 'div': { + 'accOuter': '
                  foo^bar
                  ' } } + ] + }, + + { 'desc': '[MIDAS] justifyleft', + 'command': 'justifyleft', + 'tests': [ + { 'id': 'JL_TEXT-1_SC', + 'rte1-id': 'a-justifyleft-0', + 'desc': 'justify the text left', + 'pad': 'foo^bar', + 'expected': [ '

                  foo^bar

                  ', + '
                  foo^bar
                  ' ], + 'div': { + 'accOuter': '
                  foo^bar
                  ' } } + ] + }, + + { 'desc': '[MIDAS] justifyright', + 'command': 'justifyright', + 'tests': [ + { 'id': 'JR_TEXT-1_SC', + 'rte1-id': 'a-justifyright-0', + 'desc': 'justify the text right', + 'pad': 'foo^bar', + 'expected': [ '

                  foo^bar

                  ', + '
                  foo^bar
                  ' ], + 'div': { + 'accOuter': '
                  foo^bar
                  ' } } + ] + }, + + { 'desc': '[MIDAS] heading', + 'command': 'heading', + 'tests': [ + { 'id': 'H:H1_TEXT-1_SC', + 'desc': 'create a heading from the paragraph that contains the selection', + 'value': 'h1', + 'pad': 'foo[bar]baz', + 'expected': '

                  foo[bar]baz

                  ' } + ] + }, + + + { 'desc': '[Other] createbookmark', + 'command': 'createbookmark', + 'tests': [ + { 'id': 'CB:name_TEXT-1_SI', + 'rte1-id': 'a-createbookmark-0', + 'desc': 'create a bookmark (named link) around selection', + 'value': 'created', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + } + ] +} + + + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/applyCSS.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/applyCSS.py new file mode 100644 index 0000000000..94cdad83fb --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/applyCSS.py @@ -0,0 +1,244 @@ + +APPLY_TESTS_CSS = { + 'id': 'AC', + 'caption': 'Apply Formatting Tests, using styleWithCSS', + 'checkAttrs': True, + 'checkStyle': True, + 'styleWithCSS': True, + + 'Proposed': [ + { 'desc': '', + 'command': '', + 'tests': [ + ] + }, + + { 'desc': '[HTML5] bold', + 'command': 'bold', + 'tests': [ + { 'id': 'B_TEXT-1_SI', + 'rte1-id': 'a-bold-1', + 'desc': 'Bold selection', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[HTML5] italic', + 'command': 'italic', + 'tests': [ + { 'id': 'I_TEXT-1_SI', + 'rte1-id': 'a-italic-1', + 'desc': 'Italicize selection', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[HTML5] underline', + 'command': 'underline', + 'tests': [ + { 'id': 'U_TEXT-1_SI', + 'rte1-id': 'a-underline-1', + 'desc': 'Underline selection', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[HTML5] strikethrough', + 'command': 'strikethrough', + 'tests': [ + { 'id': 'S_TEXT-1_SI', + 'rte1-id': 'a-strikethrough-1', + 'desc': 'Strike-through selection', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[HTML5] subscript', + 'command': 'subscript', + 'tests': [ + { 'id': 'SUB_TEXT-1_SI', + 'rte1-id': 'a-subscript-1', + 'desc': 'Change selection to subscript', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + { 'desc': '[HTML5] superscript', + 'command': 'superscript', + 'tests': [ + { 'id': 'SUP_TEXT-1_SI', + 'rte1-id': 'a-superscript-1', + 'desc': 'Change selection to superscript', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' } + ] + }, + + + { 'desc': '[MIDAS] backcolor', + 'command': 'backcolor', + 'tests': [ + { 'id': 'BC:blue_TEXT-1_SI', + 'rte1-id': 'a-backcolor-1', + 'desc': 'Change background color', + 'value': 'blue', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[MIDAS] forecolor', + 'command': 'forecolor', + 'tests': [ + { 'id': 'FC:blue_TEXT-1_SI', + 'rte1-id': 'a-forecolor-1', + 'desc': 'Change the text color', + 'value': 'blue', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[MIDAS] hilitecolor', + 'command': 'hilitecolor', + 'tests': [ + { 'id': 'HC:blue_TEXT-1_SI', + 'rte1-id': 'a-hilitecolor-1', + 'desc': 'Change the hilite color', + 'value': 'blue', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[MIDAS] fontname', + 'command': 'fontname', + 'tests': [ + { 'id': 'FN:a_TEXT-1_SI', + 'rte1-id': 'a-fontname-1', + 'desc': 'Change the font name', + 'value': 'arial', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[MIDAS] fontsize', + 'command': 'fontsize', + 'tests': [ + { 'id': 'FS:2_TEXT-1_SI', + 'rte1-id': 'a-fontsize-1', + 'desc': 'Change the font size to "2"', + 'value': '2', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] }, + + { 'id': 'FS:18px_TEXT-1_SI', + 'desc': 'Change the font size to "18px"', + 'value': '18px', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] }, + + { 'id': 'FS:large_TEXT-1_SI', + 'desc': 'Change the font size to "large"', + 'value': 'large', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[MIDAS] indent', + 'command': 'indent', + 'tests': [ + { 'id': 'IND_TEXT-1_SI', + 'rte1-id': 'a-indent-1', + 'desc': 'Indent the text (assume "standard" 40px)', + 'pad': 'foo[bar]baz', + 'expected': [ '
                  foo[bar]baz
                  ', + '
                  foo[bar]baz
                  ', + '
                  foo[bar]baz
                  ', + '
                  foo[bar]baz
                  ' ], + 'div': { + 'accOuter': [ '
                  foo[bar]baz
                  ', + '
                  foo[bar]baz
                  ' ] } } + ] + }, + + { 'desc': '[MIDAS] outdent (-> unapply tests)', + 'command': 'outdent', + 'tests': [ + ] + }, + + { 'desc': '[MIDAS] justifycenter', + 'command': 'justifycenter', + 'tests': [ + { 'id': 'JC_TEXT-1_SC', + 'rte1-id': 'a-justifycenter-1', + 'desc': 'justify the text centrally', + 'pad': 'foo^bar', + 'expected': [ '

                  foo^bar

                  ', + '
                  foo^bar
                  ' ], + 'div': { + 'accOuter': '
                  foo^bar
                  ' } } + ] + }, + + { 'desc': '[MIDAS] justifyfull', + 'command': 'justifyfull', + 'tests': [ + { 'id': 'JF_TEXT-1_SC', + 'rte1-id': 'a-justifyfull-1', + 'desc': 'justify the text fully', + 'pad': 'foo^bar', + 'expected': [ '

                  foo^bar

                  ', + '
                  foo^bar
                  ' ], + 'div': { + 'accOuter': '
                  foo^bar
                  ' } } + ] + }, + + { 'desc': '[MIDAS] justifyleft', + 'command': 'justifyleft', + 'tests': [ + { 'id': 'JL_TEXT-1_SC', + 'rte1-id': 'a-justifyleft-1', + 'desc': 'justify the text left', + 'pad': 'foo^bar', + 'expected': [ '

                  foo^bar

                  ', + '
                  foo^bar
                  ' ], + 'div': { + 'accOuter': '
                  foo^bar
                  ' } } + ] + }, + + { 'desc': '[MIDAS] justifyright', + 'command': 'justifyright', + 'tests': [ + { 'id': 'JR_TEXT-1_SC', + 'rte1-id': 'a-justifyright-1', + 'desc': 'justify the text right', + 'pad': 'foo^bar', + 'expected': [ '

                  foo^bar

                  ', + '
                  foo^bar
                  ' ], + 'div': { + 'accOuter': '
                  foo^bar
                  ' } } + ] + } + ] +} + + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/change.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/change.py new file mode 100644 index 0000000000..6a76d3d5fd --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/change.py @@ -0,0 +1,273 @@ + +CHANGE_TESTS = { + 'id': 'C', + 'caption': 'Change Existing Format to Different Format Tests', + 'checkAttrs': True, + 'checkStyle': True, + 'styleWithCSS': False, + + 'Proposed': [ + { 'desc': '', + 'command': '', + 'tests': [ + ] + }, + + { 'desc': '[HTML5] italic', + 'command': 'italic', + 'tests': [ + { 'id': 'I_I-1_SL', + 'desc': 'Italicize partially italicized text', + 'pad': 'foo[barbaz]qoz', + 'expected': 'foo[barbaz]qoz' }, + + { 'id': 'I_B-I-1_SO', + 'desc': 'Italicize partially italicized text in bold context', + 'pad': 'foo[barbaz}', + 'expected': 'foo[barbaz]' } + ] + }, + + { 'desc': '[HTML5] underline', + 'command': 'underline', + 'tests': [ + { 'id': 'U_U-1_SO', + 'desc': 'Underline partially underlined text', + 'pad': 'foo[barbazqoz]quz', + 'expected': 'foo[barbazqoz]quz' }, + + { 'id': 'U_U-1_SL', + 'desc': 'Underline partially underlined text', + 'pad': 'foo[barbaz]qozquz', + 'expected': 'foo[barbaz]qozquz' }, + + { 'id': 'U_S-U-1_SO', + 'desc': 'Underline partially underlined text in striked context', + 'pad': 'foo[barbaz}', + 'expected': 'foo[barbaz]' } + ] + }, + + + { 'desc': '[MIDAS] backcolor', + 'command': 'backcolor', + 'tests': [ + { 'id': 'BC:842_FONTs:bc:fca-1_SW', + 'rte1-id': 'c-backcolor-0', + 'desc': 'Change background color to new color', + 'value': '#884422', + 'pad': '[foobarbaz]', + 'expected': [ '[foobarbaz]', + '[foobarbaz]' ] }, + + { 'id': 'BC:00f_SPANs:bc:f00-1_SW', + 'rte1-id': 'c-backcolor-2', + 'desc': 'Change background color to new color', + 'value': '#0000ff', + 'pad': '[foobarbaz]', + 'expected': [ '[foobarbaz]', + '[foobarbaz]' ] }, + + { 'id': 'BC:ace_FONT.ass.s:bc:rgb-1_SW', + 'rte1-id': 'c-backcolor-1', + 'desc': 'Change background color in styled span to new color', + 'value': '#aaccee', + 'pad': '[foobarbaz]', + 'expected': [ '[foobarbaz]', + '[foobarbaz]' ] } + ] + }, + + { 'desc': '[MIDAS] forecolor', + 'command': 'forecolor', + 'tests': [ + { 'id': 'FC:g_FONTc:b-1_SW', + 'rte1-id': 'c-forecolor-0', + 'desc': 'Change the text color (without CSS)', + 'value': 'green', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FC:g_SPANs:c:g-1_SW', + 'rte1-id': 'c-forecolor-1', + 'desc': 'Change the text color from a styled span (without CSS)', + 'value': 'green', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FC:g_FONTc:b.s:c:r-1_SW', + 'rte1-id': 'c-forecolor-2', + 'desc': 'Change the text color from conflicting color and style (without CSS)', + 'value': 'green', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FC:g_FONTc:b.sz:6-1_SI', + 'desc': 'Change the font color in content with a different font size and font color', + 'value': 'green', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] } + ] + }, + + { 'desc': '[MIDAS] hilitecolor', + 'command': 'hilitecolor', + 'tests': [ + { 'id': 'HC:g_FONTs:c:b-1_SW', + 'rte1-id': 'c-hilitecolor-0', + 'desc': 'Change the hilite color (without CSS)', + 'value': 'green', + 'pad': '[foobarbaz]', + 'expected': [ '[foobarbaz]', + '[foobarbaz]' ] }, + + { 'id': 'HC:g_SPANs:c:g-1_SW', + 'rte1-id': 'c-hilitecolor-2', + 'desc': 'Change the hilite color from a styled span (without CSS)', + 'value': 'green', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'HC:g_SPAN.ass.s:c:rgb-1_SW', + 'rte1-id': 'c-hilitecolor-1', + 'desc': 'Change the hilite color from a styled span (without CSS)', + 'value': 'green', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' } + ] + }, + + { 'desc': '[MIDAS] fontname', + 'command': 'fontname', + 'tests': [ + { 'id': 'FN:c_FONTf:a-1_SW', + 'rte1-id': 'c-fontname-0', + 'desc': 'Change existing font name to new font name (without CSS)', + 'value': 'courier', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FN:c_SPANs:ff:a-1_SW', + 'rte1-id': 'c-fontname-1', + 'desc': 'Change existing font name from style to new font name (without CSS)', + 'value': 'courier', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FN:c_FONTf:a.s:ff:v-1_SW', + 'rte1-id': 'c-fontname-2', + 'desc': 'Change existing font name with conflicting face and style to new font name (without CSS)', + 'value': 'courier', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FN:c_FONTf:a-1_SI', + 'desc': 'Change existing font name to new font name, text partially selected', + 'value': 'courier', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz', + 'accept': 'foo[bar]baz' }, + + { 'id': 'FN:c_FONTf:a-2_SL', + 'desc': 'Change existing font name to new font name, using CSS styling', + 'value': 'courier', + 'pad': 'foo[barbaz]qoz', + 'expected': 'foo[barbaz]qoz' }, + + { 'id': 'FN:c_FONTf:v-FONTf:a-1_SW', + 'rte1-id': 'c-fontname-3', + 'desc': 'Change existing font name in nested tags to new font name (without CSS)', + 'value': 'courier', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]', + 'accept': '[foobarbaz]' }, + + { 'id': 'FN:c_SPANs:ff:v-FONTf:a-1_SW', + 'rte1-id': 'c-fontname-4', + 'desc': 'Change existing font name in nested mixed tags to new font name (without CSS)', + 'value': 'courier', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]', + 'accept': '[foobarbaz]' } + ] + }, + + { 'desc': '[MIDAS] fontsize', + 'command': 'fontsize', + 'tests': [ + { 'id': 'FS:1_FONTsz:4-1_SW', + 'rte1-id': 'c-fontsize-0', + 'desc': 'Change existing font size to new size (without CSS)', + 'value': '1', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FS:1_SPAN.ass.s:fs:large-1_SW', + 'rte1-id': 'c-fontsize-1', + 'desc': 'Change existing font size from styled span to new size (without CSS)', + 'value': '1', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FS:5_FONTsz:1.s:fs:xs-1_SW', + 'rte1-id': 'c-fontsize-2', + 'desc': 'Change existing font size from tag with conflicting size and style to new size (without CSS)', + 'value': '5', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FS:2_FONTc:b.sz:6-1_SI', + 'desc': 'Change the font size in content with a different font size and font color', + 'value': '2', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ] }, + + { 'id': 'FS:larger_FONTsz:4', + 'desc': 'Change selection to use next larger font', + 'value': 'larger', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz', + 'accept': 'foo[bar]baz' }, + + { 'id': 'FS:smaller_FONTsz:4', + 'desc': 'Change selection to use next smaller font', + 'value': 'smaller', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz', + 'accept': 'foo[bar]baz' } + ] + }, + + { 'desc': '[MIDAS] formatblock', + 'command': 'formatblock', + 'tests': [ + { 'id': 'FB:h1_ADDRESS-1_SW', + 'desc': 'change block from
                  to

                  ', + 'value': 'h1', + 'pad': '
                  foo [bar] baz
                  ', + 'expected': '

                  foo [bar] baz

                  ' }, + + { 'id': 'FB:h1_ADDRESS-FONTsz:4-1_SO', + 'desc': 'change block from
                  with partially formatted content to

                  ', + 'value': 'h1', + 'pad': '
                  foo [bar] baz
                  ', + 'expected': '

                  foo [bar] baz

                  ' }, + + { 'id': 'FB:h1_ADDRESS-FONTsz:4-1_SW', + 'desc': 'change block from
                  with partially formatted content to

                  ', + 'value': 'h1', + 'pad': '
                  foo [bar] baz
                  ', + 'expected': '

                  foo [bar] baz

                  ' }, + + { 'id': 'FB:h1_ADDRESS-FONT.ass.sz:4-1_SW', + 'desc': 'change block from
                  with partially formatted content to

                  ', + 'value': 'h1', + 'pad': '
                  foo [bar] baz
                  ', + 'expected': '

                  foo [bar] baz

                  ' } + ] + } + ] +} + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/changeCSS.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/changeCSS.py new file mode 100644 index 0000000000..4862b9b733 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/changeCSS.py @@ -0,0 +1,210 @@ + +CHANGE_TESTS_CSS = { + 'id': 'CC', + 'caption': 'Change Existing Format to Different Format Tests, using styleWithCSS', + 'checkAttrs': True, + 'checkStyle': True, + 'styleWithCSS': True, + + 'Proposed': [ + { 'desc': '', + 'command': '', + 'tests': [ + ] + }, + + { 'desc': '[HTML5] italic', + 'command': 'italic', + 'tests': [ + { 'id': 'I_I-1_SL', + 'desc': 'Italicize partially italicized text', + 'pad': 'foo[barbaz]qoz', + 'expected': 'foo[barbaz]qoz' }, + + { 'id': 'I_B-1_SL', + 'desc': 'Italicize partially bolded text', + 'pad': 'foo[barbaz]qoz', + 'expected': 'foo[barbaz]qoz', + 'accept': 'foo[barbaz}qoz' }, + + { 'id': 'I_B-1_SW', + 'desc': 'Italicize bold text, ideally combining both', + 'pad': 'foobar[baz]qoz', + 'expected': 'foobar[baz]qoz', + 'accept': 'foobar[baz]qoz' } + ] + }, + + { 'desc': '[MIDAS] backcolor', + 'command': 'backcolor', + 'tests': [ + { 'id': 'BC:gray_SPANs:bc:b-1_SW', + 'desc': 'Change background color from blue to gray', + 'value': 'gray', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'BC:gray_SPANs:bc:b-1_SO', + 'desc': 'Change background color from blue to gray', + 'value': 'gray', + 'pad': '{foobarbaz}', + 'expected': [ '{foobarbaz}', + '[foobarbaz]' ] }, + + { 'id': 'BC:gray_SPANs:bc:b-1_SI', + 'desc': 'Change background color from blue to gray', + 'value': 'gray', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz', + 'accept': 'foo[bar]baz' }, + + { 'id': 'BC:gray_P-SPANs:bc:b-1_SW', + 'desc': 'Change background color within a paragraph from blue to gray', + 'value': 'gray', + 'pad': '

                  [foobarbaz]

                  ', + 'expected': [ '

                  [foobarbaz]

                  ', + '

                  [foobarbaz]

                  ' ] }, + + { 'id': 'BC:gray_P-SPANs:bc:b-2_SW', + 'desc': 'Change background color within a paragraph from blue to gray', + 'value': 'gray', + 'pad': '

                  foo[bar]baz

                  ', + 'expected': '

                  foo[bar]baz

                  ' }, + + { 'id': 'BC:gray_P-SPANs:bc:b-3_SO', + 'desc': 'Change background color within a paragraph from blue to gray (selection encloses more than previous span)', + 'value': 'gray', + 'pad': '

                  [foobarbazqoz]quz

                  ', + 'expected': '

                  [foobarbazqoz]quz

                  ' }, + + { 'id': 'BC:gray_P-SPANs:bc:b-3_SL', + 'desc': 'Change background color within a paragraph from blue to gray (previous span partially selected)', + 'value': 'gray', + 'pad': '

                  [foobar]bazqozquz

                  ', + 'expected': '

                  [foobar]bazqozquz

                  ' }, + + { 'id': 'BC:gray_SPANs:bc:b-2_SL', + 'desc': 'Change background color from blue to gray on partially covered span, selection extends left', + 'value': 'gray', + 'pad': 'foo [bar baz] qoz quz sic', + 'expected': 'foo [bar baz] qoz quz sic' }, + + { 'id': 'BC:gray_SPANs:bc:b-2_SR', + 'desc': 'Change background color from blue to gray on partially covered span, selection extends right', + 'value': 'gray', + 'pad': 'foo bar baz [qoz quz] sic', + 'expected': 'foo bar baz [qoz quz] sic' } + ] + }, + + { 'desc': '[MIDAS] fontname', + 'command': 'fontname', + 'tests': [ + { 'id': 'FN:c_SPANs:ff:a-1_SW', + 'desc': 'Change existing font name to new font name, using CSS styling', + 'value': 'courier', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FN:c_FONTf:a-1_SW', + 'desc': 'Change existing font name to new font name, using CSS styling', + 'value': 'courier', + 'pad': '[foobarbaz]', + 'expected': [ '[foobarbaz]', + '[foobarbaz]' ] }, + + { 'id': 'FN:c_FONTf:a-1_SI', + 'desc': 'Change existing font name to new font name, using CSS styling', + 'value': 'courier', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' }, + + { 'id': 'FN:a_FONTf:a-1_SI', + 'desc': 'Change existing font name to same font name, using CSS styling (should be noop)', + 'value': 'arial', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' }, + + { 'id': 'FN:a_FONTf:a-1_SW', + 'desc': 'Change existing font name to same font name, using CSS styling (should be noop or perhaps change tag)', + 'value': 'arial', + 'pad': '[foobarbaz]', + 'expected': [ '[foobarbaz]', + '[foobarbaz]' ] }, + + { 'id': 'FN:a_FONTf:a-1_SO', + 'desc': 'Change existing font name to same font name, using CSS styling (should be noop or perhaps change tag)', + 'value': 'arial', + 'pad': '{foobarbaz}', + 'expected': [ '{foobarbaz}', + '[foobarbaz]', + '{foobarbaz}', + '[foobarbaz]' ] }, + + { 'id': 'FN:a_SPANs:ff:a-1_SI', + 'desc': 'Change existing font name to same font name, using CSS styling (should be noop)', + 'value': 'arial', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FN:c_FONTf:a-2_SL', + 'desc': 'Change existing font name to new font name, using CSS styling', + 'value': 'courier', + 'pad': 'foo[barbaz]qoz', + 'expected': 'foo[barbaz]qoz' } + ] + }, + + { 'desc': '[MIDAS] fontsize', + 'command': 'fontsize', + 'tests': [ + { 'id': 'FS:1_SPANs:fs:l-1_SW', + 'desc': 'Change existing font size to new size, using CSS styling', + 'value': '1', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FS:large_SPANs:fs:l-1_SW', + 'desc': 'Change existing font size to same size (should be noop)', + 'value': 'large', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FS:18px_SPANs:fs:l-1_SW', + 'desc': 'Change existing font size to equivalent px size (should be noop, or change unit)', + 'value': '18px', + 'pad': '[foobarbaz]', + 'expected': [ '[foobarbaz]', + '[foobarbaz]' ] }, + + { 'id': 'FS:4_SPANs:fs:l-1_SW', + 'desc': 'Change existing font size to equivalent numeric size (should be noop)', + 'value': '4', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FS:4_SPANs:fs:18px-1_SW', + 'desc': 'Change existing font size to equivalent numeric size (should be noop)', + 'value': '4', + 'pad': '[foobarbaz]', + 'expected': '[foobarbaz]' }, + + { 'id': 'FS:larger_SPANs:fs:l-1_SI', + 'desc': 'Change selection to use next larger font', + 'value': 'larger', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ], + 'accept': 'foo[bar]baz' }, + + { 'id': 'FS:smaller_SPANs:fs:l-1_SI', + 'desc': 'Change selection to use next smaller font', + 'value': 'smaller', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo[bar]baz', + 'foo[bar]baz' ], + 'accept': 'foo[bar]baz' } + ] + } + ] +} diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/delete.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/delete.py new file mode 100644 index 0000000000..0cc6592258 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/delete.py @@ -0,0 +1,330 @@ + +DELETE_TESTS = { + 'id': 'D', + 'caption': 'Delete Tests', + 'command': 'delete', + 'checkAttrs': True, + 'checkStyle': False, + + 'Proposed': [ + { 'desc': '', + 'tests': [ + ] + }, + + { 'desc': 'delete single characters', + 'tests': [ + { 'id': 'CHAR-1_SC', + 'desc': 'Delete 1 character', + 'pad': 'foo^barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-2_SC', + 'desc': 'Delete 1 pre-composed character o with diaeresis', + 'pad': 'foö^barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-3_SC', + 'desc': 'Delete 1 character with combining diaeresis above', + 'pad': 'foö^barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-4_SC', + 'desc': 'Delete 1 character with combining diaeresis below', + 'pad': 'foo̤^barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-5_SC', + 'desc': 'Delete 1 character with combining diaeresis above and below', + 'pad': 'foö̤^barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-5_SI-1', + 'desc': 'Delete 1 character with combining diaeresis above and below, selection on diaeresis above', + 'pad': 'foo[̈]̤barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-5_SI-2', + 'desc': 'Delete 1 character with combining diaeresis above and below, selection on diaeresis below', + 'pad': 'foö[̤]barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-5_SR', + 'desc': 'Delete 1 character with combining diaeresis above and below, selection oblique on diaeresis and following text', + 'pad': 'foö[̤bar]baz', + 'expected': 'fo^baz' }, + + { 'id': 'CHAR-6_SC', + 'desc': 'Delete 1 character with enclosing square', + 'pad': 'foo⃞^barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-7_SC', + 'desc': 'Delete 1 character with combining long solidus overlay', + 'pad': 'foo̸^barbaz', + 'expected': 'fo^barbaz' } + ] + }, + + { 'desc': 'delete text selection', + 'tests': [ + { 'id': 'TEXT-1_SI', + 'desc': 'Delete text selection', + 'pad': 'foo[bar]baz', + 'expected': 'foo^baz' }, + + { 'id': 'B-1_SS', + 'desc': 'Delete at start of span', + 'pad': 'foo^barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'B-1_SA', + 'desc': 'Delete from position after span', + 'pad': 'foobar^baz', + 'expected': 'fooba^baz' }, + + { 'id': 'B-1_SW', + 'desc': 'Delete selection that wraps the whole span content', + 'pad': 'foo[bar]baz', + 'expected': 'foo^baz' }, + + { 'id': 'B-1_SO', + 'desc': 'Delete selection that wraps the whole span', + 'pad': 'foo[bar]baz', + 'expected': 'foo^baz' }, + + { 'id': 'B-1_SL', + 'desc': 'Delete oblique selection that starts before span', + 'pad': 'foo[barbaz]quozquuz', + 'expected': 'foo^quozquuz' }, + + { 'id': 'B-1_SR', + 'desc': 'Delete oblique selection that ends after span', + 'pad': 'foobar[bazquoz]quuz', + 'expected': 'foobar^quuz' }, + + { 'id': 'B.I-1_SM', + 'desc': 'Delete oblique selection that starts and ends in different spans', + 'pad': 'foobar[bazqoz]quuzquuuz', + 'expected': 'foobar^quuzquuuz' }, + + { 'id': 'GEN-1_SS', + 'desc': 'Delete at start of span with generated content', + 'pad': 'foo^barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'GEN-1_SA', + 'desc': 'Delete from position after span with generated content', + 'pad': 'foobar^baz', + 'expected': 'fooba^baz' } + ] + }, + + { 'desc': 'delete paragraphs', + 'tests': [ + { 'id': 'P2-1_SS2', + 'desc': 'Delete from collapsed selection at start of paragraph - should merge with previous', + 'pad': '

                  foobar

                  ^bazqoz

                  ', + 'expected': '

                  foobar^bazqoz

                  ' }, + + { 'id': 'P2-1_SI2', + 'desc': 'Delete non-collapsed selection at start of paragraph - should not merge with previous', + 'pad': '

                  foobar

                  [baz]qoz

                  ', + 'expected': '

                  foobar

                  ^qoz

                  ' }, + + { 'id': 'P2-1_SM', + 'desc': 'Delete non-collapsed selection spanning 2 paragraphs - should merge them', + 'pad': '

                  foo[bar

                  baz]qoz

                  ', + 'expected': '

                  foo^qoz

                  ' } + ] + }, + + { 'desc': 'delete lists and list items', + 'tests': [ + { 'id': 'OL-LI2-1_SO1', + 'desc': 'Delete fully wrapped list item', + 'pad': 'foo
                    {
                  1. bar
                  2. }
                  3. baz
                  qoz', + 'expected': ['foo
                    |
                  1. baz
                  qoz', + 'foo
                  1. ^baz
                  qoz'] }, + + { 'id': 'OL-LI2-1_SM', + 'desc': 'Delete oblique range between list items within same list', + 'pad': 'foo
                  1. ba[r
                  2. b]az
                  qoz', + 'expected': 'foo
                  1. ba^az
                  qoz' }, + + { 'id': 'OL-LI-1_SW', + 'desc': 'Delete contents of last list item (list should remain)', + 'pad': 'foo
                  1. [foo]
                  qoz', + 'expected': ['foo
                  1. |
                  qoz', + 'foo
                  1. ^
                  qoz'] }, + + { 'id': 'OL-LI-1_SO', + 'desc': 'Delete last list item of list (should remove entire list)', + 'pad': 'foo
                    {
                  1. foo
                  2. }
                  qoz', + 'expected': 'foo^qoz' } + ] + }, + + { 'desc': 'delete with strange selections', + 'tests': [ + { 'id': 'HR.BR-1_SM', + 'desc': 'Delete selection that starts and ends within nodes that don\'t have children', + 'pad': 'foo
                  bar
                  baz', + 'expected': 'foo
                  |
                  baz' } + ] + }, + + { 'desc': 'delete after table', + 'tests': [ + { 'id': 'TABLE-1_SA', + 'desc': 'Delete from position immediately after table (should have no effect)', + 'pad': 'foo
                  bar
                  ^baz', + 'expected': 'foo
                  bar
                  ^baz' } + ] + }, + + { 'desc': 'delete within table cells', + 'tests': [ + { 'id': 'TD-1_SS', + 'desc': 'Delete from start of first cell (should have no effect)', + 'pad': 'foo
                  ^bar
                  baz', + 'expected': 'foo
                  ^bar
                  baz' }, + + { 'id': 'TD2-1_SS2', + 'desc': 'Delete from start of inner cell (should have no effect)', + 'pad': 'foo
                  bar^baz
                  quoz', + 'expected': 'foo
                  bar^baz
                  quoz' }, + + { 'id': 'TD2-1_SM', + 'desc': 'Delete with selection spanning 2 cells', + 'pad': 'foo
                  ba[rb]az
                  quoz', + 'expected': 'foo
                  ba^az
                  quoz' } + ] + }, + + { 'desc': 'delete table rows', + 'tests': [ + { 'id': 'TR3-1_SO1', + 'desc': 'Delete first table row', + 'pad': '{}
                  A
                  B
                  C
                  ', + 'expected': ['|
                  B
                  C
                  ', + '
                  ^B
                  C
                  '] }, + + { 'id': 'TR3-1_SO2', + 'desc': 'Delete middle table row', + 'pad': '{}
                  A
                  B
                  C
                  ', + 'expected': ['|
                  A
                  C
                  ', + '
                  A
                  ^C
                  '] }, + + { 'id': 'TR3-1_SO3', + 'desc': 'Delete last table row', + 'pad': '{}
                  A
                  B
                  C
                  ', + 'expected': ['|
                  A
                  B
                  ', + '
                  A
                  B^
                  '] }, + + { 'id': 'TR2rs:2-1_SO1', + 'desc': 'Delete first table row where a cell has rowspan 2', + 'pad': '{}
                  AR
                  B
                  ', + 'expected': ['|
                  BR
                  ', + '
                  ^BR
                  '] }, + + { 'id': 'TR2rs:2-1_SO2', + 'desc': 'Delete second table row where a cell has rowspan 2', + 'pad': '{}
                  AR
                  B
                  ', + 'expected': ['|
                  AR
                  ', + '
                  AR^
                  '] }, + + { 'id': 'TR3rs:3-1_SO1', + 'desc': 'Delete first table row where a cell has rowspan 3', + 'pad': '{}
                  AR
                  B
                  C
                  ', + 'expected': ['|
                  AR
                  C
                  ', + '
                  ^AR
                  C
                  '] }, + + { 'id': 'TR3rs:3-1_SO2', + 'desc': 'Delete middle table row where a cell has rowspan 3', + 'pad': '{}
                  AR
                  B
                  C
                  ', + 'expected': ['|
                  BR
                  C
                  ', + '
                  BR
                  ^C
                  '] }, + + { 'id': 'TR3rs:3-1_SO3', + 'desc': 'Delete last table row where a cell has rowspan 3', + 'pad': '{}
                  AR
                  B
                  C
                  ', + 'expected': ['|
                  AR
                  B
                  ', + '
                  AR
                  B^
                  '] } + ] + }, + + { 'desc': 'delete with non-editable nested content', + 'tests': [ + { 'id': 'DIV:ce:false-1_SO', + 'desc': 'Delete nested non-editable
                  ', + 'pad': 'foo[bar
                  NESTED
                  baz]qoz', + 'expected': 'foo^qoz' }, + + { 'id': 'DIV:ce:false-1_SB', + 'desc': 'Delete from immediately after a nested non-editable
                  (should be no-op)', + 'pad': 'foobar
                  NESTED
                  ^bazqoz', + 'expected': 'foobar
                  NESTED
                  ^bazqoz' }, + + { 'id': 'DIV:ce:false-1_SL', + 'desc': 'Delete nested non-editable
                  with oblique selection', + 'pad': 'foo[bar
                  NES]TED
                  bazqoz', + 'expected': [ 'foo^
                  NESTED
                  bazqoz', + 'foo
                  [NES]TED
                  bazqoz' ] }, + + { 'id': 'DIV:ce:false-1_SR', + 'desc': 'Delete nested non-editable
                  with oblique selection', + 'pad': 'foobar
                  NES[TED
                  baz]qoz', + 'expected': [ 'foobar
                  NESTED
                  ^qoz', + 'foobar
                  NES[TED]
                  qoz' ] }, + + { 'id': 'DIV:ce:false-1_SI', + 'desc': 'Delete inside nested non-editable
                  (should be no-op)', + 'pad': 'foobar
                  NE[ST]ED
                  bazqoz', + 'expected': 'foobar
                  NE[ST]ED
                  bazqoz' } + ] + }, + + { 'desc': 'Delete with display:inline-block', + 'checkStyle': True, + 'tests': [ + { 'id': 'SPAN:d:ib-1_SC', + 'desc': 'Delete inside an inline-block ', + 'pad': 'foobar^bazqoz', + 'expected': 'fooba^bazqoz' }, + + { 'id': 'SPAN:d:ib-1_SA', + 'desc': 'Delete from immediately after an inline-block ', + 'pad': 'foobarbaz^qoz', + 'expected': 'foobarba^qoz' }, + + { 'id': 'SPAN:d:ib-2_SL', + 'desc': 'Delete with nested inline-block , oblique selection', + 'pad': 'foo[DELETE]barbaz', + 'expected': 'foo^barbaz' }, + + { 'id': 'SPAN:d:ib-3_SR', + 'desc': 'Delete with nested inline-block , oblique selection', + 'pad': 'foobar[DELETE]baz', + 'expected': 'foobar^baz' }, + + { 'id': 'SPAN:d:ib-4i_SI', + 'desc': 'Delete with nested inline-block , oblique selection', + 'pad': 'foobar[DELETE]bazqoz', + 'expected': 'foobar^bazqoz' }, + + { 'id': 'SPAN:d:ib-4l_SI', + 'desc': 'Delete with nested inline-block , oblique selection', + 'pad': 'foo[DELETE]barbazqoz', + 'expected': 'foo^barbazqoz' }, + + { 'id': 'SPAN:d:ib-4r_SI', + 'desc': 'Delete with nested inline-block , oblique selection', + 'pad': 'foobarbaz[DELETE]qoz', + 'expected': 'foobarbaz^qoz' } + ] + } + ] +} + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/forwarddelete.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/forwarddelete.py new file mode 100644 index 0000000000..d625a2a7d0 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/forwarddelete.py @@ -0,0 +1,315 @@ + +FORWARDDELETE_TESTS = { + 'id': 'FD', + 'caption': 'Forward-Delete Tests', + 'command': 'forwardDelete', + 'checkAttrs': True, + 'checkStyle': False, + + 'Proposed': [ + { 'desc': '', + 'tests': [ + ] + }, + + { 'desc': 'forward-delete single characters', + 'tests': [ + { 'id': 'CHAR-1_SC', + 'desc': 'Delete 1 character', + 'pad': 'foo^barbaz', + 'expected': 'foo^arbaz' }, + + { 'id': 'CHAR-2_SC', + 'desc': 'Delete 1 pre-composed character o with diaeresis', + 'pad': 'fo^öbarbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-3_SC', + 'desc': 'Delete 1 character with combining diaeresis above', + 'pad': 'fo^öbarbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-4_SC', + 'desc': 'Delete 1 character with combining diaeresis below', + 'pad': 'fo^o̤barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-5_SC', + 'desc': 'Delete 1 character with combining diaeresis above and below', + 'pad': 'fo^ö̤barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-6_SC', + 'desc': 'Delete 1 character with enclosing square', + 'pad': 'fo^o⃞barbaz', + 'expected': 'fo^barbaz' }, + + { 'id': 'CHAR-7_SC', + 'desc': 'Delete 1 character with combining long solidus overlay', + 'pad': 'fo^o̸barbaz', + 'expected': 'fo^barbaz' } + ] + }, + + { 'desc': 'forward-delete text selections', + 'tests': [ + { 'id': 'TEXT-1_SI', + 'desc': 'Delete text selection', + 'pad': 'foo[bar]baz', + 'expected': 'foo^baz' }, + + { 'id': 'B-1_SE', + 'desc': 'Forward-delete at end of span', + 'pad': 'foobar^baz', + 'expected': 'foobar^az' }, + + { 'id': 'B-1_SB', + 'desc': 'Forward-delete from position before span', + 'pad': 'foo^barbaz', + 'expected': 'foo^arbaz' }, + + { 'id': 'B-1_SW', + 'desc': 'Delete selection that wraps the whole span content', + 'pad': 'foo[bar]baz', + 'expected': 'foo^baz' }, + + { 'id': 'B-1_SO', + 'desc': 'Delete selection that wraps the whole span', + 'pad': 'foo[bar]baz', + 'expected': 'foo^baz' }, + + { 'id': 'B-1_SL', + 'desc': 'Delete oblique selection that starts before span', + 'pad': 'foo[barbaz]quozquuz', + 'expected': 'foo^quozquuz' }, + + { 'id': 'B-1_SR', + 'desc': 'Delete oblique selection that ends after span', + 'pad': 'foobar[bazquoz]quuz', + 'expected': 'foobar^quuz' }, + + { 'id': 'B.I-1_SM', + 'desc': 'Delete oblique selection that starts and ends in different spans', + 'pad': 'foobar[bazqoz]quuzquuuz', + 'expected': 'foobar^quuzquuuz' }, + + { 'id': 'GEN-1_SE', + 'desc': 'Delete at end of span with generated content', + 'pad': 'foobar^baz', + 'expected': 'foobar^az' }, + + { 'id': 'GEN-1_SB', + 'desc': 'Delete from position before span with generated content', + 'pad': 'foo^barbaz', + 'expected': 'foo^arbaz' } + ] + }, + + { 'desc': 'forward-delete paragraphs', + 'tests': [ + { 'id': 'P2-1_SE1', + 'desc': 'Delete from collapsed selection at end of paragraph - should merge with next', + 'pad': '

                  foobar^

                  bazqoz

                  ', + 'expected': '

                  foobar^bazqoz

                  ' }, + + { 'id': 'P2-1_SI1', + 'desc': 'Delete non-collapsed selection at end of paragraph - should not merge with next', + 'pad': '

                  foo[bar]

                  bazqoz

                  ', + 'expected': '

                  foo^

                  bazqoz

                  ' }, + + { 'id': 'P2-1_SM', + 'desc': 'Delete non-collapsed selection spanning 2 paragraphs - should merge them', + 'pad': '

                  foo[bar

                  baz]qoz

                  ', + 'expected': '

                  foo^qoz

                  ' } + ] + }, + + { 'desc': 'forward-delete lists and list items', + 'tests': [ + { 'id': 'OL-LI2-1_SO1', + 'desc': 'Delete fully wrapped list item', + 'pad': 'foo
                    {
                  1. bar
                  2. }
                  3. baz
                  qoz', + 'expected': ['foo
                    |
                  1. baz
                  qoz', + 'foo
                  1. ^baz
                  qoz'] }, + + { 'id': 'OL-LI2-1_SM', + 'desc': 'Delete oblique range between list items within same list', + 'pad': 'foo
                  1. ba[r
                  2. b]az
                  qoz', + 'expected': 'foo
                  1. ba^az
                  qoz' }, + + { 'id': 'OL-LI-1_SW', + 'desc': 'Delete contents of last list item (list should remain)', + 'pad': 'foo
                  1. [foo]
                  qoz', + 'expected': ['foo
                  1. |
                  qoz', + 'foo
                  1. ^
                  qoz'] }, + + { 'id': 'OL-LI-1_SO', + 'desc': 'Delete last list item of list (should remove entire list)', + 'pad': 'foo
                    {
                  1. foo
                  2. }
                  qoz', + 'expected': 'foo^qoz' } + ] + }, + + { 'desc': 'forward-delete with strange selections', + 'tests': [ + { 'id': 'HR.BR-1_SM', + 'desc': 'Delete selection that starts and ends within nodes that don\'t have children', + 'pad': 'foo
                  bar
                  baz', + 'expected': 'foo
                  |
                  baz' } + ] + }, + + { 'desc': 'forward-delete from immediately before a table', + 'tests': [ + { 'id': 'TABLE-1_SB', + 'desc': 'Delete from position immediately before table (should have no effect)', + 'pad': 'foo^
                  bar
                  baz', + 'expected': 'foo^
                  bar
                  baz' } + ] + }, + + { 'desc': 'forward-delete within table cells', + 'tests': [ + { 'id': 'TD-1_SE', + 'desc': 'Delete from end of last cell (should have no effect)', + 'pad': 'foo
                  bar^
                  baz', + 'expected': 'foo
                  bar^
                  baz' }, + + { 'id': 'TD2-1_SE1', + 'desc': 'Delete from end of inner cell (should have no effect)', + 'pad': 'foo
                  bar^baz
                  quoz', + 'expected': 'foo
                  bar^baz
                  quoz' }, + + { 'id': 'TD2-1_SM', + 'desc': 'Delete with selection spanning 2 cells', + 'pad': 'foo
                  ba[rb]az
                  quoz', + 'expected': 'foo
                  ba^az
                  quoz' } + ] + }, + + { 'desc': 'forward-delete table rows', + 'tests': [ + { 'id': 'TR3-1_SO1', + 'desc': 'Delete first table row', + 'pad': '{}
                  A
                  B
                  C
                  ', + 'expected': ['|
                  B
                  C
                  ', + '
                  ^B
                  C
                  '] }, + + { 'id': 'TR3-1_SO2', + 'desc': 'Delete middle table row', + 'pad': '{}
                  A
                  B
                  C
                  ', + 'expected': ['|
                  A
                  C
                  ', + '
                  A
                  ^C
                  '] }, + + { 'id': 'TR3-1_SO3', + 'desc': 'Delete last table row', + 'pad': '{}
                  A
                  B
                  C
                  ', + 'expected': ['|
                  A
                  B
                  ', + '
                  A
                  B^
                  '] }, + + { 'id': 'TR2rs:2-1_SO1', + 'desc': 'Delete first table row where a cell has rowspan 2', + 'pad': '{}
                  AR
                  B
                  ', + 'expected': ['|
                  BR
                  ', + '
                  ^BR
                  '] }, + + { 'id': 'TR2rs:2-1_SO2', + 'desc': 'Delete second table row where a cell has rowspan 2', + 'pad': '{}
                  AR
                  B
                  ', + 'expected': ['|
                  AR
                  ', + '
                  AR^
                  '] }, + + { 'id': 'TR3rs:3-1_SO1', + 'desc': 'Delete first table row where a cell has rowspan 3', + 'pad': '{}
                  AR
                  B
                  C
                  ', + 'expected': ['|
                  AR
                  C
                  ', + '
                  ^AR
                  C
                  '] }, + + { 'id': 'TR3rs:3-1_SO2', + 'desc': 'Delete middle table row where a cell has rowspan 3', + 'pad': '{}
                  AR
                  B
                  C
                  ', + 'expected': ['|
                  BR
                  C
                  ', + '
                  BR
                  ^C
                  '] }, + + { 'id': 'TR3rs:3-1_SO3', + 'desc': 'Delete last table row where a cell has rowspan 3', + 'pad': '{}
                  AR
                  B
                  C
                  ', + 'expected': ['|
                  AR
                  B
                  ', + '
                  AR
                  B^
                  '] } + ] + }, + + { 'desc': 'delete with non-editable nested content', + 'tests': [ + { 'id': 'DIV:ce:false-1_SO', + 'desc': 'Delete nested non-editable
                  ', + 'pad': 'foo[bar
                  NESTED
                  baz]qoz', + 'expected': 'foo^qoz' }, + + { 'id': 'DIV:ce:false-1_SB', + 'desc': 'Delete from immediately before a nested non-editable
                  (should be no-op)', + 'pad': 'foobar^
                  NESTED
                  bazqoz', + 'expected': 'foobar^
                  NESTED
                  bazqoz' }, + + { 'id': 'DIV:ce:false-1_SL', + 'desc': 'Delete nested non-editable
                  with oblique selection', + 'pad': 'foo[bar
                  NES]TED
                  bazqoz', + 'expected': [ 'foo^
                  NESTED
                  bazqoz', + 'foo
                  [NES]TED
                  bazqoz' ] }, + + { 'id': 'DIV:ce:false-1_SR', + 'desc': 'Delete nested non-editable
                  with oblique selection', + 'pad': 'foobar
                  NES[TED
                  baz]qoz', + 'expected': [ 'foobar
                  NESTED
                  ^qoz', + 'foobar
                  NES[TED]
                  qoz' ] }, + + { 'id': 'DIV:ce:false-1_SI', + 'desc': 'Delete inside nested non-editable
                  (should be no-op)', + 'pad': 'foobar
                  NE[ST]ED
                  bazqoz', + 'expected': 'foobar
                  NE[ST]ED
                  bazqoz' } + ] + }, + + { 'desc': 'Delete with display:inline-block', + 'checkStyle': True, + 'tests': [ + { 'id': 'SPAN:d:ib-1_SC', + 'desc': 'Delete inside an inline-block ', + 'pad': 'foobar^bazqoz', + 'expected': 'foobar^azqoz' }, + + { 'id': 'SPAN:d:ib-1_SA', + 'desc': 'Delete from immediately before an inline-block ', + 'pad': 'foo^barbazqoz', + 'expected': 'foo^arbazqoz' }, + + { 'id': 'SPAN:d:ib-2_SL', + 'desc': 'Delete with nested inline-block , oblique selection', + 'pad': 'foo[DELETE]barbaz', + 'expected': 'foo^barbaz' }, + + { 'id': 'SPAN:d:ib-3_SR', + 'desc': 'Delete with nested inline-block , oblique selection', + 'pad': 'foobar[DELETE]baz', + 'expected': 'foobar^baz' }, + + { 'id': 'SPAN:d:ib-4i_SI', + 'desc': 'Delete with nested inline-block , oblique selection', + 'pad': 'foobar[DELETE]bazqoz', + 'expected': 'foobar^bazqoz' }, + + { 'id': 'SPAN:d:ib-4l_SI', + 'desc': 'Delete with nested inline-block , oblique selection', + 'pad': 'foo[DELETE]barbazqoz', + 'expected': 'foo^barbazqoz' }, + + { 'id': 'SPAN:d:ib-4r_SI', + 'desc': 'Delete with nested inline-block , oblique selection', + 'pad': 'foobarbaz[DELETE]qoz', + 'expected': 'foobarbaz^qoz' } + ] + } + ] +} + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/insert.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/insert.py new file mode 100644 index 0000000000..a2e79c27c8 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/insert.py @@ -0,0 +1,285 @@ + +INSERT_TESTS = { + 'id': 'I', + 'caption': 'Insert Tests', + 'checkAttrs': False, + 'checkStyle': False, + + 'Proposed': [ + { 'desc': '', + 'command': '', + 'tests': [ + ] + }, + + { 'desc': 'insert
                  ', + 'command': 'inserthorizontalrule', + 'tests': [ + { 'id': 'IHR_TEXT-1_SC', + 'rte1-id': 'a-inserthorizontalrule-0', + 'desc': 'Insert
                  into text', + 'pad': 'foo^bar', + 'expected': 'foo
                  ^bar', + 'accept': 'foo
                  |bar' }, + + { 'id': 'IHR_TEXT-1_SI', + 'desc': 'Insert
                  , replacing selected text', + 'pad': 'foo[bar]baz', + 'expected': 'foo
                  ^baz', + 'accept': 'foo
                  |baz' }, + + { 'id': 'IHR_DIV-B-1_SX', + 'desc': 'Insert
                  between elements', + 'pad': '
                  foo|bar
                  ', + 'expected': '
                  foo
                  |bar
                  ' }, + + { 'id': 'IHR_DIV-B-2_SO', + 'desc': 'Insert
                  , replacing a fully wrapped element', + 'pad': '
                  foo{bar}baz
                  ', + 'expected': '
                  foo
                  |baz
                  ' }, + + { 'id': 'IHR_B-1_SC', + 'desc': 'Insert
                  into a span, splitting it', + 'pad': 'foo^bar', + 'expected': 'foo
                  ^bar' }, + + { 'id': 'IHR_B-1_SS', + 'desc': 'Insert
                  into a span at the start (should not create an empty span)', + 'pad': '^foobar', + 'expected': '
                  ^foobar' }, + + { 'id': 'IHR_B-1_SE', + 'desc': 'Insert
                  into a span at the end', + 'pad': 'foobar^', + 'expected': [ 'foobar
                  |', + 'foobar
                  ^' ] }, + + { 'id': 'IHR_B-2_SL', + 'desc': 'Insert
                  with oblique selection starting outside of span', + 'pad': 'foo[barbaz]qoz', + 'expected': 'foo
                  |qoz' }, + + { 'id': 'IHR_B-2_SLR', + 'desc': 'Insert
                  with oblique reversed selection starting outside of span', + 'pad': 'foo]barbaz[qoz', + 'expected': [ 'foo
                  |qoz', + 'foo
                  ^qoz' ] }, + + { 'id': 'IHR_B-3_SR', + 'desc': 'Insert
                  with oblique selection ending outside of span', + 'pad': 'foo[barbaz]quoz', + 'expected': [ 'foo
                  |quoz', + 'foo
                  ^quoz' ] }, + + { 'id': 'IHR_B-3_SRR', + 'desc': 'Insert
                  with oblique reversed selection starting outside of span', + 'pad': 'foo]barbaz[quoz', + 'expected': 'foo
                  |quoz' }, + + { 'id': 'IHR_B-I-1_SM', + 'desc': 'Insert
                  with oblique selection between different spans', + 'pad': 'foo[barbaz]quoz', + 'expected': [ 'foo
                  |quoz', + 'foo
                  ^quoz' ] }, + + { 'id': 'IHR_B-I-1_SMR', + 'desc': 'Insert
                  with reversed oblique selection between different spans', + 'pad': 'foo]barbaz[quoz', + 'expected': 'foo
                  ^quoz' }, + + { 'id': 'IHR_P-1_SC', + 'desc': 'Insert
                  into a paragraph, splitting it', + 'pad': '

                  foo^bar

                  ', + 'expected': [ '

                  foo


                  |

                  bar

                  ', + '

                  foo


                  ^bar

                  ' ] }, + + { 'id': 'IHR_P-1_SS', + 'desc': 'Insert
                  into a paragraph at the start (should not create an empty span)', + 'pad': '

                  ^foobar

                  ', + 'expected': [ '
                  |

                  foobar

                  ', + '

                  ^foobar

                  ' ] }, + + { 'id': 'IHR_P-1_SE', + 'desc': 'Insert
                  into a paragraph at the end (should not create an empty span)', + 'pad': '

                  foobar^

                  ', + 'expected': '

                  foobar


                  |' } + ] + }, + + { 'desc': 'insert

                  ', + 'command': 'insertparagraph', + 'tests': [ + { 'id': 'IP_P-1_SC', + 'desc': 'Split paragraph', + 'pad': '

                  foo^bar

                  ', + 'expected': '

                  foo

                  ^bar

                  ' }, + + { 'id': 'IP_UL-LI-1_SC', + 'desc': 'Split list item', + 'pad': '
                  • foo^bar
                  ', + 'expected': '
                  • foo
                  • ^bar
                  ' } + ] + }, + + { 'desc': 'insert text', + 'command': 'inserttext', + 'tests': [ + { 'id': 'ITEXT:text_TEXT-1_SC', + 'desc': 'Insert text', + 'value': 'text', + 'pad': 'foo^bar', + 'expected': 'footext^bar' }, + + { 'id': 'ITEXT:text_TEXT-1_SI', + 'desc': 'Insert text, replacing selected text', + 'value': 'text', + 'pad': 'foo[bar]baz', + 'expected': 'footext^baz' } + ] + }, + + { 'desc': 'insert
                  ', + 'command': 'insertlinebreak', + 'tests': [ + { 'id': 'IBR_TEXT-1_SC', + 'desc': 'Insert
                  into text', + 'pad': 'foo^bar', + 'expected': [ 'foo
                  |bar', + 'foo
                  ^bar' ] }, + + { 'id': 'IBR_TEXT-1_SI', + 'desc': 'Insert
                  , replacing selected text', + 'pad': 'foo[bar]baz', + 'expected': [ 'foo
                  |baz', + 'foo
                  ^baz' ] }, + + { 'id': 'IBR_LI-1_SC', + 'desc': 'Insert
                  within list item', + 'pad': '
                  • foo^bar
                  ', + 'expected': '
                  • foo
                    ^bar
                  ' } + ] + }, + + { 'desc': 'insert ', + 'command': 'insertimage', + 'tests': [ + { 'id': 'IIMG:url_TEXT-1_SC', + 'rte1-id': 'a-insertimage-0', + 'desc': 'Insert image with URL "bar.png"', + 'value': 'bar.png', + 'checkAttrs': True, + 'pad': 'foo^bar', + 'expected': [ 'foo|bar', + 'foo^bar' ] }, + + { 'id': 'IIMG:url_IMG-1_SO', + 'desc': 'Change existing image to new URL, selection on ', + 'value': 'quz.png', + 'checkAttrs': True, + 'pad': 'foo{}bar', + 'expected': [ 'foo|bar', + 'foo^bar' ] }, + + { 'id': 'IIMG:url_SPAN-IMG-1_SO', + 'desc': 'Change existing image to new URL, selection in text surrounding ', + 'value': 'quz.png', + 'checkAttrs': True, + 'pad': 'foo[]bar', + 'expected': [ 'foo|bar', + 'foo^bar' ] }, + + { 'id': 'IIMG:._SPAN-IMG-1_SO', + 'desc': 'Remove existing image or URL, selection on ', + 'value': '', + 'checkAttrs': True, + 'pad': 'foo{}bar', + 'expected': [ 'foo^bar', + 'foo|bar', + 'foo^bar', + 'foo|bar', + 'foo^bar' ] }, + + { 'id': 'IIMG:._IMG-1_SO', + 'desc': 'Remove existing image or URL, selection in text surrounding ', + 'value': '', + 'checkAttrs': True, + 'pad': 'foo[]bar', + 'expected': [ 'foo^bar', + 'foo|bar', + 'foo^bar', + 'foo|bar', + 'foo^bar' ] } + ] + }, + + { 'desc': 'insert
                    ', + 'command': 'insertorderedlist', + 'tests': [ + { 'id': 'IOL_TEXT-1_SC', + 'rte1-id': 'a-insertorderedlist-0', + 'desc': 'Insert ordered list on collapsed selection', + 'pad': 'foo^bar', + 'expected': '
                    1. foo^bar
                    ' }, + + { 'id': 'IOL_TEXT-1_SI', + 'desc': 'Insert ordered list on selected text', + 'pad': 'foo[bar]baz', + 'expected': '
                    1. foo[bar]baz
                    ' } + ] + }, + + { 'desc': 'insert
                      ', + 'command': 'insertunorderedlist', + 'tests': [ + { 'id': 'IUL_TEXT-1_SC', + 'desc': 'Insert unordered list on collapsed selection', + 'pad': 'foo^bar', + 'expected': '
                      • foo^bar
                      ' }, + + { 'id': 'IUL_TEXT-1_SI', + 'rte1-id': 'a-insertunorderedlist-0', + 'desc': 'Insert unordered list on selected text', + 'pad': 'foo[bar]baz', + 'expected': '
                      • foo[bar]baz
                      ' } + ] + }, + + { 'desc': 'insert arbitrary HTML', + 'command': 'inserthtml', + 'tests': [ + { 'id': 'IHTML:BR_TEXT-1_SC', + 'rte1-id': 'a-inserthtml-0', + 'desc': 'InsertHTML:
                      ', + 'value': '
                      ', + 'pad': 'foo^barbaz', + 'expected': 'foo
                      ^barbaz' }, + + { 'id': 'IHTML:text_TEXT-1_SI', + 'desc': 'InsertHTML: "NEW"', + 'value': 'NEW', + 'pad': 'foo[bar]baz', + 'expected': 'fooNEW^baz' }, + + { 'id': 'IHTML:S_TEXT-1_SI', + 'desc': 'InsertHTML: "NEW"', + 'value': 'NEW', + 'pad': 'foo[bar]baz', + 'expected': 'fooNEW^baz' }, + + { 'id': 'IHTML:H1.H2_TEXT-1_SI', + 'desc': 'InsertHTML: "

                      NEW

                      HTML

                      "', + 'value': '

                      NEW

                      HTML

                      ', + 'pad': 'foo[bar]baz', + 'expected': 'foo

                      NEW

                      HTML

                      ^baz' }, + + { 'id': 'IHTML:P-B_TEXT-1_SI', + 'desc': 'InsertHTML: "

                      NEWHTML!

                      "', + 'value': '

                      NEWHTML!

                      ', + 'pad': 'foo[bar]baz', + 'expected': 'foo

                      NEWHTML!

                      ^baz' } + ] + } + ] +} + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryEnabled.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryEnabled.py new file mode 100644 index 0000000000..eb721923b6 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryEnabled.py @@ -0,0 +1,215 @@ + +QUERYENABLED_TESTS = { + 'id': 'QE', + 'caption': 'queryCommandEnabled Tests', + 'pad': 'foo[bar]baz', + 'checkAttrs': False, + 'checkStyle': False, + 'styleWithCSS': False, + 'expected': True, + + 'Proposed': [ + { 'desc': '', + 'tests': [ + ] + }, + + { 'desc': 'HTML5 commands', + 'tests': [ + { 'id': 'SELECTALL_TEXT-1', + 'desc': 'check whether the "selectall" command is enabled', + 'qcenabled': 'selectall' }, + + { 'id': 'UNSELECT_TEXT-1', + 'desc': 'check whether the "unselect" command is enabled', + 'qcenabled': 'unselect' }, + + { 'id': 'UNDO_TEXT-1', + 'desc': 'check whether the "undo" command is enabled', + 'qcenabled': 'undo' }, + + { 'id': 'REDO_TEXT-1', + 'desc': 'check whether the "redo" command is enabled', + 'qcenabled': 'redo' }, + + { 'id': 'BOLD_TEXT-1', + 'desc': 'check whether the "bold" command is enabled', + 'qcenabled': 'bold' }, + + { 'id': 'ITALIC_TEXT-1', + 'desc': 'check whether the "italic" command is enabled', + 'qcenabled': 'italic' }, + + { 'id': 'UNDERLINE_TEXT-1', + 'desc': 'check whether the "underline" command is enabled', + 'qcenabled': 'underline' }, + + { 'id': 'STRIKETHROUGH_TEXT-1', + 'desc': 'check whether the "strikethrough" command is enabled', + 'qcenabled': 'strikethrough' }, + + { 'id': 'SUBSCRIPT_TEXT-1', + 'desc': 'check whether the "subscript" command is enabled', + 'qcenabled': 'subscript' }, + + { 'id': 'SUPERSCRIPT_TEXT-1', + 'desc': 'check whether the "superscript" command is enabled', + 'qcenabled': 'superscript' }, + + { 'id': 'FORMATBLOCK_TEXT-1', + 'desc': 'check whether the "formatblock" command is enabled', + 'qcenabled': 'formatblock' }, + + { 'id': 'CREATELINK_TEXT-1', + 'desc': 'check whether the "createlink" command is enabled', + 'qcenabled': 'createlink' }, + + { 'id': 'UNLINK_TEXT-1', + 'desc': 'check whether the "unlink" command is enabled', + 'qcenabled': 'unlink' }, + + { 'id': 'INSERTHTML_TEXT-1', + 'desc': 'check whether the "inserthtml" command is enabled', + 'qcenabled': 'inserthtml' }, + + { 'id': 'INSERTHORIZONTALRULE_TEXT-1', + 'desc': 'check whether the "inserthorizontalrule" command is enabled', + 'qcenabled': 'inserthorizontalrule' }, + + { 'id': 'INSERTIMAGE_TEXT-1', + 'desc': 'check whether the "insertimage" command is enabled', + 'qcenabled': 'insertimage' }, + + { 'id': 'INSERTLINEBREAK_TEXT-1', + 'desc': 'check whether the "insertlinebreak" command is enabled', + 'qcenabled': 'insertlinebreak' }, + + { 'id': 'INSERTPARAGRAPH_TEXT-1', + 'desc': 'check whether the "insertparagraph" command is enabled', + 'qcenabled': 'insertparagraph' }, + + { 'id': 'INSERTORDEREDLIST_TEXT-1', + 'desc': 'check whether the "insertorderedlist" command is enabled', + 'qcenabled': 'insertorderedlist' }, + + { 'id': 'INSERTUNORDEREDLIST_TEXT-1', + 'desc': 'check whether the "insertunorderedlist" command is enabled', + 'qcenabled': 'insertunorderedlist' }, + + { 'id': 'INSERTTEXT_TEXT-1', + 'desc': 'check whether the "inserttext" command is enabled', + 'qcenabled': 'inserttext' }, + + { 'id': 'DELETE_TEXT-1', + 'desc': 'check whether the "delete" command is enabled', + 'qcenabled': 'delete' }, + + { 'id': 'FORWARDDELETE_TEXT-1', + 'desc': 'check whether the "forwarddelete" command is enabled', + 'qcenabled': 'forwarddelete' } + ] + }, + + { 'desc': 'MIDAS commands', + 'tests': [ + { 'id': 'STYLEWITHCSS_TEXT-1', + 'desc': 'check whether the "styleWithCSS" command is enabled', + 'qcenabled': 'styleWithCSS' }, + + { 'id': 'CONTENTREADONLY_TEXT-1', + 'desc': 'check whether the "contentreadonly" command is enabled', + 'qcenabled': 'contentreadonly' }, + + { 'id': 'BACKCOLOR_TEXT-1', + 'desc': 'check whether the "backcolor" command is enabled', + 'qcenabled': 'backcolor' }, + + { 'id': 'FORECOLOR_TEXT-1', + 'desc': 'check whether the "forecolor" command is enabled', + 'qcenabled': 'forecolor' }, + + { 'id': 'HILITECOLOR_TEXT-1', + 'desc': 'check whether the "hilitecolor" command is enabled', + 'qcenabled': 'hilitecolor' }, + + { 'id': 'FONTNAME_TEXT-1', + 'desc': 'check whether the "fontname" command is enabled', + 'qcenabled': 'fontname' }, + + { 'id': 'FONTSIZE_TEXT-1', + 'desc': 'check whether the "fontsize" command is enabled', + 'qcenabled': 'fontsize' }, + + { 'id': 'INCREASEFONTSIZE_TEXT-1', + 'desc': 'check whether the "increasefontsize" command is enabled', + 'qcenabled': 'increasefontsize' }, + + { 'id': 'DECREASEFONTSIZE_TEXT-1', + 'desc': 'check whether the "decreasefontsize" command is enabled', + 'qcenabled': 'decreasefontsize' }, + + { 'id': 'HEADING_TEXT-1', + 'desc': 'check whether the "heading" command is enabled', + 'qcenabled': 'heading' }, + + { 'id': 'INDENT_TEXT-1', + 'desc': 'check whether the "indent" command is enabled', + 'qcenabled': 'indent' }, + + { 'id': 'OUTDENT_TEXT-1', + 'desc': 'check whether the "outdent" command is enabled', + 'qcenabled': 'outdent' }, + + { 'id': 'CREATEBOOKMARK_TEXT-1', + 'desc': 'check whether the "createbookmark" command is enabled', + 'qcenabled': 'createbookmark' }, + + { 'id': 'UNBOOKMARK_TEXT-1', + 'desc': 'check whether the "unbookmark" command is enabled', + 'qcenabled': 'unbookmark' }, + + { 'id': 'JUSTIFYCENTER_TEXT-1', + 'desc': 'check whether the "justifycenter" command is enabled', + 'qcenabled': 'justifycenter' }, + + { 'id': 'JUSTIFYFULL_TEXT-1', + 'desc': 'check whether the "justifyfull" command is enabled', + 'qcenabled': 'justifyfull' }, + + { 'id': 'JUSTIFYLEFT_TEXT-1', + 'desc': 'check whether the "justifyleft" command is enabled', + 'qcenabled': 'justifyleft' }, + + { 'id': 'JUSTIFYRIGHT_TEXT-1', + 'desc': 'check whether the "justifyright" command is enabled', + 'qcenabled': 'justifyright' }, + + { 'id': 'REMOVEFORMAT_TEXT-1', + 'desc': 'check whether the "removeformat" command is enabled', + 'qcenabled': 'removeformat' }, + + { 'id': 'COPY_TEXT-1', + 'desc': 'check whether the "copy" command is enabled', + 'qcenabled': 'copy' }, + + { 'id': 'CUT_TEXT-1', + 'desc': 'check whether the "cut" command is enabled', + 'qcenabled': 'cut' }, + + { 'id': 'PASTE_TEXT-1', + 'desc': 'check whether the "paste" command is enabled', + 'qcenabled': 'paste' } + ] + }, + + { 'desc': 'Other tests', + 'tests': [ + { 'id': 'garbage-1_TEXT-1', + 'desc': 'check correct return value with garbage input', + 'qcenabled': '#!#@7', + 'expected': False } + ] + } + ] +} + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryIndeterm.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryIndeterm.py new file mode 100644 index 0000000000..d1ad8debdb --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryIndeterm.py @@ -0,0 +1,214 @@ + +QUERYINDETERM_TESTS = { + 'id': 'QI', + 'caption': 'queryCommandIndeterm Tests', + 'pad': 'foo[bar]baz', + 'checkAttrs': False, + 'checkStyle': False, + 'styleWithCSS': False, + 'expected': False, + + 'Proposed': [ + { 'desc': '', + 'tests': [ + ] + }, + + { 'desc': 'HTML5 commands', + 'tests': [ + { 'id': 'SELECTALL_TEXT-1', + 'desc': 'check whether the "selectall" command is indeterminate', + 'qcindeterm': 'selectall' }, + + { 'id': 'UNSELECT_TEXT-1', + 'desc': 'check whether the "unselect" command is indeterminate', + 'qcindeterm': 'unselect' }, + + { 'id': 'UNDO_TEXT-1', + 'desc': 'check whether the "undo" command is indeterminate', + 'qcindeterm': 'undo' }, + + { 'id': 'REDO_TEXT-1', + 'desc': 'check whether the "redo" command is indeterminate', + 'qcindeterm': 'redo' }, + + { 'id': 'BOLD_TEXT-1', + 'desc': 'check whether the "bold" command is indeterminate', + 'qcindeterm': 'bold' }, + + { 'id': 'ITALIC_TEXT-1', + 'desc': 'check whether the "italic" command is indeterminate', + 'qcindeterm': 'italic' }, + + { 'id': 'UNDERLINE_TEXT-1', + 'desc': 'check whether the "underline" command is indeterminate', + 'qcindeterm': 'underline' }, + + { 'id': 'STRIKETHROUGH_TEXT-1', + 'desc': 'check whether the "strikethrough" command is indeterminate', + 'qcindeterm': 'strikethrough' }, + + { 'id': 'SUBSCRIPT_TEXT-1', + 'desc': 'check whether the "subscript" command is indeterminate', + 'qcindeterm': 'subscript' }, + + { 'id': 'SUPERSCRIPT_TEXT-1', + 'desc': 'check whether the "superscript" command is indeterminate', + 'qcindeterm': 'superscript' }, + + { 'id': 'FORMATBLOCK_TEXT-1', + 'desc': 'check whether the "formatblock" command is indeterminate', + 'qcindeterm': 'formatblock' }, + + { 'id': 'CREATELINK_TEXT-1', + 'desc': 'check whether the "createlink" command is indeterminate', + 'qcindeterm': 'createlink' }, + + { 'id': 'UNLINK_TEXT-1', + 'desc': 'check whether the "unlink" command is indeterminate', + 'qcindeterm': 'unlink' }, + + { 'id': 'INSERTHTML_TEXT-1', + 'desc': 'check whether the "inserthtml" command is indeterminate', + 'qcindeterm': 'inserthtml' }, + + { 'id': 'INSERTHORIZONTALRULE_TEXT-1', + 'desc': 'check whether the "inserthorizontalrule" command is indeterminate', + 'qcindeterm': 'inserthorizontalrule' }, + + { 'id': 'INSERTIMAGE_TEXT-1', + 'desc': 'check whether the "insertimage" command is indeterminate', + 'qcindeterm': 'insertimage' }, + + { 'id': 'INSERTLINEBREAK_TEXT-1', + 'desc': 'check whether the "insertlinebreak" command is indeterminate', + 'qcindeterm': 'insertlinebreak' }, + + { 'id': 'INSERTPARAGRAPH_TEXT-1', + 'desc': 'check whether the "insertparagraph" command is indeterminate', + 'qcindeterm': 'insertparagraph' }, + + { 'id': 'INSERTORDEREDLIST_TEXT-1', + 'desc': 'check whether the "insertorderedlist" command is indeterminate', + 'qcindeterm': 'insertorderedlist' }, + + { 'id': 'INSERTUNORDEREDLIST_TEXT-1', + 'desc': 'check whether the "insertunorderedlist" command is indeterminate', + 'qcindeterm': 'insertunorderedlist' }, + + { 'id': 'INSERTTEXT_TEXT-1', + 'desc': 'check whether the "inserttext" command is indeterminate', + 'qcindeterm': 'inserttext' }, + + { 'id': 'DELETE_TEXT-1', + 'desc': 'check whether the "delete" command is indeterminate', + 'qcindeterm': 'delete' }, + + { 'id': 'FORWARDDELETE_TEXT-1', + 'desc': 'check whether the "forwarddelete" command is indeterminate', + 'qcindeterm': 'forwarddelete' } + ] + }, + + { 'desc': 'MIDAS commands', + 'tests': [ + { 'id': 'STYLEWITHCSS_TEXT-1', + 'desc': 'check whether the "styleWithCSS" command is indeterminate', + 'qcindeterm': 'styleWithCSS' }, + + { 'id': 'CONTENTREADONLY_TEXT-1', + 'desc': 'check whether the "contentreadonly" command is indeterminate', + 'qcindeterm': 'contentreadonly' }, + + { 'id': 'BACKCOLOR_TEXT-1', + 'desc': 'check whether the "backcolor" command is indeterminate', + 'qcindeterm': 'backcolor' }, + + { 'id': 'FORECOLOR_TEXT-1', + 'desc': 'check whether the "forecolor" command is indeterminate', + 'qcindeterm': 'forecolor' }, + + { 'id': 'HILITECOLOR_TEXT-1', + 'desc': 'check whether the "hilitecolor" command is indeterminate', + 'qcindeterm': 'hilitecolor' }, + + { 'id': 'FONTNAME_TEXT-1', + 'desc': 'check whether the "fontname" command is indeterminate', + 'qcindeterm': 'fontname' }, + + { 'id': 'FONTSIZE_TEXT-1', + 'desc': 'check whether the "fontsize" command is indeterminate', + 'qcindeterm': 'fontsize' }, + + { 'id': 'INCREASEFONTSIZE_TEXT-1', + 'desc': 'check whether the "increasefontsize" command is indeterminate', + 'qcindeterm': 'increasefontsize' }, + + { 'id': 'DECREASEFONTSIZE_TEXT-1', + 'desc': 'check whether the "decreasefontsize" command is indeterminate', + 'qcindeterm': 'decreasefontsize' }, + + { 'id': 'HEADING_TEXT-1', + 'desc': 'check whether the "heading" command is indeterminate', + 'qcindeterm': 'heading' }, + + { 'id': 'INDENT_TEXT-1', + 'desc': 'check whether the "indent" command is indeterminate', + 'qcindeterm': 'indent' }, + + { 'id': 'OUTDENT_TEXT-1', + 'desc': 'check whether the "outdent" command is indeterminate', + 'qcindeterm': 'outdent' }, + + { 'id': 'CREATEBOOKMARK_TEXT-1', + 'desc': 'check whether the "createbookmark" command is indeterminate', + 'qcindeterm': 'createbookmark' }, + + { 'id': 'UNBOOKMARK_TEXT-1', + 'desc': 'check whether the "unbookmark" command is indeterminate', + 'qcindeterm': 'unbookmark' }, + + { 'id': 'JUSTIFYCENTER_TEXT-1', + 'desc': 'check whether the "justifycenter" command is indeterminate', + 'qcindeterm': 'justifycenter' }, + + { 'id': 'JUSTIFYFULL_TEXT-1', + 'desc': 'check whether the "justifyfull" command is indeterminate', + 'qcindeterm': 'justifyfull' }, + + { 'id': 'JUSTIFYLEFT_TEXT-1', + 'desc': 'check whether the "justifyleft" command is indeterminate', + 'qcindeterm': 'justifyleft' }, + + { 'id': 'JUSTIFYRIGHT_TEXT-1', + 'desc': 'check whether the "justifyright" command is indeterminate', + 'qcindeterm': 'justifyright' }, + + { 'id': 'REMOVEFORMAT_TEXT-1', + 'desc': 'check whether the "removeformat" command is indeterminate', + 'qcindeterm': 'removeformat' }, + + { 'id': 'COPY_TEXT-1', + 'desc': 'check whether the "copy" command is indeterminate', + 'qcindeterm': 'copy' }, + + { 'id': 'CUT_TEXT-1', + 'desc': 'check whether the "cut" command is indeterminate', + 'qcindeterm': 'cut' }, + + { 'id': 'PASTE_TEXT-1', + 'desc': 'check whether the "paste" command is indeterminate', + 'qcindeterm': 'paste' } + ] + }, + + { 'desc': 'Other tests', + 'tests': [ + { 'id': 'garbage-1_TEXT-1', + 'desc': 'check correct return value with garbage input', + 'qcindeterm': '#!#@7' } + ] + } + ] +} + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryState.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryState.py new file mode 100644 index 0000000000..297559d625 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryState.py @@ -0,0 +1,575 @@ + +QUERYSTATE_TESTS = { + 'id': 'QS', + 'caption': 'queryCommandState Tests', + 'checkAttrs': False, + 'checkStyle': False, + 'styleWithCSS': False, + + 'Proposed': [ + { 'desc': '', + 'qcstate': '', + 'tests': [ + ] + }, + + { 'desc': 'query bold state', + 'qcstate': 'bold', + 'tests': [ + { 'id': 'B_TEXT_SI', + 'rte1-id': 'q-bold-0', + 'desc': 'query the "bold" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'B_B-1_SI', + 'rte1-id': 'q-bold-1', + 'desc': 'query the "bold" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'B_STRONG-1_SI', + 'rte1-id': 'q-bold-2', + 'desc': 'query the "bold" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'B_SPANs:fw:b-1_SI', + 'rte1-id': 'q-bold-3', + 'desc': 'query the "bold" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'B_SPANs:fw:n-1_SI', + 'desc': 'query the "bold" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'B_Bs:fw:n-1_SI', + 'rte1-id': 'q-bold-4', + 'desc': 'query the "bold" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'B_B-SPANs:fw:n-1_SI', + 'rte1-id': 'q-bold-5', + 'desc': 'query the "bold" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'B_SPAN.b-1-SI', + 'desc': 'query the "bold" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'B_MYB-1-SI', + 'desc': 'query the "bold" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'B_B-I-1_SC', + 'desc': 'query the "bold" state, bold tag not immediate parent', + 'pad': 'fooba^rbaz', + 'expected': True }, + + { 'id': 'B_B-I-1_SL', + 'desc': 'query the "bold" state, selection partially in child element', + 'pad': 'fo[ob]arbaz', + 'expected': True }, + + { 'id': 'B_B-I-1_SR', + 'desc': 'query the "bold" state, selection partially in child element', + 'pad': 'fooba[rb]az', + 'expected': True }, + + { 'id': 'B_STRONG-I-1_SC', + 'desc': 'query the "bold" state, bold tag not immediate parent', + 'pad': 'fooba^rbaz', + 'expected': True }, + + { 'id': 'B_B-I-U-1_SC', + 'desc': 'query the "bold" state, bold tag not immediate parent', + 'pad': 'foobarb^az', + 'expected': True }, + + { 'id': 'B_B-I-U-1_SM', + 'desc': 'query the "bold" state, bold tag not immediate parent', + 'pad': 'fooba[rb]az', + 'expected': True }, + + { 'id': 'B_TEXT-B-1_SO-1', + 'desc': 'query the "bold" state, selection wrapping the bold tag', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'B_TEXT-B-1_SO-2', + 'desc': 'query the "bold" state, selection wrapping the bold tag', + 'pad': 'foo{bar}baz', + 'expected': True }, + + { 'id': 'B_TEXT-B-1_SL', + 'desc': 'query the "bold" state, selection containing non-bold text', + 'pad': 'fo[oba]rbaz', + 'expected': False }, + + { 'id': 'B_TEXT-B-1_SR', + 'desc': 'query the "bold" state, selection containing non-bold text', + 'pad': 'foob[arb]az', + 'expected': False }, + + { 'id': 'B_TEXT-B-1_SO-3', + 'desc': 'query the "bold" state, selection containing non-bold text', + 'pad': 'fo[obarb]az', + 'expected': False }, + + { 'id': 'B_B.TEXT.B-1_SM', + 'desc': 'query the "bold" state, selection including non-bold text', + 'pad': 'fo[obarb]az', + 'expected': False }, + + { 'id': 'B_B.B.B-1_SM', + 'desc': 'query the "bold" state, selection mixed, but all bold', + 'pad': 'fo[obarb]az', + 'expected': True }, + + { 'id': 'B_B.STRONG.B-1_SM', + 'desc': 'query the "bold" state, selection mixed, but all bold', + 'pad': 'fo[obarb]az', + 'expected': True }, + + { 'id': 'B_SPAN.b.MYB.SPANs:fw:b-1_SM', + 'desc': 'query the "bold" state, selection mixed, but all bold', + 'pad': 'fo[obarb]az', + 'expected': True } + ] + }, + + { 'desc': 'query italic state', + 'qcstate': 'italic', + 'tests': [ + { 'id': 'I_TEXT_SI', + 'rte1-id': 'q-italic-0', + 'desc': 'query the "italic" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'I_I-1_SI', + 'rte1-id': 'q-italic-1', + 'desc': 'query the "italic" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'I_EM-1_SI', + 'rte1-id': 'q-italic-2', + 'desc': 'query the "italic" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'I_SPANs:fs:i-1_SI', + 'rte1-id': 'q-italic-3', + 'desc': 'query the "italic" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'I_SPANs:fs:n-1_SI', + 'desc': 'query the "italic" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'I_I-SPANs:fs:n-1_SI', + 'rte1-id': 'q-italic-4', + 'desc': 'query the "italic" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'I_SPAN.i-1-SI', + 'desc': 'query the "italic" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'I_MYI-1-SI', + 'desc': 'query the "italic" state', + 'pad': 'foo[bar]baz', + 'expected': True } + ] + }, + + { 'desc': 'query underline state', + 'qcstate': 'underline', + 'tests': [ + { 'id': 'U_TEXT_SI', + 'rte1-id': 'q-underline-0', + 'desc': 'query the "underline" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'U_U-1_SI', + 'rte1-id': 'q-underline-1', + 'desc': 'query the "underline" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'U_Us:td:n-1_SI', + 'rte1-id': 'q-underline-4', + 'desc': 'query the "underline" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'U_Ah:url-1_SI', + 'rte1-id': 'q-underline-2', + 'desc': 'query the "underline" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'U_Ah:url.s:td:n-1_SI', + 'rte1-id': 'q-underline-5', + 'desc': 'query the "underline" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'U_SPANs:td:u-1_SI', + 'rte1-id': 'q-underline-3', + 'desc': 'query the "underline" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'U_SPAN.u-1-SI', + 'desc': 'query the "underline" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'U_MYU-1-SI', + 'desc': 'query the "underline" state', + 'pad': 'foo[bar]baz', + 'expected': True } + ] + }, + + { 'desc': 'query strike-through state', + 'qcstate': 'strikethrough', + 'tests': [ + { 'id': 'S_TEXT_SI', + 'rte1-id': 'q-strikethrough-0', + 'desc': 'query the "strikethrough" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'S_S-1_SI', + 'rte1-id': 'q-strikethrough-3', + 'desc': 'query the "strikethrough" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'S_STRIKE-1_SI', + 'rte1-id': 'q-strikethrough-1', + 'desc': 'query the "strikethrough" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'S_STRIKEs:td:n-1_SI', + 'rte1-id': 'q-strikethrough-2', + 'desc': 'query the "strikethrough" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'S_DEL-1_SI', + 'rte1-id': 'q-strikethrough-4', + 'desc': 'query the "strikethrough" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'S_SPANs:td:lt-1_SI', + 'rte1-id': 'q-strikethrough-5', + 'desc': 'query the "strikethrough" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'S_SPAN.s-1-SI', + 'desc': 'query the "strikethrough" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'S_MYS-1-SI', + 'desc': 'query the "strikethrough" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'S_S.STRIKE.DEL-1_SM', + 'desc': 'query the "strikethrough" state, selection mixed, but all struck', + 'pad': 'fo[obarb]az', + 'expected': True } + ] + }, + + { 'desc': 'query subscript state', + 'qcstate': 'subscript', + 'tests': [ + { 'id': 'SUB_TEXT_SI', + 'rte1-id': 'q-subscript-0', + 'desc': 'query the "subscript" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'SUB_SUB-1_SI', + 'rte1-id': 'q-subscript-1', + 'desc': 'query the "subscript" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'SUB_SPAN.sub-1-SI', + 'desc': 'query the "subscript" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'SUB_MYSUB-1-SI', + 'desc': 'query the "subscript" state', + 'pad': 'foo[bar]baz', + 'expected': True } + ] + }, + + { 'desc': 'query superscript state', + 'qcstate': 'superscript', + 'tests': [ + { 'id': 'SUP_TEXT_SI', + 'rte1-id': 'q-superscript-0', + 'desc': 'query the "superscript" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'SUP_SUP-1_SI', + 'rte1-id': 'q-superscript-1', + 'desc': 'query the "superscript" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'IOL_TEXT_SI', + 'desc': 'query the "insertorderedlist" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'SUP_SPAN.sup-1-SI', + 'desc': 'query the "superscript" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'SUP_MYSUP-1-SI', + 'desc': 'query the "superscript" state', + 'pad': 'foo[bar]baz', + 'expected': True } + ] + }, + + { 'desc': 'query whether the selection is in an ordered list', + 'qcstate': 'insertorderedlist', + 'tests': [ + { 'id': 'IOL_TEXT-1_SI', + 'rte1-id': 'q-insertorderedlist-0', + 'desc': 'query the "insertorderedlist" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'IOL_OL-LI-1_SI', + 'rte1-id': 'q-insertorderedlist-1', + 'desc': 'query the "insertorderedlist" state', + 'pad': '
                      1. foo[bar]baz
                      ', + 'expected': True }, + + { 'id': 'IOL_UL_LI-1_SI', + 'rte1-id': 'q-insertorderedlist-2', + 'desc': 'query the "insertorderedlist" state', + 'pad': '
                      • foo[bar]baz
                      ', + 'expected': False } + ] + }, + + { 'desc': 'query whether the selection is in an unordered list', + 'qcstate': 'insertunorderedlist', + 'tests': [ + { 'id': 'IUL_TEXT_SI', + 'rte1-id': 'q-insertunorderedlist-0', + 'desc': 'query the "insertunorderedlist" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'IUL_OL-LI-1_SI', + 'rte1-id': 'q-insertunorderedlist-1', + 'desc': 'query the "insertunorderedlist" state', + 'pad': '
                      1. foo[bar]baz
                      ', + 'expected': False }, + + { 'id': 'IUL_UL-LI-1_SI', + 'rte1-id': 'q-insertunorderedlist-2', + 'desc': 'query the "insertunorderedlist" state', + 'pad': '
                      • foo[bar]baz
                      ', + 'expected': True } + ] + }, + + { 'desc': 'query whether the paragraph is centered', + 'qcstate': 'justifycenter', + 'tests': [ + { 'id': 'JC_TEXT_SI', + 'rte1-id': 'q-justifycenter-0', + 'desc': 'query the "justifycenter" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'JC_DIVa:c-1_SI', + 'rte1-id': 'q-justifycenter-1', + 'desc': 'query the "justifycenter" state', + 'pad': '
                      foo[bar]baz
                      ', + 'expected': True }, + + { 'id': 'JC_Pa:c-1_SI', + 'rte1-id': 'q-justifycenter-2', + 'desc': 'query the "justifycenter" state', + 'pad': '

                      foo[bar]baz

                      ', + 'expected': True }, + + { 'id': 'JC_SPANs:ta:c-1_SI', + 'rte1-id': 'q-justifycenter-3', + 'desc': 'query the "justifycenter" state', + 'pad': '
                      foo[bar]baz
                      ', + 'expected': True }, + + { 'id': 'JC_SPAN.jc-1-SI', + 'desc': 'query the "justifycenter" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'JC_MYJC-1-SI', + 'desc': 'query the "justifycenter" state', + 'pad': 'foo[bar]baz', + 'expected': True } + ] + }, + + { 'desc': 'query whether the paragraph is justified', + 'qcstate': 'justifyfull', + 'tests': [ + { 'id': 'JF_TEXT_SI', + 'rte1-id': 'q-justifyfull-0', + 'desc': 'query the "justifyfull" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'JF_DIVa:j-1_SI', + 'rte1-id': 'q-justifyfull-1', + 'desc': 'query the "justifyfull" state', + 'pad': '
                      foo[bar]baz
                      ', + 'expected': True }, + + { 'id': 'JF_Pa:j-1_SI', + 'rte1-id': 'q-justifyfull-2', + 'desc': 'query the "justifyfull" state', + 'pad': '

                      foo[bar]baz

                      ', + 'expected': True }, + + { 'id': 'JF_SPANs:ta:j-1_SI', + 'rte1-id': 'q-justifyfull-3', + 'desc': 'query the "justifyfull" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'JF_SPAN.jf-1-SI', + 'desc': 'query the "justifyfull" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'JF_MYJF-1-SI', + 'desc': 'query the "justifyfull" state', + 'pad': 'foo[bar]baz', + 'expected': True } + ] + }, + + { 'desc': 'query whether the paragraph is aligned left', + 'qcstate': 'justifyleft', + 'tests': [ + { 'id': 'JL_TEXT_SI', + 'desc': 'query the "justifyleft" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'JL_DIVa:l-1_SI', + 'rte1-id': 'q-justifyleft-0', + 'desc': 'query the "justifyleft" state', + 'pad': '
                      foo[bar]baz
                      ', + 'expected': True }, + + { 'id': 'JL_Pa:l-1_SI', + 'rte1-id': 'q-justifyleft-1', + 'desc': 'query the "justifyleft" state', + 'pad': '

                      foo[bar]baz

                      ', + 'expected': True }, + + { 'id': 'JL_SPANs:ta:l-1_SI', + 'rte1-id': 'q-justifyleft-2', + 'desc': 'query the "justifyleft" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'JL_SPAN.jl-1-SI', + 'desc': 'query the "justifyleft" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'JL_MYJL-1-SI', + 'desc': 'query the "justifyleft" state', + 'pad': 'foo[bar]baz', + 'expected': True } + ] + }, + + { 'desc': 'query whether the paragraph is aligned right', + 'qcstate': 'justifyright', + 'tests': [ + { 'id': 'JR_TEXT_SI', + 'rte1-id': 'q-justifyright-0', + 'desc': 'query the "justifyright" state', + 'pad': 'foo[bar]baz', + 'expected': False }, + + { 'id': 'JR_DIVa:r-1_SI', + 'rte1-id': 'q-justifyright-1', + 'desc': 'query the "justifyright" state', + 'pad': '
                      foo[bar]baz
                      ', + 'expected': True }, + + { 'id': 'JR_Pa:r-1_SI', + 'rte1-id': 'q-justifyright-2', + 'desc': 'query the "justifyright" state', + 'pad': '

                      foo[bar]baz

                      ', + 'expected': True }, + + { 'id': 'JR_SPANs:ta:r-1_SI', + 'rte1-id': 'q-justifyright-3', + 'desc': 'query the "justifyright" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'JR_SPAN.jr-1-SI', + 'desc': 'query the "justifyright" state', + 'pad': 'foo[bar]baz', + 'expected': True }, + + { 'id': 'JR_MYJR-1-SI', + 'desc': 'query the "justifyright" state', + 'pad': 'foo[bar]baz', + 'expected': True } + ] + } + ] +} + +QUERYSTATE_TESTS_CSS = { + 'id': 'QSC', + 'caption': 'queryCommandState Tests, using styleWithCSS', + 'checkAttrs': False, + 'checkStyle': False, + 'styleWithCSS': True, + + 'Proposed': QUERYSTATE_TESTS['Proposed'] +} + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/querySupported.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/querySupported.py new file mode 100644 index 0000000000..af23a428ce --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/querySupported.py @@ -0,0 +1,226 @@ + +QUERYSUPPORTED_TESTS = { + 'id': 'Q', + 'caption': 'queryCommandSupported Tests', + 'pad': 'foo[bar]baz', + 'checkAttrs': False, + 'checkStyle': False, + 'styleWithCSS': False, + 'expected': True, + + 'Proposed': [ + { 'desc': '', + 'tests': [ + ] + }, + + { 'desc': 'HTML5 commands', + 'tests': [ + { 'id': 'SELECTALL_TEXT-1', + 'desc': 'check whether the "selectall" command is supported', + 'qcsupported': 'selectall' }, + + { 'id': 'UNSELECT_TEXT-1', + 'desc': 'check whether the "unselect" command is supported', + 'qcsupported': 'unselect' }, + + { 'id': 'UNDO_TEXT-1', + 'desc': 'check whether the "undo" command is supported', + 'qcsupported': 'undo' }, + + { 'id': 'REDO_TEXT-1', + 'desc': 'check whether the "redo" command is supported', + 'qcsupported': 'redo' }, + + { 'id': 'BOLD_TEXT-1', + 'desc': 'check whether the "bold" command is supported', + 'qcsupported': 'bold' }, + + { 'id': 'BOLD_B', + 'desc': 'check whether the "bold" command is supported', + 'qcsupported': 'bold', + 'pad': 'foo[bar]baz' }, + + { 'id': 'ITALIC_TEXT-1', + 'desc': 'check whether the "italic" command is supported', + 'qcsupported': 'italic' }, + + { 'id': 'ITALIC_I', + 'desc': 'check whether the "italic" command is supported', + 'qcsupported': 'italic', + 'pad': 'foo[bar]baz' }, + + { 'id': 'UNDERLINE_TEXT-1', + 'desc': 'check whether the "underline" command is supported', + 'qcsupported': 'underline' }, + + { 'id': 'STRIKETHROUGH_TEXT-1', + 'desc': 'check whether the "strikethrough" command is supported', + 'qcsupported': 'strikethrough' }, + + { 'id': 'SUBSCRIPT_TEXT-1', + 'desc': 'check whether the "subscript" command is supported', + 'qcsupported': 'subscript' }, + + { 'id': 'SUPERSCRIPT_TEXT-1', + 'desc': 'check whether the "superscript" command is supported', + 'qcsupported': 'superscript' }, + + { 'id': 'FORMATBLOCK_TEXT-1', + 'desc': 'check whether the "formatblock" command is supported', + 'qcsupported': 'formatblock' }, + + { 'id': 'CREATELINK_TEXT-1', + 'desc': 'check whether the "createlink" command is supported', + 'qcsupported': 'createlink' }, + + { 'id': 'UNLINK_TEXT-1', + 'desc': 'check whether the "unlink" command is supported', + 'qcsupported': 'unlink' }, + + { 'id': 'INSERTHTML_TEXT-1', + 'desc': 'check whether the "inserthtml" command is supported', + 'qcsupported': 'inserthtml' }, + + { 'id': 'INSERTHORIZONTALRULE_TEXT-1', + 'desc': 'check whether the "inserthorizontalrule" command is supported', + 'qcsupported': 'inserthorizontalrule' }, + + { 'id': 'INSERTIMAGE_TEXT-1', + 'desc': 'check whether the "insertimage" command is supported', + 'qcsupported': 'insertimage' }, + + { 'id': 'INSERTLINEBREAK_TEXT-1', + 'desc': 'check whether the "insertlinebreak" command is supported', + 'qcsupported': 'insertlinebreak' }, + + { 'id': 'INSERTPARAGRAPH_TEXT-1', + 'desc': 'check whether the "insertparagraph" command is supported', + 'qcsupported': 'insertparagraph' }, + + { 'id': 'INSERTORDEREDLIST_TEXT-1', + 'desc': 'check whether the "insertorderedlist" command is supported', + 'qcsupported': 'insertorderedlist' }, + + { 'id': 'INSERTUNORDEREDLIST_TEXT-1', + 'desc': 'check whether the "insertunorderedlist" command is supported', + 'qcsupported': 'insertunorderedlist' }, + + { 'id': 'INSERTTEXT_TEXT-1', + 'desc': 'check whether the "inserttext" command is supported', + 'qcsupported': 'inserttext' }, + + { 'id': 'DELETE_TEXT-1', + 'desc': 'check whether the "delete" command is supported', + 'qcsupported': 'delete' }, + + { 'id': 'FORWARDDELETE_TEXT-1', + 'desc': 'check whether the "forwarddelete" command is supported', + 'qcsupported': 'forwarddelete' } + ] + }, + + { 'desc': 'MIDAS commands', + 'tests': [ + { 'id': 'STYLEWITHCSS_TEXT-1', + 'desc': 'check whether the "styleWithCSS" command is supported', + 'qcsupported': 'styleWithCSS' }, + + { 'id': 'CONTENTREADONLY_TEXT-1', + 'desc': 'check whether the "contentreadonly" command is supported', + 'qcsupported': 'contentreadonly' }, + + { 'id': 'BACKCOLOR_TEXT-1', + 'desc': 'check whether the "backcolor" command is supported', + 'qcsupported': 'backcolor' }, + + { 'id': 'FORECOLOR_TEXT-1', + 'desc': 'check whether the "forecolor" command is supported', + 'qcsupported': 'forecolor' }, + + { 'id': 'HILITECOLOR_TEXT-1', + 'desc': 'check whether the "hilitecolor" command is supported', + 'qcsupported': 'hilitecolor' }, + + { 'id': 'FONTNAME_TEXT-1', + 'desc': 'check whether the "fontname" command is supported', + 'qcsupported': 'fontname' }, + + { 'id': 'FONTSIZE_TEXT-1', + 'desc': 'check whether the "fontsize" command is supported', + 'qcsupported': 'fontsize' }, + + { 'id': 'INCREASEFONTSIZE_TEXT-1', + 'desc': 'check whether the "increasefontsize" command is supported', + 'qcsupported': 'increasefontsize' }, + + { 'id': 'DECREASEFONTSIZE_TEXT-1', + 'desc': 'check whether the "decreasefontsize" command is supported', + 'qcsupported': 'decreasefontsize' }, + + { 'id': 'HEADING_TEXT-1', + 'desc': 'check whether the "heading" command is supported', + 'qcsupported': 'heading' }, + + { 'id': 'INDENT_TEXT-1', + 'desc': 'check whether the "indent" command is supported', + 'qcsupported': 'indent' }, + + { 'id': 'OUTDENT_TEXT-1', + 'desc': 'check whether the "outdent" command is supported', + 'qcsupported': 'outdent' }, + + { 'id': 'CREATEBOOKMARK_TEXT-1', + 'desc': 'check whether the "createbookmark" command is supported', + 'qcsupported': 'createbookmark' }, + + { 'id': 'UNBOOKMARK_TEXT-1', + 'desc': 'check whether the "unbookmark" command is supported', + 'qcsupported': 'unbookmark' }, + + { 'id': 'JUSTIFYCENTER_TEXT-1', + 'desc': 'check whether the "justifycenter" command is supported', + 'qcsupported': 'justifycenter' }, + + { 'id': 'JUSTIFYFULL_TEXT-1', + 'desc': 'check whether the "justifyfull" command is supported', + 'qcsupported': 'justifyfull' }, + + { 'id': 'JUSTIFYLEFT_TEXT-1', + 'desc': 'check whether the "justifyleft" command is supported', + 'qcsupported': 'justifyleft' }, + + { 'id': 'JUSTIFYRIGHT_TEXT-1', + 'desc': 'check whether the "justifyright" command is supported', + 'qcsupported': 'justifyright' }, + + { 'id': 'REMOVEFORMAT_TEXT-1', + 'desc': 'check whether the "removeformat" command is supported', + 'qcsupported': 'removeformat' }, + + { 'id': 'COPY_TEXT-1', + 'desc': 'check whether the "copy" command is supported', + 'qcsupported': 'copy' }, + + { 'id': 'CUT_TEXT-1', + 'desc': 'check whether the "cut" command is supported', + 'qcsupported': 'cut' }, + + { 'id': 'PASTE_TEXT-1', + 'desc': 'check whether the "paste" command is supported', + 'qcsupported': 'paste' } + ] + }, + + { 'desc': 'Other tests', + 'tests': [ + { 'id': 'garbage-1_TEXT-1', + 'desc': 'check correct return value with garbage input', + 'qcsupported': '#!#@7', + 'expected': False } + ] + } + ] +} + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryValue.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryValue.py new file mode 100644 index 0000000000..793b7cb6cf --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/queryValue.py @@ -0,0 +1,429 @@ + +QUERYVALUE_TESTS = { + 'id': 'QV', + 'caption': 'queryCommandValue Tests', + 'checkAttrs': False, + 'checkStyle': False, + 'styleWithCSS': False, + + 'Proposed': [ + { 'desc': '', + 'tests': [ + ] + }, + + { 'desc': '[HTML5] query bold value', + 'qcvalue': 'bold', + 'tests': [ + { 'id': 'B_TEXT_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'false' }, + + { 'id': 'B_B-1_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'true' }, + + { 'id': 'B_STRONG-1_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'true' }, + + { 'id': 'B_SPANs:fw:b-1_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'true' }, + + { 'id': 'B_SPANs:fw:n-1_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'false' }, + + { 'id': 'B_Bs:fw:n-1_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'false' }, + + { 'id': 'B_SPAN.b-1_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'true' }, + + { 'id': 'B_MYB-1-SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'true' } + ] + }, + + { 'desc': '[HTML5] query italic value', + 'qcvalue': 'italic', + 'tests': [ + { 'id': 'I_TEXT_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'false' }, + + { 'id': 'I_I-1_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'true' }, + + { 'id': 'I_EM-1_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'true' }, + + { 'id': 'I_SPANs:fs:i-1_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'true' }, + + { 'id': 'I_SPANs:fs:n-1_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'false' }, + + { 'id': 'I_I-SPANs:fs:n-1_SI', + 'desc': 'query the "bold" value', + 'pad': 'foo[bar]baz', + 'expected': 'false' }, + + { 'id': 'I_SPAN.i-1_SI', + 'desc': 'query the "italic" value', + 'pad': 'foo[bar]baz', + 'expected': 'true' }, + + { 'id': 'I_MYI-1-SI', + 'desc': 'query the "italic" value', + 'pad': 'foo[bar]baz', + 'expected': 'true' } + ] + }, + + { 'desc': '[HTML5] query block formatting value', + 'qcvalue': 'formatblock', + 'tests': [ + { 'id': 'FB_TEXT-1_SC', + 'desc': 'query the "formatBlock" value', + 'pad': 'foobar^baz', + 'expected': '', + 'accept': 'normal' }, + + { 'id': 'FB_H1-1_SC', + 'desc': 'query the "formatBlock" value', + 'pad': '

                      foobar^baz

                      ', + 'expected': 'h1' }, + + { 'id': 'FB_PRE-1_SC', + 'desc': 'query the "formatBlock" value', + 'pad': '
                      foobar^baz
                      ', + 'expected': 'pre' }, + + { 'id': 'FB_BQ-1_SC', + 'desc': 'query the "formatBlock" value', + 'pad': '
                      foobar^baz
                      ', + 'expected': 'blockquote' }, + + { 'id': 'FB_ADDRESS-1_SC', + 'desc': 'query the "formatBlock" value', + 'pad': '
                      foobar^baz
                      ', + 'expected': 'address' }, + + { 'id': 'FB_H1-H2-1_SC', + 'desc': 'query the "formatBlock" value', + 'pad': '

                      foo

                      ba^r

                      baz', + 'expected': 'h2' }, + + { 'id': 'FB_H1-H2-1_SL', + 'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)', + 'pad': '

                      fo[o

                      ba]r

                      baz', + 'expected': 'h1' }, + + { 'id': 'FB_H1-H2-1_SR', + 'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)', + 'pad': '

                      foo

                      b[ar

                      ba]z', + 'expected': 'h1' }, + + { 'id': 'FB_TEXT-ADDRESS-1_SL', + 'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)', + 'pad': 'fo[o
                      ba]r
                      baz', + 'expected': '', + 'accept': 'normal' }, + + { 'id': 'FB_TEXT-ADDRESS-1_SR', + 'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)', + 'pad': 'foo
                      b[ar
                      ba]z', + 'expected': '', + 'accept': 'normal' }, + + { 'id': 'FB_H1-H2.TEXT.H2-1_SM', + 'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)', + 'pad': '

                      fo[o

                      bar

                      b]az

                      ', + 'expected': 'h1' } + ] + }, + + { 'desc': '[MIDAS] query heading type', + 'qcvalue': 'heading', + 'tests': [ + { 'id': 'H_H1-1_SC', + 'desc': 'query the "heading" type', + 'pad': '

                      foobar^baz

                      ', + 'expected': 'h1', + 'accept': '

                      ' }, + + { 'id': 'H_H3-1_SC', + 'desc': 'query the "heading" type', + 'pad': '

                      foobar^baz

                      ', + 'expected': 'h3', + 'accept': '

                      ' }, + + { 'id': 'H_H1-H2-H3-H4-1_SC', + 'desc': 'query the "heading" type within nested heading tags', + 'pad': '

                      foobar^baz

                      ', + 'expected': 'h4', + 'accept': '

                      ' }, + + { 'id': 'H_P-1_SC', + 'desc': 'query the "heading" type outside of a heading', + 'pad': '

                      foobar^baz

                      ', + 'expected': '' } + ] + }, + + { 'desc': '[MIDAS] query font name', + 'qcvalue': 'fontname', + 'tests': [ + { 'id': 'FN_FONTf:a-1_SI', + 'rte1-id': 'q-fontname-0', + 'desc': 'query the "fontname" value', + 'pad': 'foo[bar]baz', + 'expected': 'arial' }, + + { 'id': 'FN_SPANs:ff:a-1_SI', + 'rte1-id': 'q-fontname-1', + 'desc': 'query the "fontname" value', + 'pad': 'foo[bar]baz', + 'expected': 'arial' }, + + { 'id': 'FN_FONTf:a.s:ff:c-1_SI', + 'rte1-id': 'q-fontname-2', + 'desc': 'query the "fontname" value', + 'pad': 'foo[bar]baz', + 'expected': 'courier' }, + + { 'id': 'FN_FONTf:a-FONTf:c-1_SI', + 'rte1-id': 'q-fontname-3', + 'desc': 'query the "fontname" value', + 'pad': 'foo[bar]baz', + 'expected': 'courier' }, + + { 'id': 'FN_SPANs:ff:c-FONTf:a-1_SI', + 'rte1-id': 'q-fontname-4', + 'desc': 'query the "fontname" value', + 'pad': 'foo[bar]baz', + 'expected': 'arial' }, + + { 'id': 'FN_SPAN.fs18px-1_SI', + 'desc': 'query the "fontname" value', + 'pad': 'foo[bar]baz', + 'expected': 'courier' }, + + { 'id': 'FN_MYCOURIER-1-SI', + 'desc': 'query the "fontname" value', + 'pad': 'foo[bar]baz', + 'expected': 'courier' } + ] + }, + + { 'desc': '[MIDAS] query font size', + 'qcvalue': 'fontsize', + 'tests': [ + { 'id': 'FS_FONTsz:4-1_SI', + 'rte1-id': 'q-fontsize-0', + 'desc': 'query the "fontsize" value', + 'pad': 'foo[bar]baz', + 'expected': '18px' }, + + { 'id': 'FS_FONTs:fs:l-1_SI', + 'desc': 'query the "fontsize" value', + 'pad': 'foo[bar]baz', + 'expected': '18px' }, + + { 'id': 'FS_FONT.ass.s:fs:l-1_SI', + 'rte1-id': 'q-fontsize-1', + 'desc': 'query the "fontsize" value', + 'pad': 'foo[bar]baz', + 'expected': '18px' }, + + { 'id': 'FS_FONTsz:1.s:fs:xl-1_SI', + 'rte1-id': 'q-fontsize-2', + 'desc': 'query the "fontsize" value', + 'pad': 'foo[bar]baz', + 'expected': '24px' }, + + { 'id': 'FS_SPAN.large-1_SI', + 'desc': 'query the "fontsize" value', + 'pad': 'foo[bar]baz', + 'expected': 'large' }, + + { 'id': 'FS_SPAN.fs18px-1_SI', + 'desc': 'query the "fontsize" value', + 'pad': 'foo[bar]baz', + 'expected': '18px' }, + + { 'id': 'FA_MYLARGE-1-SI', + 'desc': 'query the "fontsize" value', + 'pad': 'foo[bar]baz', + 'expected': 'large' }, + + { 'id': 'FA_MYFS18PX-1-SI', + 'desc': 'query the "fontsize" value', + 'pad': 'foo[bar]baz', + 'expected': '18px' } + ] + }, + + { 'desc': '[MIDAS] query background color', + 'qcvalue': 'backcolor', + 'tests': [ + { 'id': 'BC_FONTs:bc:fca-1_SI', + 'rte1-id': 'q-backcolor-0', + 'desc': 'query the "backcolor" value', + 'pad': 'foo[bar]baz', + 'expected': '#ffccaa' }, + + { 'id': 'BC_SPANs:bc:abc-1_SI', + 'rte1-id': 'q-backcolor-2', + 'desc': 'query the "backcolor" value', + 'pad': 'foo[bar]baz', + 'expected': '#aabbcc' }, + + { 'id': 'BC_FONTs:bc:084-SPAN-1_SI', + 'desc': 'query the "backcolor" value, where the color was set on an ancestor', + 'pad': 'foo[bar]baz', + 'expected': '#008844' }, + + { 'id': 'BC_SPANs:bc:cde-SPAN-1_SI', + 'desc': 'query the "backcolor" value, where the color was set on an ancestor', + 'pad': 'foo[bar]baz', + 'expected': '#ccddee' }, + + { 'id': 'BC_SPAN.ass.s:bc:rgb-1_SI', + 'rte1-id': 'q-backcolor-1', + 'desc': 'query the "backcolor" value', + 'pad': 'foo[bar]baz', + 'expected': '#ff0000' }, + + { 'id': 'BC_SPAN.bcred-1_SI', + 'desc': 'query the "backcolor" value', + 'pad': 'foo[bar]baz', + 'expected': 'red' }, + + { 'id': 'BC_MYBCRED-1-SI', + 'desc': 'query the "backcolor" value', + 'pad': 'foo[bar]baz', + 'expected': 'red' } + ] + }, + + { 'desc': '[MIDAS] query text color', + 'qcvalue': 'forecolor', + 'tests': [ + { 'id': 'FC_FONTc:f00-1_SI', + 'rte1-id': 'q-forecolor-0', + 'desc': 'query the "forecolor" value', + 'pad': 'foo[bar]baz', + 'expected': '#ff0000' }, + + { 'id': 'FC_SPANs:c:0f0-1_SI', + 'rte1-id': 'q-forecolor-1', + 'desc': 'query the "forecolor" value', + 'pad': 'foo[bar]baz', + 'expected': '#00ff00' }, + + { 'id': 'FC_FONTc:333.s:c:999-1_SI', + 'rte1-id': 'q-forecolor-2', + 'desc': 'query the "forecolor" value', + 'pad': 'foo[bar]baz', + 'expected': '#999999' }, + + { 'id': 'FC_FONTc:641-SPAN-1_SI', + 'desc': 'query the "forecolor" value, where the color was set on an ancestor', + 'pad': 'foo[bar]baz', + 'expected': '#664411' }, + + { 'id': 'FC_SPANs:c:d95-SPAN-1_SI', + 'desc': 'query the "forecolor" value, where the color was set on an ancestor', + 'pad': 'foo[bar]baz', + 'expected': '#dd9955' }, + + { 'id': 'FC_SPAN.red-1_SI', + 'desc': 'query the "forecolor" value', + 'pad': 'foo[bar]baz', + 'expected': 'red' }, + + { 'id': 'FC_MYRED-1-SI', + 'desc': 'query the "forecolor" value', + 'pad': 'foo[bar]baz', + 'expected': 'red' } + ] + }, + + { 'desc': '[MIDAS] query hilight color (same as background color)', + 'qcvalue': 'hilitecolor', + 'tests': [ + { 'id': 'HC_FONTs:bc:fc0-1_SI', + 'rte1-id': 'q-hilitecolor-0', + 'desc': 'query the "hilitecolor" value', + 'pad': 'foo[bar]baz', + 'expected': '#ffcc00' }, + + { 'id': 'HC_SPANs:bc:a0c-1_SI', + 'rte1-id': 'q-hilitecolor-2', + 'desc': 'query the "hilitecolor" value', + 'pad': 'foo[bar]baz', + 'expected': '#aa00cc' }, + + { 'id': 'HC_SPAN.ass.s:bc:rgb-1_SI', + 'rte1-id': 'q-hilitecolor-1', + 'desc': 'query the "hilitecolor" value', + 'pad': 'foo[bar]baz', + 'expected': '#ff0000' }, + + { 'id': 'HC_FONTs:bc:83e-SPAN-1_SI', + 'desc': 'query the "hilitecolor" value, where the color was set on an ancestor', + 'pad': 'foo[bar]baz', + 'expected': '#8833ee' }, + + { 'id': 'HC_SPANs:bc:b12-SPAN-1_SI', + 'desc': 'query the "hilitecolor" value, where the color was set on an ancestor', + 'pad': 'foo[bar]baz', + 'expected': '#bb1122' }, + + { 'id': 'HC_SPAN.bcred-1_SI', + 'desc': 'query the "hilitecolor" value', + 'pad': 'foo[bar]baz', + 'expected': 'red' }, + + { 'id': 'HC_MYBCRED-1-SI', + 'desc': 'query the "hilitecolor" value', + 'pad': 'foo[bar]baz', + 'expected': 'red' } + ] + } + ] +} + +QUERYVALUE_TESTS_CSS = { + 'id': 'QVC', + 'caption': 'queryCommandValue Tests, using styleWithCSS', + 'checkAttrs': False, + 'checkStyle': False, + 'styleWithCSS': True, + + 'Proposed': QUERYVALUE_TESTS['Proposed'] +} + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/selection.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/selection.py new file mode 100644 index 0000000000..6fa7e69a66 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/selection.py @@ -0,0 +1,801 @@ + +SELECTION_TESTS = { + 'id': 'S', + 'caption': 'Selection Tests', + 'checkAttrs': True, + 'checkStyle': True, + 'styleWithCSS': False, + + 'Proposed': [ + { 'desc': '', + 'command': '', + 'tests': [ + ] + }, + + { 'desc': 'selectall', + 'command': 'selectall', + 'tests': [ + { 'id': 'SELALL_TEXT-1_SI', + 'desc': 'select all, text only', + 'pad': 'foo [bar] baz', + 'expected': [ '[foo bar baz]', + '{foo bar baz}' ] }, + + { 'id': 'SELALL_I-1_SI', + 'desc': 'select all, with outer tags', + 'pad': 'foo [bar] baz', + 'expected': '{foo bar baz}' } + ] + }, + + { 'desc': 'unselect', + 'command': 'unselect', + 'tests': [ + { 'id': 'UNSEL_TEXT-1_SI', + 'desc': 'unselect', + 'pad': 'foo [bar] baz', + 'expected': 'foo bar baz' } + ] + }, + + { 'desc': 'sel.modify (generic)', + 'tests': [ + { 'id': 'SM:m.f.c_TEXT-1_SC-1', + 'desc': 'move caret 1 character forward', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'foo b^ar baz', + 'expected': 'foo ba^r baz' }, + + { 'id': 'SM:m.b.c_TEXT-1_SC-1', + 'desc': 'move caret 1 character backward', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foo b^ar baz', + 'expected': 'foo ^bar baz' }, + + { 'id': 'SM:m.f.c_TEXT-1_SI-1', + 'desc': 'move caret forward (sollapse selection)', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'foo [bar] baz', + 'expected': 'foo bar^ baz' }, + + { 'id': 'SM:m.b.c_TEXT-1_SI-1', + 'desc': 'move caret backward (collapse selection)', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foo [bar] baz', + 'expected': 'foo ^bar baz' }, + + { 'id': 'SM:m.f.w_TEXT-1_SC-1', + 'desc': 'move caret 1 word forward', + 'function': 'sel.modify("move", "forward", "word");', + 'pad': 'foo b^ar baz', + 'expected': 'foo bar^ baz' }, + + { 'id': 'SM:m.f.w_TEXT-1_SC-2', + 'desc': 'move caret 1 word forward', + 'function': 'sel.modify("move", "forward", "word");', + 'pad': 'foo^ bar baz', + 'expected': 'foo bar^ baz' }, + + { 'id': 'SM:m.f.w_TEXT-1_SI-1', + 'desc': 'move caret 1 word forward from non-collapsed selection', + 'function': 'sel.modify("move", "forward", "word");', + 'pad': 'foo [bar] baz', + 'expected': 'foo bar baz^' }, + + { 'id': 'SM:m.b.w_TEXT-1_SC-1', + 'desc': 'move caret 1 word backward', + 'function': 'sel.modify("move", "backward", "word");', + 'pad': 'foo b^ar baz', + 'expected': 'foo ^bar baz' }, + + { 'id': 'SM:m.b.w_TEXT-1_SC-3', + 'desc': 'move caret 1 word backward', + 'function': 'sel.modify("move", "backward", "word");', + 'pad': 'foo bar ^baz', + 'expected': 'foo ^bar baz' }, + + { 'id': 'SM:m.b.w_TEXT-1_SI-1', + 'desc': 'move caret 1 word backward from non-collapsed selection', + 'function': 'sel.modify("move", "backward", "word");', + 'pad': 'foo [bar] baz', + 'expected': '^foo bar baz' } + ] + }, + + { 'desc': 'sel.modify: move forward over combining diacritics, etc.', + 'tests': [ + { 'id': 'SM:m.f.c_CHAR-2_SC-1', + 'desc': 'move 1 character forward over combined o with diaeresis', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'fo^öbarbaz', + 'expected': 'foö^barbaz' }, + + { 'id': 'SM:m.f.c_CHAR-3_SC-1', + 'desc': 'move 1 character forward over character with combining diaeresis above', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'fo^öbarbaz', + 'expected': 'foö^barbaz' }, + + { 'id': 'SM:m.f.c_CHAR-4_SC-1', + 'desc': 'move 1 character forward over character with combining diaeresis below', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'fo^o̤barbaz', + 'expected': 'foo̤^barbaz' }, + + { 'id': 'SM:m.f.c_CHAR-5_SC-1', + 'desc': 'move 1 character forward over character with combining diaeresis above and below', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'fo^ö̤barbaz', + 'expected': 'foö̤^barbaz' }, + + { 'id': 'SM:m.f.c_CHAR-5_SI-1', + 'desc': 'move 1 character forward over character with combining diaeresis above and below, selection on diaeresis above', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'foo[̈]̤barbaz', + 'expected': 'foö̤^barbaz' }, + + { 'id': 'SM:m.f.c_CHAR-5_SI-2', + 'desc': 'move 1 character forward over character with combining diaeresis above and below, selection on diaeresis below', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'foö[̤]barbaz', + 'expected': 'foö̤^barbaz' }, + + { 'id': 'SM:m.f.c_CHAR-5_SL', + 'desc': 'move 1 character forward over character with combining diaeresis above and below, selection oblique on diaeresis and preceding text', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'fo[ö]̤barbaz', + 'expected': 'foö̤^barbaz' }, + + { 'id': 'SM:m.f.c_CHAR-5_SR', + 'desc': 'move 1 character forward over character with combining diaeresis above and below, selection oblique on diaeresis and following text', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'foö[̤bar]baz', + 'expected': 'foö̤bar^baz' }, + + { 'id': 'SM:m.f.c_CHAR-6_SC-1', + 'desc': 'move 1 character forward over character with enclosing square', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'fo^o⃞barbaz', + 'expected': 'foo⃞^barbaz' }, + + { 'id': 'SM:m.f.c_CHAR-7_SC-1', + 'desc': 'move 1 character forward over character with combining long solidus overlay', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'fo^o̸barbaz', + 'expected': 'foo̸^barbaz' } + ] + }, + + { 'desc': 'sel.modify: move backward over combining diacritics, etc.', + 'tests': [ + { 'id': 'SM:m.b.c_CHAR-2_SC-1', + 'desc': 'move 1 character backward over combined o with diaeresis', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foö^barbaz', + 'expected': 'fo^öbarbaz' }, + + { 'id': 'SM:m.b.c_CHAR-3_SC-1', + 'desc': 'move 1 character backward over character with combining diaeresis above', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foö^barbaz', + 'expected': 'fo^öbarbaz' }, + + { 'id': 'SM:m.b.c_CHAR-4_SC-1', + 'desc': 'move 1 character backward over character with combining diaeresis below', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foo̤^barbaz', + 'expected': 'fo^o̤barbaz' }, + + { 'id': 'SM:m.b.c_CHAR-5_SC-1', + 'desc': 'move 1 character backward over character with combining diaeresis above and below', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foö̤^barbaz', + 'expected': 'fo^ö̤barbaz' }, + + { 'id': 'SM:m.b.c_CHAR-5_SI-1', + 'desc': 'move 1 character backward over character with combining diaeresis above and below, selection on diaeresis above', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foo[̈]̤barbaz', + 'expected': 'fo^ö̤barbaz' }, + + { 'id': 'SM:m.b.c_CHAR-5_SI-2', + 'desc': 'move 1 character backward over character with combining diaeresis above and below, selection on diaeresis below', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foö[̤]barbaz', + 'expected': 'fo^ö̤barbaz' }, + + { 'id': 'SM:m.b.c_CHAR-5_SL', + 'desc': 'move 1 character backward over character with combining diaeresis above and below, selection oblique on diaeresis and preceding text', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'fo[ö]̤barbaz', + 'expected': 'fo^ö̤barbaz' }, + + { 'id': 'SM:m.b.c_CHAR-5_SR', + 'desc': 'move 1 character backward over character with combining diaeresis above and below, selection oblique on diaeresis and following text', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foö[̤bar]baz', + 'expected': 'fo^ö̤barbaz' }, + + { 'id': 'SM:m.b.c_CHAR-6_SC-1', + 'desc': 'move 1 character backward over character with enclosing square', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foo⃞^barbaz', + 'expected': 'fo^o⃞barbaz' }, + + { 'id': 'SM:m.b.c_CHAR-7_SC-1', + 'desc': 'move 1 character backward over character with combining long solidus overlay', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foo̸^barbaz', + 'expected': 'fo^o̸barbaz' } + ] + }, + + { 'desc': 'sel.modify: move forward/backward/left/right in RTL text', + 'tests': [ + { 'id': 'SM:m.f.c_Pdir:rtl-1_SC-1', + 'desc': 'move caret forward 1 character in right-to-left text', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': '

                      foo b^ar baz

                      ', + 'expected': '

                      foo ba^r baz

                      ' }, + + { 'id': 'SM:m.b.c_Pdir:rtl-1_SC-1', + 'desc': 'move caret backward 1 character in right-to-left text', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': '

                      foo ba^r baz

                      ', + 'expected': '

                      foo b^ar baz

                      ' }, + + { 'id': 'SM:m.r.c_Pdir:rtl-1_SC-1', + 'desc': 'move caret 1 character to the right in LTR text within RTL context', + 'function': 'sel.modify("move", "right", "character");', + 'pad': '

                      foo b^ar baz

                      ', + 'expected': '

                      foo ba^r baz

                      ' }, + + { 'id': 'SM:m.l.c_Pdir:rtl-1_SC-1', + 'desc': 'move caret 1 character to the left in LTR text within RTL context', + 'function': 'sel.modify("move", "left", "character");', + 'pad': '

                      foo ba^r baz

                      ', + 'expected': '

                      foo b^ar baz

                      ' }, + + + { 'id': 'SM:m.f.c_TEXT:ar-1_SC-1', + 'desc': 'move caret forward 1 character in Arabic text', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'مرح^با العالم', + 'expected': 'مرحب^ا العالم' }, + + { 'id': 'SM:m.b.c_TEXT:ar-1_SC-1', + 'desc': 'move caret backward 1 character in Arabic text', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'مرح^با العالم', + 'expected': 'مر^حبا العالم' }, + + { 'id': 'SM:m.f.c_TEXT:he-1_SC-1', + 'desc': 'move caret forward 1 character in Hebrew text', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'של^ום עולם', + 'expected': 'שלו^ם עולם' }, + + { 'id': 'SM:m.b.c_TEXT:he-1_SC-1', + 'desc': 'move caret backward 1 character in Hebrew text', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'של^ום עולם', + 'expected': 'ש^לום עולם' }, + + + { 'id': 'SM:m.f.c_BDOdir:rtl-1_SC-1', + 'desc': 'move caret forward 1 character inside ', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'foo b^ar baz', + 'expected': 'foo ba^r baz' }, + + { 'id': 'SM:m.b.c_BDOdir:rtl-1_SC-1', + 'desc': 'move caret backward 1 character inside ', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'foo ba^r baz', + 'expected': 'foo b^ar baz' }, + + { 'id': 'SM:m.r.c_BDOdir:rtl-1_SC-1', + 'desc': 'move caret 1 character to the right inside ', + 'function': 'sel.modify("move", "right", "character");', + 'pad': 'foo ba^r baz', + 'expected': 'foo b^ar baz' }, + + { 'id': 'SM:m.l.c_BDOdir:rtl-1_SC-1', + 'desc': 'move caret 1 character to the left inside ', + 'function': 'sel.modify("move", "left", "character");', + 'pad': 'foo b^ar baz', + 'expected': 'foo ba^r baz' }, + + + { 'id': 'SM:m.f.c_TEXTrle-1_SC-rtl-1', + 'desc': 'move caret forward in RTL text within RLE-PDF marks', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'I said, "(RLE)‫car يعني سي^ارة‬(PDF)".', + 'expected': 'I said, "(RLE)‫car يعني سيا^رة‬(PDF)".' }, + + { 'id': 'SM:m.b.c_TEXTrle-1_SC-rtl-1', + 'desc': 'move caret backward in RTL text within RLE-PDF marks', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'I said, "(RLE)‫car يعني سي^ارة‬(PDF)".', + 'expected': 'I said, "(RLE)‫car يعني س^يارة‬(PDF)".' }, + + { 'id': 'SM:m.r.c_TEXTrle-1_SC-rtl-1', + 'desc': 'move caret 1 character to the right in RTL text within RLE-PDF marks', + 'function': 'sel.modify("move", "right", "character");', + 'pad': 'I said, "(RLE)‫car يعني سي^ارة‬(PDF)".', + 'expected': 'I said, "(RLE)‫car يعني س^يارة‬(PDF)".' }, + + { 'id': 'SM:m.l.c_TEXTrle-1_SC-rtl-1', + 'desc': 'move caret 1 character to the left in RTL text within RLE-PDF marks', + 'function': 'sel.modify("move", "left", "character");', + 'pad': 'I said, "(RLE)‫car يعني سي^ارة‬(PDF)".', + 'expected': 'I said, "(RLE)‫car يعني سيا^رة‬(PDF)".' }, + + { 'id': 'SM:m.f.c_TEXTrle-1_SC-ltr-1', + 'desc': 'move caret forward in LTR text within RLE-PDF marks', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'I said, "(RLE)‫c^ar يعني سيارة‬(PDF)".', + 'expected': 'I said, "(RLE)‫ca^r يعني سيارة‬(PDF)".' }, + + { 'id': 'SM:m.b.c_TEXTrle-1_SC-ltr-1', + 'desc': 'move caret backward in LTR text within RLE-PDF marks', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'I said, "(RLE)‫ca^r يعني سيارة‬(PDF)".', + 'expected': 'I said, "(RLE)‫c^ar يعني سيارة‬(PDF)".' }, + + { 'id': 'SM:m.r.c_TEXTrle-1_SC-ltr-1', + 'desc': 'move caret 1 character to the right in LTR text within RLE-PDF marks', + 'function': 'sel.modify("move", "right", "character");', + 'pad': 'I said, "(RLE)‫c^ar يعني سيارة‬(PDF)".', + 'expected': 'I said, "(RLE)‫ca^r يعني سيارة‬(PDF)".' }, + + { 'id': 'SM:m.l.c_TEXTrle-1_SC-ltr-1', + 'desc': 'move caret 1 character to the left in LTR text within RLE-PDF marks', + 'function': 'sel.modify("move", "left", "character");', + 'pad': 'I said, "(RLE)‫ca^r يعني سيارة‬(PDF)".', + 'expected': 'I said, "(RLE)‫c^ar يعني سيارة‬(PDF)".' }, + + + { 'id': 'SM:m.f.c_TEXTrlo-1_SC-rtl-1', + 'desc': 'move caret forward in RTL text within RLO-PDF marks', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'I said, "(RLO)‮car يعني سي^ارة‬(PDF)".', + 'expected': 'I said, "(RLO)‮car يعني سيا^رة‬(PDF)".' }, + + { 'id': 'SM:m.b.c_TEXTrlo-1_SC-rtl-1', + 'desc': 'move caret backward in RTL text within RLO-PDF marks', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'I said, "(RLO)‮car يعني سي^ارة‬(PDF)".', + 'expected': 'I said, "(RLO)‮car يعني س^يارة‬(PDF)".' }, + + { 'id': 'SM:m.r.c_TEXTrlo-1_SC-rtl-1', + 'desc': 'move caret 1 character to the right in RTL text within RLO-PDF marks', + 'function': 'sel.modify("move", "right", "character");', + 'pad': 'I said, "(RLO)‮car يعني سي^ارة‬(PDF)".', + 'expected': 'I said, "(RLO)‮car يعني س^يارة‬(PDF)".' }, + + { 'id': 'SM:m.l.c_TEXTrlo-1_SC-rtl-1', + 'desc': 'move caret 1 character to the left in RTL text within RLO-PDF marks', + 'function': 'sel.modify("move", "left", "character");', + 'pad': 'I said, "(RLO)‮car يعني سي^ارة‬(PDF)".', + 'expected': 'I said, "(RLO)‮car يعني سيا^رة‬(PDF)".' }, + + { 'id': 'SM:m.f.c_TEXTrlo-1_SC-ltr-1', + 'desc': 'move caret forward in Latin text within RLO-PDF marks', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'I said, "(RLO)‮c^ar يعني سيارة‬(PDF)".', + 'expected': 'I said, "(RLO)‮ca^r يعني سيارة‬(PDF)".' }, + + { 'id': 'SM:m.b.c_TEXTrlo-1_SC-ltr-1', + 'desc': 'move caret backward in Latin text within RLO-PDF marks', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'I said, "(RLO)‮ca^r يعني سيارة‬(PDF)".', + 'expected': 'I said, "(RLO)‮c^ar يعني سيارة‬(PDF)".' }, + + { 'id': 'SM:m.r.c_TEXTrlo-1_SC-ltr-1', + 'desc': 'move caret 1 character to the right in Latin text within RLO-PDF marks', + 'function': 'sel.modify("move", "right", "character");', + 'pad': 'I said, "(RLO)‮ca^r يعني سيارة‬(PDF)".', + 'expected': 'I said, "(RLO)‮c^ar يعني سيارة‬(PDF)".' }, + + { 'id': 'SM:m.l.c_TEXTrlo-1_SC-ltr-1', + 'desc': 'move caret 1 character to the left in Latin text within RLO-PDF marks', + 'function': 'sel.modify("move", "left", "character");', + 'pad': 'I said, "(RLO)‮c^ar يعني سيارة‬(PDF)".', + 'expected': 'I said, "(RLO)‮ca^r يعني سيارة‬(PDF)".' }, + + + { 'id': 'SM:m.f.c_TEXTrlm-1_SC-1', + 'desc': 'move caret forward in RTL text within neutral characters followed by RLM', + 'function': 'sel.modify("move", "forward", "character");', + 'pad': 'I said, "يعني سيارة!^?!‏(RLM)".', + 'expected': 'I said, "يعني سيارة!?^!‏(RLM)".' }, + + { 'id': 'SM:m.b.c_TEXTrlm-1_SC-1', + 'desc': 'move caret backward in RTL text within neutral characters followed by RLM', + 'function': 'sel.modify("move", "backward", "character");', + 'pad': 'I said, "يعني سيارة!?^!‏(RLM)".', + 'expected': 'I said, "يعني سيارة!^?!‏(RLM)".' }, + + { 'id': 'SM:m.r.c_TEXTrlm-1_SC-1', + 'desc': 'move caret 1 character to the right in RTL text within neutral characters followed by RLM', + 'function': 'sel.modify("move", "right", "character");', + 'pad': 'I said, "يعني سيارة!?^!‏(RLM)".', + 'expected': 'I said, "يعني سيارة!^?!‏(RLM)".' }, + + { 'id': 'SM:m.l.c_TEXTrlm-1_SC-1', + 'desc': 'move caret 1 character to the left in RTL text within neutral characters followed by RLM', + 'function': 'sel.modify("move", "left", "character");', + 'pad': 'I said, "يعني سيارة!^?!‏(RLM)".', + 'expected': 'I said, "يعني سيارة!?^!‏(RLM)".' } + ] + }, + + { 'desc': 'sel.modify: move forward/backward over words in Japanese text', + 'tests': [ + { 'id': 'SM:m.f.w_TEXT-jp_SC-1', + 'desc': 'move caret forward 1 word in Japanese text (adjective)', + 'function': 'sel.modify("move", "forward", "word");', + 'pad': '^面白い例文をテストしましょう。', + 'expected': '面白い^例文をテストしましょう。' }, + + { 'id': 'SM:m.f.w_TEXT-jp_SC-2', + 'desc': 'move caret forward 1 word in Japanese text (in the middle of a word)', + 'function': 'sel.modify("move", "forward", "word");', + 'pad': '面^白い例文をテストしましょう。', + 'expected': '面白い^例文をテストしましょう。' }, + + { 'id': 'SM:m.f.w_TEXT-jp_SC-3', + 'desc': 'move caret forward 1 word in Japanese text (noun)', + 'function': 'sel.modify("move", "forward", "word");', + 'pad': '面白い^例文をテストしましょう。', + 'expected': [ '面白い例文^をテストしましょう。', + '面白い例文を^テストしましょう。' ] }, + + { 'id': 'SM:m.f.w_TEXT-jp_SC-4', + 'desc': 'move caret forward 1 word in Japanese text (Katakana)', + 'function': 'sel.modify("move", "forward", "word");', + 'pad': '面白い例文を^テストしましょう。', + 'expected': '面白い例文をテスト^しましょう。' }, + + { 'id': 'SM:m.f.w_TEXT-jp_SC-5', + 'desc': 'move caret forward 1 word in Japanese text (verb)', + 'function': 'sel.modify("move", "forward", "word");', + 'pad': '面白い例文をテスト^しましょう。', + 'expected': '面白い例文をテストしましょう^。' } + ] + }, + + { 'desc': 'sel.modify: move forward/backward over words in Thai text', + 'tests': [ + { 'id': 'SM:m.f.w_TEXT-th_SC-1', + 'desc': 'move caret forward 1 word in Thai text', + 'function': 'sel.modify("move", "forward", "word");', + 'pad': '^ทดสอบการทำงาน', + 'expected': 'ทดสอบ^การทำงาน' }, + + { 'id': 'SM:m.f.w_TEXT-th_SC-2', + 'desc': 'move caret forward 1 word in Thai text (mid-word)', + 'function': 'sel.modify("move", "forward", "word");', + 'pad': 'ทดสอบก^ารทำงาน', + 'expected': 'ทดสอบการ^ทำงาน' }, + + { 'id': 'SM:m.b.w_TEXT-th_SC-1', + 'desc': 'move caret backward 1 word in Thai text', + 'function': 'sel.modify("move", "backward", "word");', + 'pad': 'ทดสอบการ^ทำงาน', + 'expected': 'ทดสอบ^การทำงาน' }, + + { 'id': 'SM:m.b.w_TEXT-th_SC-2', + 'desc': 'move caret backward 1 word in Thai text (mid-word)', + 'function': 'sel.modify("move", "backward", "word");', + 'pad': 'ทดสอบการทำงา^น', + 'expected': [ 'ทดสอบการ^ทำงาน', + 'ทดสอบการทำ^งาน' ] }, + ] + }, + + { 'desc': 'sel.modify: extend selection forward', + 'tests': [ + { 'id': 'SM:e.f.c_TEXT-1_SC-1', + 'desc': 'extend selection 1 character forward', + 'function': 'sel.modify("extend", "forward", "character");', + 'pad': 'foo ^bar baz', + 'expected': 'foo [b]ar baz' }, + + { 'id': 'SM:e.f.c_TEXT-1_SI-1', + 'desc': 'extend selection 1 character forward', + 'function': 'sel.modify("extend", "forward", "character");', + 'pad': 'foo [b]ar baz', + 'expected': 'foo [ba]r baz' }, + + { 'id': 'SM:e.f.w_TEXT-1_SC-1', + 'desc': 'extend selection 1 word forward', + 'function': 'sel.modify("extend", "forward", "word");', + 'pad': 'foo ^bar baz', + 'expected': 'foo [bar] baz' }, + + { 'id': 'SM:e.f.w_TEXT-1_SI-1', + 'desc': 'extend selection 1 word forward', + 'function': 'sel.modify("extend", "forward", "word");', + 'pad': 'foo [b]ar baz', + 'expected': 'foo [bar] baz' }, + + { 'id': 'SM:e.f.w_TEXT-1_SI-2', + 'desc': 'extend selection 1 word forward', + 'function': 'sel.modify("extend", "forward", "word");', + 'pad': 'foo [bar] baz', + 'expected': 'foo [bar baz]' } + ] + }, + + { 'desc': 'sel.modify: extend selection backward, shrinking it', + 'tests': [ + { 'id': 'SM:e.b.c_TEXT-1_SI-2', + 'desc': 'extend selection 1 character backward', + 'function': 'sel.modify("extend", "backward", "character");', + 'pad': 'foo [bar] baz', + 'expected': 'foo [ba]r baz' }, + + { 'id': 'SM:e.b.c_TEXT-1_SI-1', + 'desc': 'extend selection 1 character backward', + 'function': 'sel.modify("extend", "backward", "character");', + 'pad': 'foo [b]ar baz', + 'expected': 'foo ^bar baz' }, + + { 'id': 'SM:e.b.w_TEXT-1_SI-3', + 'desc': 'extend selection 1 word backward', + 'function': 'sel.modify("extend", "backward", "word");', + 'pad': 'foo [bar baz]', + 'expected': 'foo [bar] baz' }, + + { 'id': 'SM:e.b.w_TEXT-1_SI-2', + 'desc': 'extend selection 1 word backward', + 'function': 'sel.modify("extend", "backward", "word");', + 'pad': 'foo [bar] baz', + 'expected': 'foo ^bar baz' }, + + { 'id': 'SM:e.b.w_TEXT-1_SI-4', + 'desc': 'extend selection 1 word backward', + 'function': 'sel.modify("extend", "backward", "word");', + 'pad': 'foo b[ar baz]', + 'expected': 'foo b[ar] baz' }, + + { 'id': 'SM:e.b.w_TEXT-1_SI-5', + 'desc': 'extend selection 1 word backward', + 'function': 'sel.modify("extend", "backward", "word");', + 'pad': 'foo b[ar] baz', + 'expected': 'foo b^ar baz' } + ] + }, + + { 'desc': 'sel.modify: extend selection backward, creating or extending a reverse selections', + 'tests': [ + { 'id': 'SM:e.b.c_TEXT-1_SC-1', + 'desc': 'extend selection 1 character backward', + 'function': 'sel.modify("extend", "backward", "character");', + 'pad': 'foo b^ar baz', + 'expected': 'foo ]b[ar baz' }, + + { 'id': 'SM:e.b.c_TEXT-1_SIR-1', + 'desc': 'extend selection 1 character backward', + 'function': 'sel.modify("extend", "backward", "character");', + 'pad': 'foo b]a[r baz', + 'expected': 'foo ]ba[r baz' }, + + { 'id': 'SM:e.b.w_TEXT-1_SIR-1', + 'desc': 'extend selection 1 word backward', + 'function': 'sel.modify("extend", "backward", "word");', + 'pad': 'foo b]a[r baz', + 'expected': 'foo ]ba[r baz' }, + + { 'id': 'SM:e.b.w_TEXT-1_SIR-2', + 'desc': 'extend selection 1 word backward', + 'function': 'sel.modify("extend", "backward", "word");', + 'pad': 'foo ]ba[r baz', + 'expected': ']foo ba[r baz' } + ] + }, + + { 'desc': 'sel.modify: extend selection forward, shrinking a reverse selections', + 'tests': [ + { 'id': 'SM:e.f.c_TEXT-1_SIR-1', + 'desc': 'extend selection 1 character forward', + 'function': 'sel.modify("extend", "forward", "character");', + 'pad': 'foo b]a[r baz', + 'expected': 'foo ba^r baz' }, + + { 'id': 'SM:e.f.c_TEXT-1_SIR-2', + 'desc': 'extend selection 1 character forward', + 'function': 'sel.modify("extend", "forward", "character");', + 'pad': 'foo ]ba[r baz', + 'expected': 'foo b]a[r baz' }, + + { 'id': 'SM:e.f.w_TEXT-1_SIR-1', + 'desc': 'extend selection 1 word forward', + 'function': 'sel.modify("extend", "forward", "word");', + 'pad': 'foo ]ba[r baz', + 'expected': 'foo ba^r baz' }, + + { 'id': 'SM:e.f.w_TEXT-1_SIR-3', + 'desc': 'extend selection 1 word forward', + 'function': 'sel.modify("extend", "forward", "word");', + 'pad': ']foo ba[r baz', + 'expected': 'foo ]ba[r baz' } + ] + }, + + { 'desc': 'sel.modify: extend selection forward to line boundary', + 'tests': [ + { 'id': 'SM:e.f.lb_BR.BR-1_SC-1', + 'desc': 'extend selection forward to line boundary', + 'function': 'sel.modify("extend", "forward", "lineboundary");', + 'pad': 'fo^o
                      bar
                      baz', + 'expected': 'fo[o]
                      bar
                      baz' }, + + { 'id': 'SM:e.f.lb_BR.BR-1_SI-1', + 'desc': 'extend selection forward to next line boundary', + 'function': 'sel.modify("extend", "forward", "lineboundary");', + 'pad': 'fo[o]
                      bar
                      baz', + 'expected': 'fo[o
                      bar]
                      baz' }, + + { 'id': 'SM:e.f.lb_BR.BR-1_SM-1', + 'desc': 'extend selection forward to line boundary', + 'function': 'sel.modify("extend", "forward", "lineboundary");', + 'pad': 'fo[o
                      b]ar
                      baz', + 'expected': 'fo[o
                      bar]
                      baz' }, + + { 'id': 'SM:e.f.lb_P.P.P-1_SC-1', + 'desc': 'extend selection forward to line boundary', + 'function': 'sel.modify("extend", "forward", "lineboundary");', + 'pad': '

                      fo^o

                      bar

                      baz

                      ', + 'expected': '

                      fo[o]

                      bar

                      baz

                      ' }, + + { 'id': 'SM:e.f.lb_P.P.P-1_SI-1', + 'desc': 'extend selection forward to next line boundary', + 'function': 'sel.modify("extend", "forward", "lineboundary");', + 'pad': '

                      fo[o]

                      bar

                      baz

                      ', + 'expected': '

                      fo[o

                      bar]

                      baz

                      ' }, + + { 'id': 'SM:e.f.lb_P.P.P-1_SM-1', + 'desc': 'extend selection forward to line boundary', + 'function': 'sel.modify("extend", "forward", "lineboundary");', + 'pad': '

                      fo[o

                      b]ar

                      baz

                      ', + 'expected': '

                      fo[o

                      bar]

                      baz

                      ' }, + + { 'id': 'SM:e.f.lb_P.P.P-1_SMR-1', + 'desc': 'extend selection forward to line boundary', + 'function': 'sel.modify("extend", "forward", "lineboundary");', + 'pad': '

                      foo

                      b]a[r

                      baz

                      ', + 'expected': '

                      foo

                      ba[r]

                      baz

                      ' } + ] + }, + + { 'desc': 'sel.modify: extend selection backward to line boundary', + 'tests': [ + { 'id': 'SM:e.b.lb_BR.BR-1_SC-2', + 'desc': 'extend selection backward to line boundary', + 'function': 'sel.modify("extend", "backward", "lineboundary");', + 'pad': 'foo
                      bar
                      b^az', + 'expected': 'foo
                      bar
                      ]b[az' }, + + { 'id': 'SM:e.b.lb_BR.BR-1_SIR-2', + 'desc': 'extend selection backward to previous line boundary', + 'function': 'sel.modify("extend", "backward", "lineboundary");', + 'pad': 'foo
                      bar
                      ]b[az', + 'expected': 'foo
                      ]bar
                      b[az' }, + + { 'id': 'SM:e.b.lb_BR.BR-1_SMR-2', + 'desc': 'extend selection backward to line boundary', + 'function': 'sel.modify("extend", "backward", "lineboundary");', + 'pad': 'foo
                      ba]r
                      b[az', + 'expected': 'foo
                      ]bar
                      b[az' }, + + { 'id': 'SM:e.b.lb_P.P.P-1_SC-2', + 'desc': 'extend selection backward to line boundary', + 'function': 'sel.modify("extend", "backward", "lineboundary");', + 'pad': '

                      foo

                      bar

                      b^az

                      ', + 'expected': '

                      foo

                      bar

                      ]b[az

                      ' }, + + { 'id': 'SM:e.b.lb_P.P.P-1_SIR-2', + 'desc': 'extend selection backward to previous line boundary', + 'function': 'sel.modify("extend", "backward", "lineboundary");', + 'pad': '

                      foo

                      bar

                      ]b[az

                      ', + 'expected': '

                      foo

                      ]bar

                      b[az

                      ' }, + + { 'id': 'SM:e.b.lb_P.P.P-1_SMR-2', + 'desc': 'extend selection backward to line boundary', + 'function': 'sel.modify("extend", "backward", "lineboundary");', + 'pad': '

                      foo

                      ba]r

                      b[az

                      ', + 'expected': '

                      foo

                      ]bar

                      b[az

                      ' }, + + { 'id': 'SM:e.b.lb_P.P.P-1_SM-2', + 'desc': 'extend selection backward to line boundary', + 'function': 'sel.modify("extend", "backward", "lineboundary");', + 'pad': '

                      foo

                      b[a]r

                      baz

                      ', + 'expected': '

                      foo

                      ]b[ar

                      baz

                      ' } + ] + }, + + { 'desc': 'sel.modify: extend selection forward to next line (NOTE: use identical text in every line!)', + 'tests': [ + { 'id': 'SM:e.f.l_BR.BR-2_SC-1', + 'desc': 'extend selection forward to next line', + 'function': 'sel.modify("extend", "forward", "line");', + 'pad': 'fo^o
                      foo
                      foo', + 'expected': 'fo[o
                      fo]o
                      foo' }, + + { 'id': 'SM:e.f.l_BR.BR-2_SI-1', + 'desc': 'extend selection forward to next line', + 'function': 'sel.modify("extend", "forward", "line");', + 'pad': 'fo[o]
                      foo
                      foo', + 'expected': 'fo[o
                      foo]
                      foo' }, + + { 'id': 'SM:e.f.l_BR.BR-2_SM-1', + 'desc': 'extend selection forward to next line', + 'function': 'sel.modify("extend", "forward", "line");', + 'pad': 'fo[o
                      f]oo
                      foo', + 'expected': 'fo[o
                      foo
                      f]oo' }, + + { 'id': 'SM:e.f.l_P.P-1_SC-1', + 'desc': 'extend selection forward to next line over paragraph boundaries', + 'function': 'sel.modify("extend", "forward", "line");', + 'pad': '

                      foo^bar

                      foobar

                      ', + 'expected': '

                      foo[bar

                      foo]bar

                      ' }, + + { 'id': 'SM:e.f.l_P.P-1_SMR-1', + 'desc': 'extend selection forward to next line over paragraph boundaries', + 'function': 'sel.modify("extend", "forward", "line");', + 'pad': '

                      fo]obar

                      foob[ar

                      ', + 'expected': '

                      foobar

                      fo]ob[ar

                      ' } + ] + }, + + { 'desc': 'sel.modify: extend selection backward to previous line (NOTE: use identical text in every line!)', + 'tests': [ + { 'id': 'SM:e.b.l_BR.BR-2_SC-2', + 'desc': 'extend selection backward to previous line', + 'function': 'sel.modify("extend", "backward", "line");', + 'pad': 'foo
                      foo
                      f^oo', + 'expected': 'foo
                      f]oo
                      f[oo' }, + + { 'id': 'SM:e.b.l_BR.BR-2_SIR-2', + 'desc': 'extend selection backward to previous line', + 'function': 'sel.modify("extend", "backward", "line");', + 'pad': 'foo
                      foo
                      ]f[oo', + 'expected': 'foo
                      ]foo
                      f[oo' }, + + { 'id': 'SM:e.b.l_BR.BR-2_SMR-2', + 'desc': 'extend selection backward to previous line', + 'function': 'sel.modify("extend", "backward", "line");', + 'pad': 'foo
                      fo]o
                      f[oo', + 'expected': 'fo]o
                      foo
                      f[oo' }, + + { 'id': 'SM:e.b.l_P.P-1_SC-2', + 'desc': 'extend selection backward to next line over paragraph boundaries', + 'function': 'sel.modify("extend", "backward", "line");', + 'pad': '

                      foobar

                      foo^bar

                      ', + 'expected': '

                      foo]bar

                      foo[bar

                      ' }, + + { 'id': 'SM:e.b.l_P.P-1_SM-1', + 'desc': 'extend selection backward to next line over paragraph boundaries', + 'function': 'sel.modify("extend", "backward", "line");', + 'pad': '

                      fo[obar

                      foob]ar

                      ', + 'expected': '

                      fo[ob]ar

                      foobar

                      ' } + ] + }, + + { 'desc': 'sel.selectAllChildren()', + 'function': 'sel.selectAllChildren(doc.getElementById("div"));', + 'tests': [ + { 'id': 'SAC:div_DIV-1_SC-1', + 'desc': 'selectAllChildren(
                      )', + 'pad': 'foo
                      bar ba^z
                      qoz', + 'expected': [ 'foo
                      [bar baz}
                      qoz', + 'foo
                      {bar baz}
                      qoz' ] }, + ] + } + ] +} + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapply.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapply.py new file mode 100644 index 0000000000..adad65617e --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapply.py @@ -0,0 +1,462 @@ + +UNAPPLY_TESTS = { + 'id': 'U', + 'caption': 'Unapply Existing Formatting Tests', + 'checkAttrs': True, + 'checkStyle': True, + 'styleWithCSS': False, + 'expected': 'foo[bar]baz', + + 'RFC': [ + { 'desc': '', + 'command': '', + 'tests': [ + ] + }, + + { 'desc': 'remove link', + 'command': 'unlink', + 'tests': [ + { 'id': 'UNLINK_A-1_SO', + 'desc': 'unlink wrapped element', + 'pad': 'foo[bar]baz' }, + + { 'id': 'UNLINK_A-1_SW', + 'desc': 'unlink element where the selection wraps the full content', + 'pad': 'foo[bar]baz' }, + + { 'id': 'UNLINK_An:a.h:id-1_SO', + 'desc': 'unlink wrapped element that has a name and href attribute', + 'pad': 'foo[bar]baz' }, + + { 'id': 'UNLINK_A-2_SO', + 'desc': 'unlink contained element', + 'pad': 'foo[bar]baz' }, + + { 'id': 'UNLINK_A2-1_SO', + 'desc': 'unlink 2 contained elements', + 'pad': 'foo[bar]baz' } + ] + } + ], + + 'Proposed': [ + { 'desc': '', + 'command': '', + 'tests': [ + ] + }, + + { 'desc': 'remove bold', + 'command': 'bold', + 'tests': [ + { 'id': 'B_B-1_SW', + 'rte1-id': 'u-bold-0', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_B-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_B-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_B-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_STRONG-1_SW', + 'rte1-id': 'u-bold-1', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_STRONG-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_STRONG-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_STRONG-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_SPANs:fw:b-1_SW', + 'rte1-id': 'u-bold-2', + 'desc': 'Selection within tags; remove "font-weight: bold"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_SPANs:fw:b-1_SO', + 'desc': 'Selection outside of tags; remove "font-weight: bold"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_SPANs:fw:b-1_SL', + 'desc': 'Selection oblique left; remove "font-weight: bold"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_SPANs:fw:b-1_SR', + 'desc': 'Selection oblique right; remove "font-weight: bold"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_B-P3-1_SO12', + 'desc': 'Unbolding multiple paragraphs in inside bolded content with content-model violation', + 'pad': '{

                      foo

                      bar

                      }

                      baz

                      ', + 'expected': [ '

                      [foo

                      bar]

                      baz

                      ', + '

                      [foo

                      bar]

                      baz

                      ' ] }, + + { 'id': 'B_B-P-I..P-1_SO-I', + 'desc': 'Unbolding italicized content inside bolded content with content-model violation', + 'pad': '

                      foo[bar]

                      baz

                      ', + 'expected': [ '

                      foo[bar]

                      baz

                      ', + '

                      foo

                      [bar]

                      baz

                      ' ] }, + + { 'id': 'B_B-2_SL', + 'desc': 'Remove partially covered bold, selection extends left', + 'pad': 'foo [bar baz] qoz quz sic', + 'expected': 'foo [bar baz] qoz quz sic' }, + + { 'id': 'B_B-2_SR', + 'desc': 'Remove partially covered bold, selection extends right', + 'pad': 'foo bar baz [qoz quz] sic', + 'expected': 'foo bar baz [qoz quz] sic' } + ] + }, + + { 'desc': 'remove italic', + 'command': 'italic', + 'tests': [ + { 'id': 'I_I-1_SW', + 'rte1-id': 'u-italic-0', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_I-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_I-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_I-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_EM-1_SW', + 'rte1-id': 'u-italic-1', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_EM-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_EM-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_EM-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_SPANs:fs:i-1_SW', + 'rte1-id': 'u-italic-2', + 'desc': 'Selection within tags; remove "font-style: italic"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_SPANs:fs:i-1_SO', + 'desc': 'Selection outside of tags; Italicize "font-style: italic"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_SPANs:fs:i-1_SL', + 'desc': 'Selection oblique left; Italicize "font-style: italic"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_SPANs:fs:i-1_SR', + 'desc': 'Selection oblique right; Italicize "font-style: italic"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_I-P3-1_SO2', + 'desc': 'Unitalicize content with content-model violation', + 'pad': '

                      foo

                      {

                      bar

                      }

                      baz

                      ', + 'expected': [ '

                      foo

                      [bar]

                      baz

                      ', + '

                      foo

                      [bar]

                      baz

                      ' ] } + ] + }, + + { 'desc': 'remove underline', + 'command': 'underline', + 'tests': [ + { 'id': 'U_U-1_SW', + 'rte1-id': 'u-underline-0', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_U-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_U-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_U-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_SPANs:td:u-1_SW', + 'rte1-id': 'u-underline-1', + 'desc': 'Selection within tags; remove "text-decoration: underline"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_SPANs:td:u-1_SO', + 'desc': 'Selection outside of tags; remove "text-decoration: underline"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_SPANs:td:u-1_SL', + 'desc': 'Selection oblique left; remove "text-decoration: underline"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_SPANs:td:u-1_SR', + 'desc': 'Selection oblique right; remove "text-decoration: underline"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_U-S-1_SO', + 'desc': 'Removing underline from underlined content with striked content', + 'pad': 'foo[barbazquoz]', + 'expected': 'foo[barbazquoz]' }, + + { 'id': 'U_U-S-2_SI', + 'desc': 'Removing underline from striked content inside underlined content', + 'pad': 'foo[bar]bazquoz', + 'expected': 'foo[bar]bazquoz' }, + + { 'id': 'U_U-P3-1_SO', + 'desc': 'Removing underline from underlined content with content-model violation', + 'pad': '

                      foo

                      {

                      bar

                      }

                      baz

                      ', + 'expected': [ '

                      foo

                      [bar]

                      baz

                      ', + '

                      foo

                      [bar]

                      baz

                      ' ] } + ] + }, + + { 'desc': 'remove strike through', + 'command': 'strikethrough', + 'tests': [ + { 'id': 'S_S-1_SW', + 'rte1-id': 'u-strikethrough-1', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_S-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_S-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_S-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_STRIKE-1_SW', + 'rte1-id': 'u-strikethrough-0', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_STRIKE-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_STRIKE-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_STRIKE-2_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_DEL-1_SW', + 'rte1-id': 'u-strikethrough-2', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_SPANs:td:lt-1_SW', + 'rte1-id': 'u-strikethrough-3', + 'desc': 'Selection within tags; remove "text-decoration:line-through"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_SPANs:td:lt-1_SO', + 'desc': 'Selection outside of tags; Italicize "text-decoration:line-through"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_SPANs:td:lt-1_SL', + 'desc': 'Selection oblique left; Italicize "text-decoration:line-through"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_SPANs:td:lt-1_SR', + 'desc': 'Selection oblique right; Italicize "text-decoration:line-through"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_S-U-1_SI', + 'desc': 'Removing underline from underlined content inside striked content', + 'pad': 'foo[bar]bazquoz', + 'expected': 'foo[bar]bazquoz' }, + + { 'id': 'S_U-S-1_SI', + 'desc': 'Removing underline from striked content inside underlined content', + 'pad': 'foo[bar]bazquoz', + 'expected': 'foo[bar]bazquoz' } + ] + }, + + { 'desc': 'remove subscript', + 'command': 'subscript', + 'tests': [ + { 'id': 'SUB_SUB-1_SW', + 'rte1-id': 'u-subscript-0', + 'desc': 'remove subscript', + 'pad': 'foo[bar]baz' }, + + { 'id': 'SUB_SPANs:va:sub-1_SW', + 'rte1-id': 'u-subscript-1', + 'desc': 'remove subscript', + 'pad': 'foo[bar]baz' } + ] + }, + + { 'desc': 'remove superscript', + 'command': 'superscript', + 'tests': [ + { 'id': 'SUP_SUP-1_SW', + 'rte1-id': 'u-superscript-0', + 'desc': 'remove superscript', + 'pad': 'foo[bar]baz' }, + + { 'id': 'SUP_SPANs:va:super-1_SW', + 'rte1-id': 'u-superscript-1', + 'desc': 'remove superscript', + 'pad': 'foo[bar]baz' } + ] + }, + + { 'desc': 'remove links', + 'command': 'unlink', + 'tests': [ + { 'id': 'UNLINK_Ahref:url-1_SW', + 'rte1-id': 'u-unlink-0', + 'desc': 'unlink an element with href attribute where all children are selected', + 'pad': 'foo[bar]baz' }, + + { 'id': 'UNLINK_A-1_SC', + 'desc': 'unlink an element that contains the collapsed selection', + 'pad': 'fooba^rbaz', + 'expected': 'fooba^rbaz' }, + + { 'id': 'UNLINK_A-1_SI', + 'desc': 'unlink an element that contains the whole selection', + 'pad': 'foob[a]rbaz', + 'expected': 'foob[a]rbaz' }, + + { 'id': 'UNLINK_A-2_SL', + 'desc': 'unlink a partially contained element', + 'pad': 'foo[bar]baz' }, + + { 'id': 'UNLINK_A-3_SR', + 'desc': 'unlink a partially contained element', + 'pad': 'foo[bar]baz' }, + + { 'id': 'UNLINK_As:d:b.fw:b-1_SW', + 'desc': 'unlink, preserving styles', + 'pad': 'foo[bar]baz', + 'expected': 'foo[bar]baz' }, + + { 'id': 'UNLINK_A-IMG-1_SO', + 'desc': 'unlink a linked image at the start of the content', + 'pad': '{abc]', + 'expected': '{abc]' } + ] + }, + + { 'desc': 'outdent', + 'command': 'outdent', + 'tests': [ + { 'id': 'OUTDENT_BQ-1_SW', + 'rte1-id': 'u-outdent-0', + 'desc': 'outdent (remove) a
                      ', + 'pad': 'foo
                      [bar]
                      baz', + 'expected': [ 'foo

                      [bar]

                      baz', + 'foo
                      [bar]
                      baz' ], + 'accept': 'foo
                      [bar]
                      baz' }, + + { 'id': 'OUTDENT_BQ.wibq.s:m:00040.b:n.p:0-1_SW', + 'rte1-id': 'u-outdent-1', + 'desc': 'outdent (remove) a styled
                      ', + 'pad': 'foo
                      [bar]
                      baz', + 'expected': [ 'foo

                      [bar]

                      baz', + 'foo
                      [bar]
                      baz' ], + 'accept': 'foo
                      [bar]
                      baz' }, + + { 'id': 'OUTDENT_OL-LI-1_SW', + 'rte1-id': 'u-outdent-3', + 'desc': 'outdent (remove) an ordered list', + 'pad': 'foo
                      1. [bar]
                      baz', + 'expected': [ 'foo

                      [bar]

                      baz', + 'foo
                      [bar]
                      baz' ], + 'accept': 'foo
                      [bar]
                      baz' }, + + { 'id': 'OUTDENT_UL-LI-1_SW', + 'rte1-id': 'u-outdent-2', + 'desc': 'outdent (remove) an unordered list', + 'pad': 'foo
                      • [bar]
                      baz', + 'expected': [ 'foo

                      [bar]

                      baz', + 'foo
                      [bar]
                      baz' ], + 'accept': 'foo
                      [bar]
                      baz' }, + + { 'id': 'OUTDENT_DIV-1_SW', + 'rte1-id': 'u-outdent-4', + 'desc': 'outdent (remove) a styled
                      with margin', + 'pad': 'foo
                      [bar]
                      baz', + 'expected': [ 'foo

                      [bar]

                      baz', + 'foo
                      [bar]
                      baz' ], + 'accept': 'foo
                      [bar]
                      baz' } + ] + }, + + { 'desc': 'remove all formatting', + 'command': 'removeformat', + 'tests': [ + { 'id': 'REMOVEFORMAT_B-1_SW', + 'rte1-id': 'u-removeformat-0', + 'desc': 'remove a tag using "removeformat"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'REMOVEFORMAT_Ahref:url-1_SW', + 'rte1-id': 'u-removeformat-0', + 'desc': 'remove a link using "removeformat"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW', + 'rte1-id': 'u-removeformat-2', + 'desc': 'remove a table using "removeformat"', + 'pad': 'foo
                      [bar]
                      baz', + 'expected': [ 'foo

                      [bar]

                      baz', + 'foo
                      [bar]
                      baz' ], + 'accept': 'foo
                      [bar]
                      baz' } + ] + }, + + { 'desc': 'remove bookmark', + 'command': 'unbookmark', + 'tests': [ + { 'id': 'UNBOOKMARK_An:name-1_SW', + 'rte1-id': 'u-unbookmark-0', + 'desc': 'unlink a bookmark (a named element) where all children are selected', + 'pad': 'foo[bar]baz' } + ] + } + ] +} diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapplyCSS.py b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapplyCSS.py new file mode 100644 index 0000000000..6f934a0f02 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/unapplyCSS.py @@ -0,0 +1,226 @@ + +UNAPPLY_TESTS_CSS = { + 'id': 'UC', + 'caption': 'Unapply Existing Formatting Tests, using styleWithCSS', + 'checkAttrs': True, + 'checkStyle': True, + 'styleWithCSS': True, + 'expected': 'foo[bar]baz', + + 'Proposed': [ + { 'desc': '', + 'id': '', + 'command': '', + 'tests': [ + ] + }, + + { 'desc': 'remove bold', + 'command': 'bold', + 'tests': [ + { 'id': 'B_B-1_SW', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_B-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_B-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_B-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_STRONG-1_SW', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_STRONG-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_STRONG-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_STRONG-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_SPANs:fw:b-1_SW', + 'desc': 'Selection within tags; remove "font-weight: bold"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_SPANs:fw:b-1_SO', + 'desc': 'Selection outside of tags; remove "font-weight: bold"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_SPANs:fw:b-1_SL', + 'desc': 'Selection oblique left; remove "font-weight: bold"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'B_SPANs:fw:b-1_SR', + 'desc': 'Selection oblique right; remove "font-weight: bold"', + 'pad': 'foo[bar]baz' } + ] + }, + + { 'desc': 'remove italic', + 'command': 'italic', + 'tests': [ + { 'id': 'I_I-1_SW', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_I-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_I-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_I-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_EM-1_SW', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_EM-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_EM-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_EM-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_SPANs:fs:i-1_SW', + 'desc': 'Selection within tags; remove "font-style: italic"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_SPANs:fs:i-1_SO', + 'desc': 'Selection outside of tags; Italicize "font-style: italic"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_SPANs:fs:i-1_SL', + 'desc': 'Selection oblique left; Italicize "font-style: italic"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'I_SPANs:fs:i-1_SR', + 'desc': 'Selection oblique right; Italicize "font-style: italic"', + 'pad': 'foo[bar]baz' } + ] + }, + + { 'desc': 'remove underline', + 'command': 'underline', + 'tests': [ + { 'id': 'U_U-1_SW', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_U-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_U-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_U-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_SPANs:td:u-1_SW', + 'desc': 'Selection within tags; remove "text-decoration: underline"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_SPANs:td:u-1_SO', + 'desc': 'Selection outside of tags; remove "text-decoration: underline"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_SPANs:td:u-1_SL', + 'desc': 'Selection oblique left; remove "text-decoration: underline"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'U_SPANs:td:u-1_SR', + 'desc': 'Selection oblique right; remove "text-decoration: underline"', + 'pad': 'foo[bar]baz' } + ] + }, + + { 'desc': 'remove strike-through', + 'command': 'strikethrough', + 'tests': [ + { 'id': 'S_S-1_SW', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_S-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_S-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_S-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_STRIKE-1_SW', + 'desc': 'Selection within tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_STRIKE-1_SO', + 'desc': 'Selection outside of tags; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_STRIKE-1_SL', + 'desc': 'Selection oblique left; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_STRIKE-1_SR', + 'desc': 'Selection oblique right; remove tags', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_SPANs:td:lt-1_SW', + 'desc': 'Selection within tags; remove "text-decoration:line-through"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_SPANs:td:lt-1_SO', + 'desc': 'Selection outside of tags; Italicize "text-decoration:line-through"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_SPANs:td:lt-1_SL', + 'desc': 'Selection oblique left; Italicize "text-decoration:line-through"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_SPANs:td:lt-1_SR', + 'desc': 'Selection oblique right; Italicize "text-decoration:line-through"', + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_SPANc:s-1_SW', + 'desc': 'Unapply "strike-through" on interited CSS style', + 'checkClass': True, + 'pad': 'foo[bar]baz' }, + + { 'id': 'S_SPANc:s-2_SI', + 'desc': 'Unapply "strike-through" on interited CSS style', + 'pad': 'foo[bar]baz', + 'checkClass': True, + 'expected': 'foo[bar]baz' } + ] + } + ] +} + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/unittestexample.html b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/unittestexample.html new file mode 100644 index 0000000000..4e27b05540 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/unittestexample.html @@ -0,0 +1,103 @@ + + + + + + + Rich Text 2 Unit Test Example + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/editor/libeditor/tests/browserscope/lib/richtext2/update_from_upstream b/editor/libeditor/tests/browserscope/lib/richtext2/update_from_upstream new file mode 100644 index 0000000000..baeb767454 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/update_from_upstream @@ -0,0 +1,19 @@ +#!/bin/sh + +set -x + +if test -d richtext2; then + rm -drf richtext2; +fi + +svn checkout http://browserscope.googlecode.com/svn/trunk/categories/richtext2 richtext2 | tail -1 | sed 's/[^0-9]//g' > current_revision + +find richtext2 -type d -name .svn -exec rm -drf \{\} \; 2> /dev/null + +# Remove test_set.py and other similarly named files because they confuse our mochitest runner +find richtext2 =type f -name test_\* -exec rm -rf \{\} \; 2> /dev/null + +hg add current_revision richtext2 + +hg stat . + diff --git a/editor/libeditor/tests/browserscope/mochitest.ini b/editor/libeditor/tests/browserscope/mochitest.ini new file mode 100644 index 0000000000..2f198fa853 --- /dev/null +++ b/editor/libeditor/tests/browserscope/mochitest.ini @@ -0,0 +1,59 @@ +[default] +support-files = + lib/richtext2/current_revision + lib/richtext2/richtext2/common.py + lib/richtext2/richtext2/unittestexample.html + lib/richtext2/richtext2/static/editable-dM.html + lib/richtext2/richtext2/static/editable.css + lib/richtext2/richtext2/static/editable-body.html + lib/richtext2/richtext2/static/editable-div.html + lib/richtext2/richtext2/static/js/variables.js + lib/richtext2/richtext2/static/js/range-bootstrap.js + lib/richtext2/richtext2/static/js/range.js + lib/richtext2/richtext2/static/js/output.js + lib/richtext2/richtext2/static/js/compare.js + lib/richtext2/richtext2/static/js/canonicalize.js + lib/richtext2/richtext2/static/js/pad.js + lib/richtext2/richtext2/static/js/run.js + lib/richtext2/richtext2/static/js/units.js + lib/richtext2/richtext2/static/common.css + lib/richtext2/richtext2/__init__.py + lib/richtext2/richtext2/handlers.py + lib/richtext2/richtext2/templates/output.html + lib/richtext2/richtext2/templates/richtext2.html + lib/richtext2/richtext2/tests/forwarddelete.py + lib/richtext2/richtext2/tests/selection.py + lib/richtext2/richtext2/tests/queryIndeterm.py + lib/richtext2/richtext2/tests/unapplyCSS.py + lib/richtext2/richtext2/tests/apply.py + lib/richtext2/richtext2/tests/unapply.py + lib/richtext2/richtext2/tests/change.py + lib/richtext2/richtext2/tests/queryState.py + lib/richtext2/richtext2/tests/queryValue.py + lib/richtext2/richtext2/tests/__init__.py + lib/richtext2/richtext2/tests/insert.py + lib/richtext2/richtext2/tests/queryEnabled.py + lib/richtext2/richtext2/tests/applyCSS.py + lib/richtext2/richtext2/tests/changeCSS.py + lib/richtext2/richtext2/tests/delete.py + lib/richtext2/richtext2/tests/querySupported.py + lib/richtext2/README + lib/richtext2/update_from_upstream + lib/richtext2/LICENSE + lib/richtext2/README.Mozilla + lib/richtext2/currentStatus.js + lib/richtext2/platformFailures.js + lib/richtext/current_revision + lib/richtext/README + lib/richtext/update_from_upstream + lib/richtext/LICENSE + lib/richtext/README.Mozilla + lib/richtext/richtext/editable.html + lib/richtext/richtext/richtext.html + lib/richtext/richtext/js/range.js + lib/richtext/currentStatus.js + +[test_richtext2.html] +skip-if = os == 'android' # Bug 1202045 +[test_richtext.html] + diff --git a/editor/libeditor/tests/browserscope/test_richtext.html b/editor/libeditor/tests/browserscope/test_richtext.html new file mode 100644 index 0000000000..c07f0a366a --- /dev/null +++ b/editor/libeditor/tests/browserscope/test_richtext.html @@ -0,0 +1,48 @@ + + + + + BrowserScope Richtext Tests + + + + + + +Mozilla Bug 550569 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/browserscope/test_richtext2.html b/editor/libeditor/tests/browserscope/test_richtext2.html new file mode 100644 index 0000000000..2ecafbc059 --- /dev/null +++ b/editor/libeditor/tests/browserscope/test_richtext2.html @@ -0,0 +1,238 @@ + + + + + + + + BrowserScope Richtext2 Tests + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/editor/libeditor/tests/bug527935.html b/editor/libeditor/tests/bug527935.html new file mode 100644 index 0000000000..1731734d29 --- /dev/null +++ b/editor/libeditor/tests/bug527935.html @@ -0,0 +1,11 @@ + + + +
                      + +
                      + +
                      +
                      + +dummy page diff --git a/editor/libeditor/tests/chrome.ini b/editor/libeditor/tests/chrome.ini new file mode 100644 index 0000000000..12db86977a --- /dev/null +++ b/editor/libeditor/tests/chrome.ini @@ -0,0 +1,19 @@ +[DEFAULT] +skip-if = os == 'android' +prefs = + editor.white_space_normalization.blink_compatible=true +support-files = green.png + +[test_bug489202.xhtml] +[test_bug599983.xhtml] +[test_bug607584.xhtml] +[test_bug616590.xhtml] +[test_bug780908.xhtml] +[test_bug1386222.xhtml] +[test_bug1397412.xhtml] +[test_contenteditable_text_input_handling.html] +[test_cut_copy_delete_command_enabled.xhtml] +[test_htmleditor_keyevent_handling.html] +[test_texteditor_keyevent_handling.html] +skip-if = (debug && os=='win') || (os == 'linux') # Bug 1116205, leaks on windows debug, fails delete key on linux +[test_pasteImgTextarea.xhtml] diff --git a/editor/libeditor/tests/data/cfhtml-chromium.txt b/editor/libeditor/tests/data/cfhtml-chromium.txt new file mode 100644 index 0000000000..7e02537157 Binary files /dev/null and b/editor/libeditor/tests/data/cfhtml-chromium.txt differ diff --git a/editor/libeditor/tests/data/cfhtml-firefox.txt b/editor/libeditor/tests/data/cfhtml-firefox.txt new file mode 100644 index 0000000000..cc686d8562 Binary files /dev/null and b/editor/libeditor/tests/data/cfhtml-firefox.txt differ diff --git a/editor/libeditor/tests/data/cfhtml-ie.txt b/editor/libeditor/tests/data/cfhtml-ie.txt new file mode 100644 index 0000000000..a30bc5295e Binary files /dev/null and b/editor/libeditor/tests/data/cfhtml-ie.txt differ diff --git a/editor/libeditor/tests/data/cfhtml-nocontext.txt b/editor/libeditor/tests/data/cfhtml-nocontext.txt new file mode 100644 index 0000000000..aa48822277 --- /dev/null +++ b/editor/libeditor/tests/data/cfhtml-nocontext.txt @@ -0,0 +1,18 @@ +Version:0.9 +StartHTML:-1 +EndHTML:-1 +StartFragment:0000000111 +EndFragment:0000000246 + + + + Test + + + +

                      + 3.1415926535897932 +

                      + + + diff --git a/editor/libeditor/tests/data/cfhtml-ooo.txt b/editor/libeditor/tests/data/cfhtml-ooo.txt new file mode 100644 index 0000000000..0bcf7616ef Binary files /dev/null and b/editor/libeditor/tests/data/cfhtml-ooo.txt differ diff --git a/editor/libeditor/tests/file_bug289384-1.html b/editor/libeditor/tests/file_bug289384-1.html new file mode 100644 index 0000000000..42b7a4da49 --- /dev/null +++ b/editor/libeditor/tests/file_bug289384-1.html @@ -0,0 +1 @@ +link diff --git a/editor/libeditor/tests/file_bug289384-2.html b/editor/libeditor/tests/file_bug289384-2.html new file mode 100644 index 0000000000..0356626279 --- /dev/null +++ b/editor/libeditor/tests/file_bug289384-2.html @@ -0,0 +1 @@ +foo bar diff --git a/editor/libeditor/tests/file_bug549262.html b/editor/libeditor/tests/file_bug549262.html new file mode 100644 index 0000000000..92a0c76f35 --- /dev/null +++ b/editor/libeditor/tests/file_bug549262.html @@ -0,0 +1,8 @@ + + + + test +
                      abc
                      +
                      + + diff --git a/editor/libeditor/tests/file_bug586662.html b/editor/libeditor/tests/file_bug586662.html new file mode 100644 index 0000000000..2989531975 --- /dev/null +++ b/editor/libeditor/tests/file_bug586662.html @@ -0,0 +1,7 @@ + + + +
                      + + + diff --git a/editor/libeditor/tests/file_bug611182.html b/editor/libeditor/tests/file_bug611182.html new file mode 100644 index 0000000000..cc9e3e3765 --- /dev/null +++ b/editor/libeditor/tests/file_bug611182.html @@ -0,0 +1 @@ +foo bar diff --git a/editor/libeditor/tests/file_bug611182.sjs b/editor/libeditor/tests/file_bug611182.sjs new file mode 100644 index 0000000000..c547042ad8 --- /dev/null +++ b/editor/libeditor/tests/file_bug611182.sjs @@ -0,0 +1,240 @@ +// SJS file for test_bug611182.html +"use strict"; + +const TESTS = [ + { + ct: "text/html", + val: "fooz bar", + }, + { + ct: "text/html", + val: "fooz bar", + }, + { + ct: "text/html", + val: "fooz bar", + }, + { + ct: "text/html", + val: "

                      fooz bar

                      ", + }, + { + ct: "text/html", + val: "
                      fooz bar
                      ", + }, + { + ct: "text/html", + val: "fooz bar", + }, + { + ct: "text/html", + val: "

                      fooz bar

                      ", + }, + { + ct: "text/html", + val: "fooz bar", + }, + { + ct: "text/html", + val: "fooz bar", + }, + { + ct: "application/xhtml+xml", + val: 'fooz bar', + }, + { + ct: "application/xhtml+xml", + val: 'fooz bar', + }, + { + ct: "text/html", + val: "fooz bar", + }, + { + ct: "text/html", + val: ' diff --git a/editor/libeditor/tests/file_bug795418-2.sjs b/editor/libeditor/tests/file_bug795418-2.sjs new file mode 100644 index 0000000000..5b629abd8c --- /dev/null +++ b/editor/libeditor/tests/file_bug795418-2.sjs @@ -0,0 +1,8 @@ +// SJS file for test_bug795418-2.html +"use strict"; + +function handleRequest(request, response) { + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "application/xhtml+xml", false); + response.write("AB"); +} diff --git a/editor/libeditor/tests/file_bug915962.html b/editor/libeditor/tests/file_bug915962.html new file mode 100644 index 0000000000..85c5139d3b --- /dev/null +++ b/editor/libeditor/tests/file_bug915962.html @@ -0,0 +1,13 @@ + + + + + + + + + +

                      + + diff --git a/editor/libeditor/tests/file_bug966155.html b/editor/libeditor/tests/file_bug966155.html new file mode 100644 index 0000000000..04f55a9188 --- /dev/null +++ b/editor/libeditor/tests/file_bug966155.html @@ -0,0 +1 @@ + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_abs_positioner_appearance.html b/editor/libeditor/tests/test_abs_positioner_appearance.html new file mode 100644 index 0000000000..c516b9c511 --- /dev/null +++ b/editor/libeditor/tests/test_abs_positioner_appearance.html @@ -0,0 +1,177 @@ + + + + Test for absolute positioner appearance + + + + + +

                      + + +
                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_abs_positioner_hidden_during_dragging.html b/editor/libeditor/tests/test_abs_positioner_hidden_during_dragging.html new file mode 100644 index 0000000000..3badd4c3b3 --- /dev/null +++ b/editor/libeditor/tests/test_abs_positioner_hidden_during_dragging.html @@ -0,0 +1,102 @@ + + +Drag absolutely positioned element to crash + + + +
                      +
                      + This is absolutely positioned element. +
                      +

                      This is static positioned paragraph #1

                      +

                      This is static positioned paragraph #2

                      +

                      This is static positioned paragraph #3

                      +

                      This is static positioned paragraph #4

                      +

                      This is static positioned paragraph #5

                      +

                      This is static positioned paragraph #6

                      +

                      This is static positioned paragraph #7

                      +
                      + diff --git a/editor/libeditor/tests/test_abs_positioner_positioning_elements.html b/editor/libeditor/tests/test_abs_positioner_positioning_elements.html new file mode 100644 index 0000000000..9d9955076c --- /dev/null +++ b/editor/libeditor/tests/test_abs_positioner_positioning_elements.html @@ -0,0 +1,200 @@ + + + + Test for positioners of absolute positioned elements + + + + + + +

                      +
                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_backspace_vs.html b/editor/libeditor/tests/test_backspace_vs.html new file mode 100644 index 0000000000..d52d83f79e --- /dev/null +++ b/editor/libeditor/tests/test_backspace_vs.html @@ -0,0 +1,128 @@ + + + + + Test for Bug 1216427 + + + + + +Mozilla Bug 1216427 +

                      +
                      +
                      a☺️b
                      +
                      a🌐︎b
                      +
                      a㐂󠄀b
                      +
                      a𠀀󠄁b
                      +
                      a☺︁︂︃b
                      +
                      a𠀀󠄀󠄁󠄂b
                      + +
                      a🇨🇳b
                      +
                      a🇨🇳🇩🇪b
                      +
                      a🇨🇳🇩🇪🇪🇸b
                      +
                      a🇨🇳🇩🇪🇪🇸🇫🇷b
                      +
                      a🇨🇳🇩🇪🇪🇸🇫🇷🇬🇧b
                      + +
                      a☺️b
                      +
                      a🌐︎b
                      +
                      a㐂󠄀b
                      +
                      a𠀀󠄁b
                      +
                      a☺︁︂︃b
                      +
                      a𠀀󠄀󠄁󠄂b
                      +
                      a🇨🇳b
                      +
                      a🇨🇳🇩🇪b
                      +
                      a🇨🇳🇩🇪🇪🇸b
                      +
                      a🇨🇳🇩🇪🇪🇸🇫🇷b
                      +
                      a🇨🇳🇩🇪🇪🇸🇫🇷🇬🇧b
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1026397.html b/editor/libeditor/tests/test_bug1026397.html new file mode 100644 index 0000000000..ef54befe57 --- /dev/null +++ b/editor/libeditor/tests/test_bug1026397.html @@ -0,0 +1,101 @@ + + + + + Test for Bug 1026397 + + + + + +Mozilla Bug 1026397 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1053048.html b/editor/libeditor/tests/test_bug1053048.html new file mode 100644 index 0000000000..aca8bfdefc --- /dev/null +++ b/editor/libeditor/tests/test_bug1053048.html @@ -0,0 +1,69 @@ + + + + + + Test for Bug 1053048 + + + + + + +Mozilla Bug 1053048 +

                      + + + + +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1068979.html b/editor/libeditor/tests/test_bug1068979.html new file mode 100644 index 0000000000..189be35f91 --- /dev/null +++ b/editor/libeditor/tests/test_bug1068979.html @@ -0,0 +1,72 @@ + + + + + Test for Bug 1068979 + + + + + +Mozilla Bug 1068979 +

                      +
                      +
                      𝐀
                      +
                      a𝐁b
                      +
                      a𝐂b
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1094000.html b/editor/libeditor/tests/test_bug1094000.html new file mode 100644 index 0000000000..32d4eebca7 --- /dev/null +++ b/editor/libeditor/tests/test_bug1094000.html @@ -0,0 +1,137 @@ + + + + + Test for Bug 1094000 + + + + + +Mozilla Bug 1094000 +

                      +
                      +
                      +

                      +
                      a
                      +
                      b
                      +
                      c
                      +
                      d
                      +
                      e
                      +
                      f
                      +
                      g
                      +
                      h
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1100966.html b/editor/libeditor/tests/test_bug1100966.html new file mode 100644 index 0000000000..4336bf3863 --- /dev/null +++ b/editor/libeditor/tests/test_bug1100966.html @@ -0,0 +1,72 @@ + + + + + Test for Bug 1100966 + + + + + +
                      +
                      +
                      +=====
                      +correct
                      +fivee sixx
                      +==== +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug1102906.html b/editor/libeditor/tests/test_bug1102906.html new file mode 100644 index 0000000000..26b0592637 --- /dev/null +++ b/editor/libeditor/tests/test_bug1102906.html @@ -0,0 +1,51 @@ + + + + + + Test for Bug 1102906 + + + + + + + + + +Mozilla Bug 1102906 +
                      Drag
                      + + diff --git a/editor/libeditor/tests/test_bug1109465.html b/editor/libeditor/tests/test_bug1109465.html new file mode 100644 index 0000000000..97bc6a71e9 --- /dev/null +++ b/editor/libeditor/tests/test_bug1109465.html @@ -0,0 +1,65 @@ + + + + + Test for Bug 1109465 + + + + + +
                      + +
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug1130651.html b/editor/libeditor/tests/test_bug1130651.html new file mode 100644 index 0000000000..a9e1bad8c2 --- /dev/null +++ b/editor/libeditor/tests/test_bug1130651.html @@ -0,0 +1,17 @@ + +Test for Bug 1130651 + + +Mozilla Bug 1332876 +
                      a b
                      + diff --git a/editor/libeditor/tests/test_bug1140105.html b/editor/libeditor/tests/test_bug1140105.html new file mode 100644 index 0000000000..7820194aab --- /dev/null +++ b/editor/libeditor/tests/test_bug1140105.html @@ -0,0 +1,64 @@ + + + + + Test for Bug 1140105 + + + + + +
                      +
                      + +
                      1234567890
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug1140617.html b/editor/libeditor/tests/test_bug1140617.html new file mode 100644 index 0000000000..e8a9923489 --- /dev/null +++ b/editor/libeditor/tests/test_bug1140617.html @@ -0,0 +1,37 @@ + +Mozilla Bug 1140617 + + +Mozilla Bug 1140617 + + + diff --git a/editor/libeditor/tests/test_bug1151186.html b/editor/libeditor/tests/test_bug1151186.html new file mode 100644 index 0000000000..049287a135 --- /dev/null +++ b/editor/libeditor/tests/test_bug1151186.html @@ -0,0 +1,69 @@ + + + + + + Test for Bug 1151186 + + + + + +Mozilla Bug 1151186 +

                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1153237.html b/editor/libeditor/tests/test_bug1153237.html new file mode 100644 index 0000000000..ea1863a059 --- /dev/null +++ b/editor/libeditor/tests/test_bug1153237.html @@ -0,0 +1,48 @@ + + + + + + Test for Bug 1153237 + + + + + +Mozilla Bug 1153237 +
                      Some text
                      + +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1154791.html b/editor/libeditor/tests/test_bug1154791.html new file mode 100644 index 0000000000..8ac00104b8 --- /dev/null +++ b/editor/libeditor/tests/test_bug1154791.html @@ -0,0 +1,72 @@ + + + + + Test for Bug 1154791 + + + + + +
                      +
                      + +
                      +thiss onee is stilll a +
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug1162952.html b/editor/libeditor/tests/test_bug1162952.html new file mode 100644 index 0000000000..0b8287f157 --- /dev/null +++ b/editor/libeditor/tests/test_bug1162952.html @@ -0,0 +1,43 @@ + + + + + Test for Bug 1162952 + + + + + +Mozilla Bug 1162952 +

                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1181130-1.html b/editor/libeditor/tests/test_bug1181130-1.html new file mode 100644 index 0000000000..0b9710a3b2 --- /dev/null +++ b/editor/libeditor/tests/test_bug1181130-1.html @@ -0,0 +1,50 @@ + + + + + + Test for Bug 1181130 + + + + + +Mozilla Bug 1181130 +

                      +
                      + editable div +
                      + non-editable div +
                      nested editable div
                      +
                      +
                      + +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1181130-2.html b/editor/libeditor/tests/test_bug1181130-2.html new file mode 100644 index 0000000000..fa091b71a0 --- /dev/null +++ b/editor/libeditor/tests/test_bug1181130-2.html @@ -0,0 +1,44 @@ + + + + + + Test for Bug 1181130 + + + + + +Mozilla Bug 1181130 +

                      +
                      + editable div +
                      + non-editable div +
                      +
                      + +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1186799.html b/editor/libeditor/tests/test_bug1186799.html new file mode 100644 index 0000000000..f5f14eb9c0 --- /dev/null +++ b/editor/libeditor/tests/test_bug1186799.html @@ -0,0 +1,78 @@ + + + + + Test for Bug 1186799 + + + + + +
                      +Mozilla Bug 1186799 +

                      +
                      + span +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1230473.html b/editor/libeditor/tests/test_bug1230473.html new file mode 100644 index 0000000000..7d1ec43bb0 --- /dev/null +++ b/editor/libeditor/tests/test_bug1230473.html @@ -0,0 +1,103 @@ + + + + + + Test for Bug 1230473 + + + + + +Mozilla Bug 1230473 + + +
                      + + + diff --git a/editor/libeditor/tests/test_bug1247483.html b/editor/libeditor/tests/test_bug1247483.html new file mode 100644 index 0000000000..c8b45b4439 --- /dev/null +++ b/editor/libeditor/tests/test_bug1247483.html @@ -0,0 +1,61 @@ + + +Test for bug 1247483 + + + + + + + +Mozilla Bug 1247483 +

                      + +
                      +
                      + +
                      + + + +
                      1 11 2
                      2 12 2
                      +
                      + +
                      +
                      + + + diff --git a/editor/libeditor/tests/test_bug1248128.html b/editor/libeditor/tests/test_bug1248128.html new file mode 100644 index 0000000000..30c39bcff8 --- /dev/null +++ b/editor/libeditor/tests/test_bug1248128.html @@ -0,0 +1,52 @@ + + + + + + Test for Bug 1248128 + + + + + + +Mozilla Bug 1248128 +
                      + +
                      + + diff --git a/editor/libeditor/tests/test_bug1248185.html b/editor/libeditor/tests/test_bug1248185.html new file mode 100644 index 0000000000..d18b62b025 --- /dev/null +++ b/editor/libeditor/tests/test_bug1248185.html @@ -0,0 +1,56 @@ + + + + + + Test for Bug 1248185 + + + + + +Mozilla Bug 1248185 + +
                      +blablablablablablablablablablablablablabla one two three four five +
                      +foo +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1250010.html b/editor/libeditor/tests/test_bug1250010.html new file mode 100644 index 0000000000..7113fa9177 --- /dev/null +++ b/editor/libeditor/tests/test_bug1250010.html @@ -0,0 +1,90 @@ + + + + + Test for Bug 1250010 + + + + + +
                      +
                      + +

                      1234567890

                      +

                      xyz

                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug1257363.html b/editor/libeditor/tests/test_bug1257363.html new file mode 100644 index 0000000000..b8d762d5e2 --- /dev/null +++ b/editor/libeditor/tests/test_bug1257363.html @@ -0,0 +1,180 @@ + + + + + Test for Bug 1257363 + + + + + +
                      +
                      + +

                      12345

                      67
                      +

                      12345

                      67
                      +

                      x

                      +

                      y

                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug1258085.html b/editor/libeditor/tests/test_bug1258085.html new file mode 100644 index 0000000000..c93e8ee0d9 --- /dev/null +++ b/editor/libeditor/tests/test_bug1258085.html @@ -0,0 +1,67 @@ + +Test for Bug 1186799 + + + +
                      + diff --git a/editor/libeditor/tests/test_bug1268736.html b/editor/libeditor/tests/test_bug1268736.html new file mode 100644 index 0000000000..bd0265aaf3 --- /dev/null +++ b/editor/libeditor/tests/test_bug1268736.html @@ -0,0 +1,60 @@ + + + + + Test for Bug 1268736 + + + + + +Mozilla Bug 1268736 + + + + + + + + + + + + + +
                      abc
                      def
                      + + + + diff --git a/editor/libeditor/tests/test_bug1270235.html b/editor/libeditor/tests/test_bug1270235.html new file mode 100644 index 0000000000..1499239ae1 --- /dev/null +++ b/editor/libeditor/tests/test_bug1270235.html @@ -0,0 +1,46 @@ + + + + + Test for Bug 1270235 + + + + + + +Mozilla Bug 1270235 +

                      + + +

                      AB

                      + + + diff --git a/editor/libeditor/tests/test_bug1306532.html b/editor/libeditor/tests/test_bug1306532.html new file mode 100644 index 0000000000..57c4ad6927 --- /dev/null +++ b/editor/libeditor/tests/test_bug1306532.html @@ -0,0 +1,68 @@ + + +Test for bug 1306532 + + + + + + + +Mozilla Bug 1306532 +

                      + +
                      +
                      + +
                      + + + + + + + + + +
                      MonthSavings
                      January$100
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug1310912.html b/editor/libeditor/tests/test_bug1310912.html new file mode 100644 index 0000000000..1581a1bec9 --- /dev/null +++ b/editor/libeditor/tests/test_bug1310912.html @@ -0,0 +1,121 @@ + + + + + Test for Bug 1310912 + + + + + +Mozilla Bug 1310912 +

                      + + +
                      ABC
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1314790.html b/editor/libeditor/tests/test_bug1314790.html new file mode 100644 index 0000000000..29c9e471a2 --- /dev/null +++ b/editor/libeditor/tests/test_bug1314790.html @@ -0,0 +1,57 @@ + + + + + Test for Bug 1314790 + + + + + +Mozilla Bug 1314790 +

                      + + +

                      pen pineapple

                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1315065.html b/editor/libeditor/tests/test_bug1315065.html new file mode 100644 index 0000000000..c8e861c3a8 --- /dev/null +++ b/editor/libeditor/tests/test_bug1315065.html @@ -0,0 +1,145 @@ + + + + + + Test for Bug 1315065 + + + + + +Mozilla Bug 1315065 +

                      abc

                      + + + diff --git a/editor/libeditor/tests/test_bug1316302.html b/editor/libeditor/tests/test_bug1316302.html new file mode 100644 index 0000000000..f8f7299330 --- /dev/null +++ b/editor/libeditor/tests/test_bug1316302.html @@ -0,0 +1,50 @@ + + + + + + Test for Bug 1316302 + + + + + +Mozilla Bug 1316302 +
                      +

                      abc

                      +
                      + + + diff --git a/editor/libeditor/tests/test_bug1318312.html b/editor/libeditor/tests/test_bug1318312.html new file mode 100644 index 0000000000..530731d6b3 --- /dev/null +++ b/editor/libeditor/tests/test_bug1318312.html @@ -0,0 +1,108 @@ + + + +Test for bug1318312 + + + + + + +

                      content of outer editor

                      +

                      static content of outer editor

                      +

                      content of inner editor

                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1328023.html b/editor/libeditor/tests/test_bug1328023.html new file mode 100644 index 0000000000..b3c7cadee0 --- /dev/null +++ b/editor/libeditor/tests/test_bug1328023.html @@ -0,0 +1,61 @@ + + + + + Test for Bug 1328023 + + + + + +Mozilla Bug 1328023 +

                      + + + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1330796.html b/editor/libeditor/tests/test_bug1330796.html new file mode 100644 index 0000000000..1fe1430b78 --- /dev/null +++ b/editor/libeditor/tests/test_bug1330796.html @@ -0,0 +1,95 @@ + + + + + + Test for Bug 772796 + + + + + + +Mozilla Bug 1330796 +

                      + + +
                      + +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1332876.html b/editor/libeditor/tests/test_bug1332876.html new file mode 100644 index 0000000000..1234b53f62 --- /dev/null +++ b/editor/libeditor/tests/test_bug1332876.html @@ -0,0 +1,57 @@ + + + + + + Test for Bug 1332876 + + + + + +Mozilla Bug 1332876 +

                      + + + + +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1352799.html b/editor/libeditor/tests/test_bug1352799.html new file mode 100644 index 0000000000..a3f53fc43b --- /dev/null +++ b/editor/libeditor/tests/test_bug1352799.html @@ -0,0 +1,84 @@ + + + + + Test for Bug 1352799 + + + + + +Mozilla Bug 1352799 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1355792.html b/editor/libeditor/tests/test_bug1355792.html new file mode 100644 index 0000000000..c8231ebec4 --- /dev/null +++ b/editor/libeditor/tests/test_bug1355792.html @@ -0,0 +1,17 @@ + +Test for Bug 1355792 + + +
                      a


                      b
                      + diff --git a/editor/libeditor/tests/test_bug1358025.html b/editor/libeditor/tests/test_bug1358025.html new file mode 100644 index 0000000000..331bde5d8a --- /dev/null +++ b/editor/libeditor/tests/test_bug1358025.html @@ -0,0 +1,98 @@ + + + Test for bug 1358025 + + + + +Mozilla Bug 1358025 +
                      + +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1361008.html b/editor/libeditor/tests/test_bug1361008.html new file mode 100644 index 0000000000..177ed6085e --- /dev/null +++ b/editor/libeditor/tests/test_bug1361008.html @@ -0,0 +1,61 @@ + + + + + Bug 1361008 + + + + + +Mozilla Bug 1361008 +

                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1361052.html b/editor/libeditor/tests/test_bug1361052.html new file mode 100644 index 0000000000..5e9e4df065 --- /dev/null +++ b/editor/libeditor/tests/test_bug1361052.html @@ -0,0 +1,50 @@ + + + + Test for Bug 1361052 + + + + + +Mozilla Bug 1361052 +

                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1368544.html b/editor/libeditor/tests/test_bug1368544.html new file mode 100644 index 0000000000..899b5977e2 --- /dev/null +++ b/editor/libeditor/tests/test_bug1368544.html @@ -0,0 +1,90 @@ + + + + + + + + + +Mozilla Bug 1368544 +
                      + +
                      +
                      + + + + diff --git a/editor/libeditor/tests/test_bug1385905.html b/editor/libeditor/tests/test_bug1385905.html new file mode 100644 index 0000000000..fda99ae741 --- /dev/null +++ b/editor/libeditor/tests/test_bug1385905.html @@ -0,0 +1,51 @@ + + + + + + + + + +Mozilla Bug 1385905 +
                      +
                      contents
                      +
                      +
                      + + + + diff --git a/editor/libeditor/tests/test_bug1386222.xhtml b/editor/libeditor/tests/test_bug1386222.xhtml new file mode 100644 index 0000000000..ce1f8fa509 --- /dev/null +++ b/editor/libeditor/tests/test_bug1386222.xhtml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug1390562.html b/editor/libeditor/tests/test_bug1390562.html new file mode 100644 index 0000000000..924062352d --- /dev/null +++ b/editor/libeditor/tests/test_bug1390562.html @@ -0,0 +1,67 @@ + + + + + Test for Bug 1390562 + + + + + +Mozilla Bug 1390562 +

                      + + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1394758.html b/editor/libeditor/tests/test_bug1394758.html new file mode 100644 index 0000000000..d1560e5092 --- /dev/null +++ b/editor/libeditor/tests/test_bug1394758.html @@ -0,0 +1,60 @@ + + + + + Test for Bug1394758 + + + + + +Mozilla Bug 1394758 +

                      +
                      +
                      + + Hello + + World +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1397412.xhtml b/editor/libeditor/tests/test_bug1397412.xhtml new file mode 100644 index 0000000000..a975967696 --- /dev/null +++ b/editor/libeditor/tests/test_bug1397412.xhtml @@ -0,0 +1,65 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug1399722.html b/editor/libeditor/tests/test_bug1399722.html new file mode 100644 index 0000000000..4b6e2c7c72 --- /dev/null +++ b/editor/libeditor/tests/test_bug1399722.html @@ -0,0 +1,38 @@ + + + + + Test for Bug 1399722 + + + + + +Mozilla Bug 1399722 +

                      + + + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1406726.html b/editor/libeditor/tests/test_bug1406726.html new file mode 100644 index 0000000000..7f7cbca963 --- /dev/null +++ b/editor/libeditor/tests/test_bug1406726.html @@ -0,0 +1,126 @@ + + + + + Test for Bug 1406726 + + + + + +Mozilla Bug 1406726 +

                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1409520.html b/editor/libeditor/tests/test_bug1409520.html new file mode 100644 index 0000000000..f610d25a93 --- /dev/null +++ b/editor/libeditor/tests/test_bug1409520.html @@ -0,0 +1,45 @@ + + + + + Test for Bug 1409520 + + + + +Mozilla Bug 1409520 +

                      + + +
                    • + +
                    • + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1425997.html b/editor/libeditor/tests/test_bug1425997.html new file mode 100644 index 0000000000..637d77a0ca --- /dev/null +++ b/editor/libeditor/tests/test_bug1425997.html @@ -0,0 +1,63 @@ + + + + + Test for Bug 1425997 + + + + +Mozilla Bug 1425997 +

                      + + +
                      + +foo +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug1497480.html b/editor/libeditor/tests/test_bug1497480.html new file mode 100644 index 0000000000..cc18facf00 --- /dev/null +++ b/editor/libeditor/tests/test_bug1497480.html @@ -0,0 +1,93 @@ + + + + + + Test for Bug 1497480 + + + + + + + +Mozilla Bug 1497480 +

                      + +
                      Bug 1497480
                      +
                      + + + + diff --git a/editor/libeditor/tests/test_bug1543312.html b/editor/libeditor/tests/test_bug1543312.html new file mode 100644 index 0000000000..50db750f29 --- /dev/null +++ b/editor/libeditor/tests/test_bug1543312.html @@ -0,0 +1,68 @@ + + + + + Test for Bug 1543312 + + + + + + + + Mozilla Bug 1543312 +

                      + +
                      + + +
                      + + diff --git a/editor/libeditor/tests/test_bug1568996.html b/editor/libeditor/tests/test_bug1568996.html new file mode 100644 index 0000000000..e0d48dad76 --- /dev/null +++ b/editor/libeditor/tests/test_bug1568996.html @@ -0,0 +1,67 @@ + + + + +Test for Bug 1568996 + + + + + +Bug 1568996 +

                      + +
                      
                      +
                      +
                      +
                      +
                      diff --git a/editor/libeditor/tests/test_bug1574596.html b/editor/libeditor/tests/test_bug1574596.html
                      new file mode 100644
                      index 0000000000..fe0a090d26
                      --- /dev/null
                      +++ b/editor/libeditor/tests/test_bug1574596.html
                      @@ -0,0 +1,64 @@
                      +
                      +
                      +
                      +
                      +  Test for Bug 1574596
                      +  
                      +  
                      +  
                      +
                      +
                      +
                      +
                      +  Mozilla Bug 1574596
                      +  

                      + +
                      + +
                      + + diff --git a/editor/libeditor/tests/test_bug1581337.html b/editor/libeditor/tests/test_bug1581337.html new file mode 100644 index 0000000000..c6163f6637 --- /dev/null +++ b/editor/libeditor/tests/test_bug1581337.html @@ -0,0 +1,33 @@ + + + + + Test for Bug 1581337 + + + + + + Mozilla Bug 1581337 +

                      + +
                      foo bar
                      + + + diff --git a/editor/libeditor/tests/test_bug1619852.html b/editor/libeditor/tests/test_bug1619852.html new file mode 100644 index 0000000000..4564f36526 --- /dev/null +++ b/editor/libeditor/tests/test_bug1619852.html @@ -0,0 +1,34 @@ + + + + +Test for Bug 1619852 + + + + + +Bug 1619852 +

                      + +
                      
                      +
                      abcd
                      + + + diff --git a/editor/libeditor/tests/test_bug1620778.html b/editor/libeditor/tests/test_bug1620778.html new file mode 100644 index 0000000000..5a1c34fb1a --- /dev/null +++ b/editor/libeditor/tests/test_bug1620778.html @@ -0,0 +1,27 @@ + +Test for Bug 1620778 + + + + + + + + diff --git a/editor/libeditor/tests/test_bug1649005.html b/editor/libeditor/tests/test_bug1649005.html new file mode 100644 index 0000000000..4665c6b6de --- /dev/null +++ b/editor/libeditor/tests/test_bug1649005.html @@ -0,0 +1,45 @@ + + + + + + Test for bug 1649005 + + + + + + + diff --git a/editor/libeditor/tests/test_bug1659276.html b/editor/libeditor/tests/test_bug1659276.html new file mode 100644 index 0000000000..6789db2e77 --- /dev/null +++ b/editor/libeditor/tests/test_bug1659276.html @@ -0,0 +1,78 @@ + + + + +Test for Bug 1659276 + + + + + +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      +

                      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

                      + + + + diff --git a/editor/libeditor/tests/test_bug200416.html b/editor/libeditor/tests/test_bug200416.html new file mode 100644 index 0000000000..9fb6564250 --- /dev/null +++ b/editor/libeditor/tests/test_bug200416.html @@ -0,0 +1,15 @@ + + +Test for Bug 200416 + + +Mozilla Bug 200416 +
                      foo

                      bar

                      + diff --git a/editor/libeditor/tests/test_bug289384.html b/editor/libeditor/tests/test_bug289384.html new file mode 100644 index 0000000000..f459822c03 --- /dev/null +++ b/editor/libeditor/tests/test_bug289384.html @@ -0,0 +1,48 @@ + + + + + Test for Bug 289384 + + + + + +Mozilla Bug 289384 +

                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug290026.html b/editor/libeditor/tests/test_bug290026.html new file mode 100644 index 0000000000..786a12018c --- /dev/null +++ b/editor/libeditor/tests/test_bug290026.html @@ -0,0 +1,52 @@ + + + + + Test for Bug 290026 + + + + + +Mozilla Bug 290026 +

                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug291780.html b/editor/libeditor/tests/test_bug291780.html new file mode 100644 index 0000000000..3a97073fad --- /dev/null +++ b/editor/libeditor/tests/test_bug291780.html @@ -0,0 +1,49 @@ + + + + + Test for Bug 291780 + + + + + +Mozilla Bug 291780 +

                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug309731.html b/editor/libeditor/tests/test_bug309731.html new file mode 100644 index 0000000000..6e2a2e6001 --- /dev/null +++ b/editor/libeditor/tests/test_bug309731.html @@ -0,0 +1,58 @@ + + + + + Test for Bug 309731 + + + + + +Mozilla Bug 309731 +

                      + +
                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug316447.html b/editor/libeditor/tests/test_bug316447.html new file mode 100644 index 0000000000..76d123815b --- /dev/null +++ b/editor/libeditor/tests/test_bug316447.html @@ -0,0 +1,16 @@ + + +Test for Bug 316447 + + +Mozilla Bug 316447 +

                      + diff --git a/editor/libeditor/tests/test_bug318065.html b/editor/libeditor/tests/test_bug318065.html new file mode 100644 index 0000000000..be989fcdef --- /dev/null +++ b/editor/libeditor/tests/test_bug318065.html @@ -0,0 +1,82 @@ + + + + + + + Test for Bug 318065 + + + + + + + Mozilla Bug 318065 +

                      + + +
                      +    
                      +  
                      + + + + + diff --git a/editor/libeditor/tests/test_bug332636.html b/editor/libeditor/tests/test_bug332636.html new file mode 100644 index 0000000000..6fc255f7d6 --- /dev/null +++ b/editor/libeditor/tests/test_bug332636.html @@ -0,0 +1,75 @@ + + + + + Test for Bug 332636 + + + + + +Mozilla Bug 332636 +

                      +
                      +
                      axb
                      +
                      äb
                      +
                      a𐐀b
                      +
                      a𐨏b
                      + +
                      axb
                      +
                      äb
                      +
                      a𐐀b
                      +
                      a𐨏b
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug332636.html^headers^ b/editor/libeditor/tests/test_bug332636.html^headers^ new file mode 100644 index 0000000000..e853d6cee5 --- /dev/null +++ b/editor/libeditor/tests/test_bug332636.html^headers^ @@ -0,0 +1 @@ +Content-Type: text/html; charset=UTF-8 diff --git a/editor/libeditor/tests/test_bug358033.html b/editor/libeditor/tests/test_bug358033.html new file mode 100644 index 0000000000..db2b00400e --- /dev/null +++ b/editor/libeditor/tests/test_bug358033.html @@ -0,0 +1,41 @@ + + + + + Test for Bug 358033 + + + + + +Mozilla Bug 358033 +

                      +
                      + +
                      +
                      +
                      +
                      +
                      diff --git a/editor/libeditor/tests/test_bug366682.html b/editor/libeditor/tests/test_bug366682.html
                      new file mode 100644
                      index 0000000000..a6f5135a4b
                      --- /dev/null
                      +++ b/editor/libeditor/tests/test_bug366682.html
                      @@ -0,0 +1,64 @@
                      +
                      +
                      +
                      +
                      +  Test for Bug 366682
                      +  
                      +  
                      +  
                      +  
                      +
                      +
                      +Mozilla Bug 366682
                      +

                      + +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug372345.html b/editor/libeditor/tests/test_bug372345.html new file mode 100644 index 0000000000..bd2de542c4 --- /dev/null +++ b/editor/libeditor/tests/test_bug372345.html @@ -0,0 +1,58 @@ + + + + + Test for Bug 372345 + + + + + +Mozilla Bug 372345 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug404320.html b/editor/libeditor/tests/test_bug404320.html new file mode 100644 index 0000000000..fe27dfc875 --- /dev/null +++ b/editor/libeditor/tests/test_bug404320.html @@ -0,0 +1,87 @@ + + + + + Test for Bug 404320 + + + + +Mozilla Bug 404320 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug408231.html b/editor/libeditor/tests/test_bug408231.html new file mode 100644 index 0000000000..a490d62c56 --- /dev/null +++ b/editor/libeditor/tests/test_bug408231.html @@ -0,0 +1,249 @@ + + + + + Test for Bug 408231 + + + + +Mozilla Bug 408231 +

                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug410986.html b/editor/libeditor/tests/test_bug410986.html new file mode 100644 index 0000000000..fdc5d27631 --- /dev/null +++ b/editor/libeditor/tests/test_bug410986.html @@ -0,0 +1,80 @@ + + + + + Test for Bug 410986 + + + + + +Mozilla Bug 410986 +

                      +
                      +
                      green text
                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug414526.html b/editor/libeditor/tests/test_bug414526.html new file mode 100644 index 0000000000..03aa72867e --- /dev/null +++ b/editor/libeditor/tests/test_bug414526.html @@ -0,0 +1,234 @@ + + + Test for backspace key and delete key shouldn't remove another editing host's text + + + + + +
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug417418.html b/editor/libeditor/tests/test_bug417418.html new file mode 100644 index 0000000000..d319e4e984 --- /dev/null +++ b/editor/libeditor/tests/test_bug417418.html @@ -0,0 +1,78 @@ + + + + + Test for Bug 417418 + + + + + + +Mozilla Bug 417418 +
                      +

                      first paragraph

                      +

                      second paragraph.

                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug426246.html b/editor/libeditor/tests/test_bug426246.html new file mode 100644 index 0000000000..50e5df2cb4 --- /dev/null +++ b/editor/libeditor/tests/test_bug426246.html @@ -0,0 +1,71 @@ + + + + + Test for Bug 426246 + + + + + +Mozilla Bug 426246 +

                      + + +
                      +

                      first line

                      +

                      this is the second line

                      +
                      + +
                      first line
                      this is the second line
                      +
                      • first line
                      • this is the second line
                      +
                      first line
                      +this is the second line
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug430392.html b/editor/libeditor/tests/test_bug430392.html new file mode 100644 index 0000000000..6c8db068fc --- /dev/null +++ b/editor/libeditor/tests/test_bug430392.html @@ -0,0 +1,181 @@ + + + + + Test for Bug 430392 + + + + + +Mozilla Bug 430392 +

                      +
                      +
                      A ; B ; C
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug432225.html b/editor/libeditor/tests/test_bug432225.html new file mode 100644 index 0000000000..010c1cdf4b --- /dev/null +++ b/editor/libeditor/tests/test_bug432225.html @@ -0,0 +1,70 @@ + + + + + Test for Bug 432225 + + + + + + +Mozilla Bug 432225 +

                      + +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug439808.html b/editor/libeditor/tests/test_bug439808.html new file mode 100644 index 0000000000..169ba5bd70 --- /dev/null +++ b/editor/libeditor/tests/test_bug439808.html @@ -0,0 +1,37 @@ + + + + + Test for Bug 439808 + + + + + +Mozilla Bug 439808 +

                      +
                      +twest +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug442186.html b/editor/libeditor/tests/test_bug442186.html new file mode 100644 index 0000000000..deecbed5f1 --- /dev/null +++ b/editor/libeditor/tests/test_bug442186.html @@ -0,0 +1,103 @@ + + + + + Test for Bug 442186 + + + + + +Mozilla Bug 442186 +

                      +
                      +

                      two <div> containers

                      +
                      +
                      First paragraph with some text.
                      +
                      Second paragraph with some text.
                      +
                      + +

                      two paragraphs

                      +
                      +

                      First paragraph with some text.

                      +

                      Second paragraph with some text.

                      +
                      + +

                      one text node, one paragraph

                      +
                      + First paragraph with some text. +

                      Second paragraph with some text.

                      +
                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug449243.html b/editor/libeditor/tests/test_bug449243.html new file mode 100644 index 0000000000..13debfcec8 --- /dev/null +++ b/editor/libeditor/tests/test_bug449243.html @@ -0,0 +1,146 @@ + + + + + Test for Bug 449243 + + + + + +Mozilla Bug 449243 +

                      +
                      +

                      This is a title

                      +
                        +
                      • this is a
                      • +
                      • bullet list
                      • +
                      +
                        +
                      1. this is a
                      2. +
                      3. numbered list
                      4. +
                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug455992.html b/editor/libeditor/tests/test_bug455992.html new file mode 100644 index 0000000000..b6a77e2c9b --- /dev/null +++ b/editor/libeditor/tests/test_bug455992.html @@ -0,0 +1,96 @@ + + +Test for bug 455992 + + + + + + + +Mozilla Bug 455992 +

                      + +
                      +
                      + +
                      X Y
                      +
                      X Y
                      +
                      X Y
                      +
                      X Y
                      +
                      X
                      Y
                      + +
                      +
                      +
                      +
                      + + + diff --git a/editor/libeditor/tests/test_bug456244.html b/editor/libeditor/tests/test_bug456244.html new file mode 100644 index 0000000000..11ae5ad987 --- /dev/null +++ b/editor/libeditor/tests/test_bug456244.html @@ -0,0 +1,69 @@ + + +Test for bug 456244 + + + + + + + +Mozilla Bug 456244 +

                      + +
                      +
                      + +
                      X Y
                      + +
                      +
                      + + + diff --git a/editor/libeditor/tests/test_bug460740.html b/editor/libeditor/tests/test_bug460740.html new file mode 100644 index 0000000000..509ad6d6ae --- /dev/null +++ b/editor/libeditor/tests/test_bug460740.html @@ -0,0 +1,124 @@ + + + + + Test for Bug 460740 + + + + + +Mozilla Bug 460740 +

                      +
                      +
                        +
                      • + Editable LI +
                      • +
                      • +
                        + Editable DIV inside LI +
                        +
                      • +
                      • +
                        +
                        + Editable DIV inside DIV inside LI +
                        +
                        +
                      • +
                      • +

                        +
                        + Editable DIV inside H3 inside LI +
                        +

                        +
                      • +
                      +
                      + Editable DIV +
                      +

                      + Editable H3 +

                      +

                      + Editable P +

                      +
                      +

                      + Editable P in a DIV +

                      +
                      +

                      Editable SPAN in a P

                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug46555.html b/editor/libeditor/tests/test_bug46555.html new file mode 100644 index 0000000000..3838bdb3b2 --- /dev/null +++ b/editor/libeditor/tests/test_bug46555.html @@ -0,0 +1,47 @@ + + + + + + + Test for Bug 46555 + + + + + + Mozilla Bug 46555 +

                      + + + + +
                      +    
                      +  
                      + + + diff --git a/editor/libeditor/tests/test_bug471319.html b/editor/libeditor/tests/test_bug471319.html new file mode 100644 index 0000000000..f9f9ac9eee --- /dev/null +++ b/editor/libeditor/tests/test_bug471319.html @@ -0,0 +1,77 @@ + + + + + + + Test for Bug 471319 + + + + + + Mozilla Bug 471319 +

                      + + +
                      +    
                      +  
                      + + + + + diff --git a/editor/libeditor/tests/test_bug471722.html b/editor/libeditor/tests/test_bug471722.html new file mode 100644 index 0000000000..b7fd6522e3 --- /dev/null +++ b/editor/libeditor/tests/test_bug471722.html @@ -0,0 +1,79 @@ + + + + + + + Test for Bug 471722 + + + + + + + Mozilla Bug 471722 +

                      + + +
                      +    
                      +  
                      + + + + diff --git a/editor/libeditor/tests/test_bug478725.html b/editor/libeditor/tests/test_bug478725.html new file mode 100644 index 0000000000..45e6aeed13 --- /dev/null +++ b/editor/libeditor/tests/test_bug478725.html @@ -0,0 +1,130 @@ + + +Test for bug 478725 + + + + + + + +Mozilla Bug 478725 +

                      + +
                      +
                      + + +
                      +
                      + + + diff --git a/editor/libeditor/tests/test_bug480647.html b/editor/libeditor/tests/test_bug480647.html new file mode 100644 index 0000000000..33f088a1b1 --- /dev/null +++ b/editor/libeditor/tests/test_bug480647.html @@ -0,0 +1,110 @@ + + +Test for Bug 480647 + + +Mozilla Bug 480647 +
                      + diff --git a/editor/libeditor/tests/test_bug480972.html b/editor/libeditor/tests/test_bug480972.html new file mode 100644 index 0000000000..37037b756a --- /dev/null +++ b/editor/libeditor/tests/test_bug480972.html @@ -0,0 +1,97 @@ + + +Test for bug 480972 + + + + + + + +Mozilla Bug 480972 +

                      + +
                      +
                      + + +
                      +
                      + + + diff --git a/editor/libeditor/tests/test_bug483651.html b/editor/libeditor/tests/test_bug483651.html new file mode 100644 index 0000000000..4ad570aa8b --- /dev/null +++ b/editor/libeditor/tests/test_bug483651.html @@ -0,0 +1,52 @@ + + + + + + + Test for Bug 483651 + + + + + + + Mozilla Bug 483651 +

                      + + +
                      +    
                      +  
                      + + + + diff --git a/editor/libeditor/tests/test_bug484181.html b/editor/libeditor/tests/test_bug484181.html new file mode 100644 index 0000000000..50dfe2d50d --- /dev/null +++ b/editor/libeditor/tests/test_bug484181.html @@ -0,0 +1,72 @@ + + + + + Test for Bug 484181 + + + + + + +Mozilla Bug 484181 +

                      + +
                      +
                      +
                      + +
                      I can haz cheezburger
                      + + + diff --git a/editor/libeditor/tests/test_bug489202.xhtml b/editor/libeditor/tests/test_bug489202.xhtml new file mode 100644 index 0000000000..6e7de2d3b9 --- /dev/null +++ b/editor/libeditor/tests/test_bug489202.xhtml @@ -0,0 +1,73 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug490879.html b/editor/libeditor/tests/test_bug490879.html new file mode 100644 index 0000000000..d8b4531eb2 --- /dev/null +++ b/editor/libeditor/tests/test_bug490879.html @@ -0,0 +1,45 @@ + +Mozilla Bug 490879 + + +Mozilla Bug 490879 + + + diff --git a/editor/libeditor/tests/test_bug502673.html b/editor/libeditor/tests/test_bug502673.html new file mode 100644 index 0000000000..f34148a6e4 --- /dev/null +++ b/editor/libeditor/tests/test_bug502673.html @@ -0,0 +1,97 @@ + + + + + + + Test for Bug 502673 + + + + + + + Mozilla Bug 502673 +

                      + + +
                      +    
                      +  
                      + + + + diff --git a/editor/libeditor/tests/test_bug514156.html b/editor/libeditor/tests/test_bug514156.html new file mode 100644 index 0000000000..1331d62b12 --- /dev/null +++ b/editor/libeditor/tests/test_bug514156.html @@ -0,0 +1,46 @@ + + + + + Test for Bug 514156 + + + + + + +Mozilla Bug 514156 +

                      +
                      + + +
                      +
                      +
                      +
                      + + + diff --git a/editor/libeditor/tests/test_bug520189.html b/editor/libeditor/tests/test_bug520189.html new file mode 100644 index 0000000000..5f1f4ae028 --- /dev/null +++ b/editor/libeditor/tests/test_bug520189.html @@ -0,0 +1,621 @@ + + + + + Test for Bug 520182 + + + + + +Mozilla Bug 520182 +

                      +
                      + + + +
                      +
                      +
                      + + +
                      +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug525389.html b/editor/libeditor/tests/test_bug525389.html new file mode 100644 index 0000000000..6fb0735608 --- /dev/null +++ b/editor/libeditor/tests/test_bug525389.html @@ -0,0 +1,207 @@ + + +Test for bug 525389 + + + + + + + +Mozilla Bug 525389 +

                      + +
                      +
                      + +
                      +
                      + + + diff --git a/editor/libeditor/tests/test_bug537046.html b/editor/libeditor/tests/test_bug537046.html new file mode 100644 index 0000000000..746aba6edc --- /dev/null +++ b/editor/libeditor/tests/test_bug537046.html @@ -0,0 +1,49 @@ + + + + + Test for Bug 537046 + + + + + +Mozilla Bug 537046 +

                      +
                      +
                      + Some editable content +
                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug549262.html b/editor/libeditor/tests/test_bug549262.html new file mode 100644 index 0000000000..a6848e3a66 --- /dev/null +++ b/editor/libeditor/tests/test_bug549262.html @@ -0,0 +1,160 @@ + + + + + Test for Bug 549262 + + + + + + +Mozilla Bug 549262 +

                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug550434.html b/editor/libeditor/tests/test_bug550434.html new file mode 100644 index 0000000000..2018701f6d --- /dev/null +++ b/editor/libeditor/tests/test_bug550434.html @@ -0,0 +1,42 @@ + + + + + Test for Bug 550434 + + + + + +Mozilla Bug 550434 +

                      +
                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug551704.html b/editor/libeditor/tests/test_bug551704.html new file mode 100644 index 0000000000..ad63904f66 --- /dev/null +++ b/editor/libeditor/tests/test_bug551704.html @@ -0,0 +1,126 @@ + + + + + Test for Bug 551704 + + + + + +Mozilla Bug 551704 +

                      +
                      +
                      a b
                      +

                      +
                      a
                      +

                      +
                      a
                      +
                      +
                      a
                      +
                      +
                      a
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug552782.html b/editor/libeditor/tests/test_bug552782.html new file mode 100644 index 0000000000..66a70cae72 --- /dev/null +++ b/editor/libeditor/tests/test_bug552782.html @@ -0,0 +1,46 @@ + + + + + Test for Bug 552782 + + + + + +Mozilla Bug 552782 +

                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug567213.html b/editor/libeditor/tests/test_bug567213.html new file mode 100644 index 0000000000..cfad69dff7 --- /dev/null +++ b/editor/libeditor/tests/test_bug567213.html @@ -0,0 +1,58 @@ + + + + + + Test for Bug 567213 + + + + + + + Mozilla Bug 567213 +

                      +
                      +
                      test
                      + +
                      + +
                      +    
                      +  
                      + + diff --git a/editor/libeditor/tests/test_bug569988.html b/editor/libeditor/tests/test_bug569988.html new file mode 100644 index 0000000000..219c97ba3b --- /dev/null +++ b/editor/libeditor/tests/test_bug569988.html @@ -0,0 +1,104 @@ + + + + + Test for Bug 569988 + + + + + +Mozilla Bug 569988 +

                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug570144.html b/editor/libeditor/tests/test_bug570144.html new file mode 100644 index 0000000000..9ea4cd1d6e --- /dev/null +++ b/editor/libeditor/tests/test_bug570144.html @@ -0,0 +1,123 @@ + + + + + Test for Bug 570144 + + + + + +Mozilla Bug 570144 +

                      +
                      + +
                      +
                        +
                      1. foo

                      2. +
                      +
                        +
                      • foo

                      • +
                      +
                      +
                      foo
                      +

                      bar

                      +
                      +
                      + +
                      +
                        +
                      1. foo

                      2. +
                      +
                        +
                      • foo

                      • +
                      +
                      +
                      foo
                      +

                      bar

                      +
                      +
                      + +
                      +
                        +
                      1. foo

                      2. +
                      +
                        +
                      • foo

                      • +
                      +
                      +
                      foo
                      +

                      bar

                      +
                      +
                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug578771.html b/editor/libeditor/tests/test_bug578771.html new file mode 100644 index 0000000000..5cf7b23e52 --- /dev/null +++ b/editor/libeditor/tests/test_bug578771.html @@ -0,0 +1,63 @@ + + + + + + + Test for Bug 578771 + + + + + + + Mozilla Bug 578771 +

                      + + +
                      +    
                      +  
                      + + + +
                      Contenteditable div that could interfere with focus
                      + + diff --git a/editor/libeditor/tests/test_bug586662.html b/editor/libeditor/tests/test_bug586662.html new file mode 100644 index 0000000000..c7280b4ac2 --- /dev/null +++ b/editor/libeditor/tests/test_bug586662.html @@ -0,0 +1,62 @@ + + + + + + Test for Bug 586662 + + + + + + + Mozilla Bug 586662 +

                      + + +
                      +    
                      +  
                      + + diff --git a/editor/libeditor/tests/test_bug587461.html b/editor/libeditor/tests/test_bug587461.html new file mode 100644 index 0000000000..2cf9f29fc6 --- /dev/null +++ b/editor/libeditor/tests/test_bug587461.html @@ -0,0 +1,16 @@ + + +Test for Bug 587461 + + + +Mozilla Bug 587461 +
                      foobar
                      + diff --git a/editor/libeditor/tests/test_bug590554.html b/editor/libeditor/tests/test_bug590554.html new file mode 100644 index 0000000000..ea48b4c08f --- /dev/null +++ b/editor/libeditor/tests/test_bug590554.html @@ -0,0 +1,36 @@ + + + + + + Test for Bug 590554 + + + + + + + + + + + + diff --git a/editor/libeditor/tests/test_bug592592.html b/editor/libeditor/tests/test_bug592592.html new file mode 100644 index 0000000000..c1a74e9893 --- /dev/null +++ b/editor/libeditor/tests/test_bug592592.html @@ -0,0 +1,72 @@ + + + + + Test for Bug 592592 + + + + + +Mozilla Bug 592592 +

                      +
                      +
                      a b
                      +
                      a b
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug596001.html b/editor/libeditor/tests/test_bug596001.html new file mode 100644 index 0000000000..451b1f9c28 --- /dev/null +++ b/editor/libeditor/tests/test_bug596001.html @@ -0,0 +1,57 @@ + + + + + Test for Bug 596001 + + + + + +Mozilla Bug 596001 +

                      +
                      + + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug596333.html b/editor/libeditor/tests/test_bug596333.html new file mode 100644 index 0000000000..794e5d1329 --- /dev/null +++ b/editor/libeditor/tests/test_bug596333.html @@ -0,0 +1,138 @@ + + + + + Test for Bug 596333 + + + + + + +Mozilla Bug 596333 +

                      + +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug596506.html b/editor/libeditor/tests/test_bug596506.html new file mode 100644 index 0000000000..a9b337e3ee --- /dev/null +++ b/editor/libeditor/tests/test_bug596506.html @@ -0,0 +1,55 @@ + + + + + Test for Bug 596506 + + + + + +Mozilla Bug 596506 +

                      + +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug597331.html b/editor/libeditor/tests/test_bug597331.html new file mode 100644 index 0000000000..d165ff78a5 --- /dev/null +++ b/editor/libeditor/tests/test_bug597331.html @@ -0,0 +1,73 @@ + + + + + Test for Bug 597331 + + + + + + + +Mozilla Bug 597331 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug597784.html b/editor/libeditor/tests/test_bug597784.html new file mode 100644 index 0000000000..ef0348a0a4 --- /dev/null +++ b/editor/libeditor/tests/test_bug597784.html @@ -0,0 +1,37 @@ + + + + + Test for Bug 597784 + + + + + +Mozilla Bug 597784 +

                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug599322.html b/editor/libeditor/tests/test_bug599322.html new file mode 100644 index 0000000000..57c15cf4c7 --- /dev/null +++ b/editor/libeditor/tests/test_bug599322.html @@ -0,0 +1,58 @@ + + + + + Test for Bug 599322.patch + + + + + +Mozilla Bug 599322.patch +

                      +
                      +
                      src
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug599983.html b/editor/libeditor/tests/test_bug599983.html new file mode 100644 index 0000000000..08fc9a228a --- /dev/null +++ b/editor/libeditor/tests/test_bug599983.html @@ -0,0 +1,16 @@ + + +Test for Bug 599983 + + + +Mozilla Bug 599983 +
                      foo
                      + diff --git a/editor/libeditor/tests/test_bug599983.xhtml b/editor/libeditor/tests/test_bug599983.xhtml new file mode 100644 index 0000000000..6e943929d4 --- /dev/null +++ b/editor/libeditor/tests/test_bug599983.xhtml @@ -0,0 +1,67 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug600570.html b/editor/libeditor/tests/test_bug600570.html new file mode 100644 index 0000000000..f4ef84199c --- /dev/null +++ b/editor/libeditor/tests/test_bug600570.html @@ -0,0 +1,81 @@ + + + + + Test for Bug 600570 + + + + + + + +Mozilla Bug 600570 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug602130.html b/editor/libeditor/tests/test_bug602130.html new file mode 100644 index 0000000000..54f4f5c312 --- /dev/null +++ b/editor/libeditor/tests/test_bug602130.html @@ -0,0 +1,44 @@ + + + + + Test for Bug 602130 + + + + + +Mozilla Bug 602130 +

                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug603556.html b/editor/libeditor/tests/test_bug603556.html new file mode 100644 index 0000000000..1e27d824e3 --- /dev/null +++ b/editor/libeditor/tests/test_bug603556.html @@ -0,0 +1,53 @@ + + + + + Test for Bug 603556 + + + + + +Mozilla Bug 603556 +

                      +
                      +
                      testing
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug604532.html b/editor/libeditor/tests/test_bug604532.html new file mode 100644 index 0000000000..cd790a58b1 --- /dev/null +++ b/editor/libeditor/tests/test_bug604532.html @@ -0,0 +1,42 @@ + + + + + Test for Bug 604532 + + + + + +Mozilla Bug 604532 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug607584.html b/editor/libeditor/tests/test_bug607584.html new file mode 100644 index 0000000000..3a77fa62c4 --- /dev/null +++ b/editor/libeditor/tests/test_bug607584.html @@ -0,0 +1,41 @@ + + + + + Test for Bug 607584 + + + + + +Mozilla Bug 607584 +

                      +
                      +

                      Hello world

                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug607584.xhtml b/editor/libeditor/tests/test_bug607584.xhtml new file mode 100644 index 0000000000..f610de544b --- /dev/null +++ b/editor/libeditor/tests/test_bug607584.xhtml @@ -0,0 +1,112 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug611182.html b/editor/libeditor/tests/test_bug611182.html new file mode 100644 index 0000000000..7843156fda --- /dev/null +++ b/editor/libeditor/tests/test_bug611182.html @@ -0,0 +1,105 @@ + + + + + Test for Bug 611182 + + + + + + +Mozilla Bug 611182 +

                      +
                      + + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug612128.html b/editor/libeditor/tests/test_bug612128.html new file mode 100644 index 0000000000..3d6d7ed34e --- /dev/null +++ b/editor/libeditor/tests/test_bug612128.html @@ -0,0 +1,42 @@ + + + + + Test for Bug 612128 + + + + + +Mozilla Bug 612128 +

                      +
                      + +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug612447.html b/editor/libeditor/tests/test_bug612447.html new file mode 100644 index 0000000000..fdb3b38f25 --- /dev/null +++ b/editor/libeditor/tests/test_bug612447.html @@ -0,0 +1,74 @@ + + + + + Test for Bug 612447 + + + + + + +Mozilla Bug 612447 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug616590.xhtml b/editor/libeditor/tests/test_bug616590.xhtml new file mode 100644 index 0000000000..1f6cb3d0f8 --- /dev/null +++ b/editor/libeditor/tests/test_bug616590.xhtml @@ -0,0 +1,101 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug620906.html b/editor/libeditor/tests/test_bug620906.html new file mode 100644 index 0000000000..e5a7138e18 --- /dev/null +++ b/editor/libeditor/tests/test_bug620906.html @@ -0,0 +1,50 @@ + + + + + Test for Bug 620906 + + + + + +Mozilla Bug 620906 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug622371.html b/editor/libeditor/tests/test_bug622371.html new file mode 100644 index 0000000000..de52efb618 --- /dev/null +++ b/editor/libeditor/tests/test_bug622371.html @@ -0,0 +1,44 @@ + + + + + Test for Bug 622371 + + + + + +Mozilla Bug 622371 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug625452.html b/editor/libeditor/tests/test_bug625452.html new file mode 100644 index 0000000000..68ff16342f --- /dev/null +++ b/editor/libeditor/tests/test_bug625452.html @@ -0,0 +1,66 @@ + + + + + Test for Bug 625452 + + + + + +Mozilla Bug 625452 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug629172.html b/editor/libeditor/tests/test_bug629172.html new file mode 100644 index 0000000000..36c8dcf43f --- /dev/null +++ b/editor/libeditor/tests/test_bug629172.html @@ -0,0 +1,106 @@ + + + + + Test for Bug 629172 + + + + + + +Mozilla Bug 629172 +

                      +
                      + + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug629845.html b/editor/libeditor/tests/test_bug629845.html new file mode 100644 index 0000000000..e7c4bd5019 --- /dev/null +++ b/editor/libeditor/tests/test_bug629845.html @@ -0,0 +1,58 @@ + + + + + Test for Bug 629845 + + + + + +Mozilla Bug 629845 +

                      + + + +
                      + + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug635636.html b/editor/libeditor/tests/test_bug635636.html new file mode 100644 index 0000000000..3da04e18f2 --- /dev/null +++ b/editor/libeditor/tests/test_bug635636.html @@ -0,0 +1,63 @@ + + + + + Test for Bug 635636 + + + + + +Mozilla Bug 635636 +

                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug636465.html b/editor/libeditor/tests/test_bug636465.html new file mode 100644 index 0000000000..2c7d866cd0 --- /dev/null +++ b/editor/libeditor/tests/test_bug636465.html @@ -0,0 +1,53 @@ + +Mozilla bug 636465 + + + + +Mozilla Bug 636465 + + diff --git a/editor/libeditor/tests/test_bug638596.html b/editor/libeditor/tests/test_bug638596.html new file mode 100644 index 0000000000..976ccb32ab --- /dev/null +++ b/editor/libeditor/tests/test_bug638596.html @@ -0,0 +1,34 @@ + + + + + Test for Bug 638596 + + + + + +Mozilla Bug 638596 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug641466.html b/editor/libeditor/tests/test_bug641466.html new file mode 100644 index 0000000000..5004df2d8a --- /dev/null +++ b/editor/libeditor/tests/test_bug641466.html @@ -0,0 +1,48 @@ + + + + + Test for Bug 641466 + + + + + +Mozilla Bug 641466 +

                      +
                      + + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug645914.html b/editor/libeditor/tests/test_bug645914.html new file mode 100644 index 0000000000..8f1a8cbfda --- /dev/null +++ b/editor/libeditor/tests/test_bug645914.html @@ -0,0 +1,63 @@ + + + + + Test for Bug 645914 + + + + + +Mozilla Bug 645914 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug646194.html b/editor/libeditor/tests/test_bug646194.html new file mode 100644 index 0000000000..5131e9cab0 --- /dev/null +++ b/editor/libeditor/tests/test_bug646194.html @@ -0,0 +1,36 @@ + +Mozilla Bug 646194 + + +Mozilla Bug 646194 + + diff --git a/editor/libeditor/tests/test_bug668599.html b/editor/libeditor/tests/test_bug668599.html new file mode 100644 index 0000000000..1bf9a64075 --- /dev/null +++ b/editor/libeditor/tests/test_bug668599.html @@ -0,0 +1,73 @@ + + + + + Test for Bug 668599 + + + + + +Mozilla Bug 668599 +

                      +
                      +
                      + block type here block +
                      +
                      +

                      + block type here block +

                      +
                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug674770-1.html b/editor/libeditor/tests/test_bug674770-1.html new file mode 100644 index 0000000000..0b6089e0ef --- /dev/null +++ b/editor/libeditor/tests/test_bug674770-1.html @@ -0,0 +1,85 @@ + + + + + Test for Bug 674770 + + + + + +Mozilla Bug 674770 +

                      +
                      +test +
                      +test +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug674770-2.html b/editor/libeditor/tests/test_bug674770-2.html new file mode 100644 index 0000000000..a7f09c718c --- /dev/null +++ b/editor/libeditor/tests/test_bug674770-2.html @@ -0,0 +1,378 @@ + + + + + Test for Bug 674770 + + + + + +Mozilla Bug 674770 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug674861.html b/editor/libeditor/tests/test_bug674861.html new file mode 100644 index 0000000000..a103bb3c40 --- /dev/null +++ b/editor/libeditor/tests/test_bug674861.html @@ -0,0 +1,194 @@ + + + + + Test for Bug 674861 + + + + + +Mozilla Bug 674861 +

                      +
                      +
                      +

                      Editable Bullet List

                      +
                        +
                      • item A
                      • +
                      • item B
                      • +
                      • item C
                      • +
                      + +

                      Editable Ordered List

                      +
                        +
                      1. item A
                      2. +
                      3. item B
                      4. +
                      5. item C
                      6. +
                      + +

                      Editable Definition List

                      +
                      +
                      term A
                      +
                      definition A
                      +
                      term B
                      +
                      definition B
                      +
                      term C
                      +
                      definition C
                      +
                      +
                      + +
                      +

                      Bullet List In Editable Section

                      +
                        +
                      • item A
                      • +
                      • item B
                      • +
                      • item C
                      • +
                      + +

                      Ordered List In Editable Section

                      +
                        +
                      1. item A
                      2. +
                      3. item B
                      4. +
                      5. item C
                      6. +
                      + +

                      Definition List In Editable Section

                      +
                      +
                      term A
                      +
                      definition A
                      +
                      term B
                      +
                      definition B
                      +
                      term C
                      +
                      definition C
                      +
                      +
                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug676401.html b/editor/libeditor/tests/test_bug676401.html new file mode 100644 index 0000000000..46445ec3c9 --- /dev/null +++ b/editor/libeditor/tests/test_bug676401.html @@ -0,0 +1,126 @@ + + + + + Test for Bug 676401 + + + + + +Mozilla Bug 676401 +

                      +
                      + +
                      +
                      not editable
                      +
                      +
                      +
                      editable
                      +
                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug677752.html b/editor/libeditor/tests/test_bug677752.html new file mode 100644 index 0000000000..cadbbf4c0d --- /dev/null +++ b/editor/libeditor/tests/test_bug677752.html @@ -0,0 +1,107 @@ + + + + + Test for Bug 677752 + + + + + +Mozilla Bug 677752 +

                      +
                      +
                      foo bar
                      +
                      foo bar
                      +

                      foo bar

                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug681229.html b/editor/libeditor/tests/test_bug681229.html new file mode 100644 index 0000000000..f63c37329c --- /dev/null +++ b/editor/libeditor/tests/test_bug681229.html @@ -0,0 +1,50 @@ + + + + + Test for Bug 681229 + + + + + + +Mozilla Bug 681229 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug686203.html b/editor/libeditor/tests/test_bug686203.html new file mode 100644 index 0000000000..d27c3555fc --- /dev/null +++ b/editor/libeditor/tests/test_bug686203.html @@ -0,0 +1,50 @@ + + + + + + + Test for Bug 686203 + + + + + + + Mozilla Bug 686203 +

                      + + +
                      +    
                      +  
                      + + +
                      abc
                      + + diff --git a/editor/libeditor/tests/test_bug692520.html b/editor/libeditor/tests/test_bug692520.html new file mode 100644 index 0000000000..68c7d5d11c --- /dev/null +++ b/editor/libeditor/tests/test_bug692520.html @@ -0,0 +1,41 @@ + + + + + Test for Bug 692520 + + + + + +Mozilla Bug 692520 +

                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug697842.html b/editor/libeditor/tests/test_bug697842.html new file mode 100644 index 0000000000..5b39abbace --- /dev/null +++ b/editor/libeditor/tests/test_bug697842.html @@ -0,0 +1,114 @@ + + + + + Test for Bug 697842 + + + + + +
                      +

                      +
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug725069.html b/editor/libeditor/tests/test_bug725069.html new file mode 100644 index 0000000000..dbbca5a13a --- /dev/null +++ b/editor/libeditor/tests/test_bug725069.html @@ -0,0 +1,34 @@ + + + + + Test for Bug 725069 + + + + +abcdef +Mozilla Bug 725069 +

                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug735059.html b/editor/libeditor/tests/test_bug735059.html new file mode 100644 index 0000000000..3b81ce48ba --- /dev/null +++ b/editor/libeditor/tests/test_bug735059.html @@ -0,0 +1,22 @@ + + +Test for Bug 735059 + + +Mozilla Bug 735059 +
                      foo
                      +
                      +
                      +
                      diff --git a/editor/libeditor/tests/test_bug738366.html b/editor/libeditor/tests/test_bug738366.html new file mode 100644 index 0000000000..a54aec7a2f --- /dev/null +++ b/editor/libeditor/tests/test_bug738366.html @@ -0,0 +1,24 @@ + + +Test for Bug 738366 + + +Mozilla Bug 738366 +
                      foobarbaz
                      + diff --git a/editor/libeditor/tests/test_bug740784.html b/editor/libeditor/tests/test_bug740784.html new file mode 100644 index 0000000000..74e8374385 --- /dev/null +++ b/editor/libeditor/tests/test_bug740784.html @@ -0,0 +1,46 @@ + + + + + + + Test for Bug 740784 + + + + + + + Mozilla Bug 740784 +

                      + + +
                      +    
                      +  
                      + + + + diff --git a/editor/libeditor/tests/test_bug742261.html b/editor/libeditor/tests/test_bug742261.html new file mode 100644 index 0000000000..9ad41dd52b --- /dev/null +++ b/editor/libeditor/tests/test_bug742261.html @@ -0,0 +1,14 @@ + + +Test for Bug 742261 + + + + diff --git a/editor/libeditor/tests/test_bug757371.html b/editor/libeditor/tests/test_bug757371.html new file mode 100644 index 0000000000..5ca41a5951 --- /dev/null +++ b/editor/libeditor/tests/test_bug757371.html @@ -0,0 +1,26 @@ + + +Test for Bug 757371 + + + +Mozilla Bug 757371 +
                      + diff --git a/editor/libeditor/tests/test_bug757771.html b/editor/libeditor/tests/test_bug757771.html new file mode 100644 index 0000000000..9ef980b662 --- /dev/null +++ b/editor/libeditor/tests/test_bug757771.html @@ -0,0 +1,31 @@ + + +Test for Bug 757771 + + + +Mozilla Bug 757771 + + + diff --git a/editor/libeditor/tests/test_bug767684.html b/editor/libeditor/tests/test_bug767684.html new file mode 100644 index 0000000000..0e65a88a70 --- /dev/null +++ b/editor/libeditor/tests/test_bug767684.html @@ -0,0 +1,15 @@ + + +Test for Bug 767684 + + +Mozilla Bug 767684 +
                      foobarbaz
                      + diff --git a/editor/libeditor/tests/test_bug772796.html b/editor/libeditor/tests/test_bug772796.html new file mode 100644 index 0000000000..80606f20e5 --- /dev/null +++ b/editor/libeditor/tests/test_bug772796.html @@ -0,0 +1,218 @@ + + + + + + Test for Bug 772796 + + + + + + +Mozilla Bug 772796 +

                      + + +
                      + +
                      +
                      +  
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug773262.html b/editor/libeditor/tests/test_bug773262.html new file mode 100644 index 0000000000..b0dc827559 --- /dev/null +++ b/editor/libeditor/tests/test_bug773262.html @@ -0,0 +1,63 @@ + + +Test for Bug 773262 + + +

                      Mozilla Bug 773262

                      + + diff --git a/editor/libeditor/tests/test_bug780035.html b/editor/libeditor/tests/test_bug780035.html new file mode 100644 index 0000000000..9992314888 --- /dev/null +++ b/editor/libeditor/tests/test_bug780035.html @@ -0,0 +1,23 @@ + + +Test for Bug 780035 + + + +Mozilla Bug 780035 +
                      + diff --git a/editor/libeditor/tests/test_bug780908.xhtml b/editor/libeditor/tests/test_bug780908.xhtml new file mode 100644 index 0000000000..590316ef46 --- /dev/null +++ b/editor/libeditor/tests/test_bug780908.xhtml @@ -0,0 +1,110 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug787432.html b/editor/libeditor/tests/test_bug787432.html new file mode 100644 index 0000000000..c73bb3c7ea --- /dev/null +++ b/editor/libeditor/tests/test_bug787432.html @@ -0,0 +1,17 @@ + + +Test for Bug 787432 + + +Mozilla Bug 787432 +
                      %
                      + diff --git a/editor/libeditor/tests/test_bug790475.html b/editor/libeditor/tests/test_bug790475.html new file mode 100644 index 0000000000..d30b14b312 --- /dev/null +++ b/editor/libeditor/tests/test_bug790475.html @@ -0,0 +1,90 @@ + + + + + Test for Bug 790475 + + + + + +Mozilla Bug 790475 +

                      + +
                      +
                      +
                      + +
                      This is a test
                      + + + diff --git a/editor/libeditor/tests/test_bug795418-2.html b/editor/libeditor/tests/test_bug795418-2.html new file mode 100644 index 0000000000..64a33398b4 --- /dev/null +++ b/editor/libeditor/tests/test_bug795418-2.html @@ -0,0 +1,90 @@ + + + + + + Test #2 for Bug 772796 + + + + + +Mozilla Bug 795418 +

                      + + +
                      Copy this
                      + + + +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug795418-3.html b/editor/libeditor/tests/test_bug795418-3.html new file mode 100644 index 0000000000..aae076069f --- /dev/null +++ b/editor/libeditor/tests/test_bug795418-3.html @@ -0,0 +1,89 @@ + + + + + + Test #3 for Bug 772796 + + + + + +Mozilla Bug 795418 +

                      + + +
                      Copy this
                      + + +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug795418-4.html b/editor/libeditor/tests/test_bug795418-4.html new file mode 100644 index 0000000000..1c71ee5894 --- /dev/null +++ b/editor/libeditor/tests/test_bug795418-4.html @@ -0,0 +1,70 @@ + + + + + + Test #4 for Bug 795418 + + + + + +Mozilla Bug 795418 +

                      + + +
                      Copy this
                      +
                      AB
                      + +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug795418-5.html b/editor/libeditor/tests/test_bug795418-5.html new file mode 100644 index 0000000000..562a225f3e --- /dev/null +++ b/editor/libeditor/tests/test_bug795418-5.html @@ -0,0 +1,69 @@ + + + + + + Test #5 for Bug 795418 + + + + + +Mozilla Bug 795418 +

                      + + +
                      Copy this
                      +
                      AB
                      + +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug795418-6.html b/editor/libeditor/tests/test_bug795418-6.html new file mode 100644 index 0000000000..ea6a62612b --- /dev/null +++ b/editor/libeditor/tests/test_bug795418-6.html @@ -0,0 +1,69 @@ + + + + + + Test #5 for Bug 795418 + + + + + +Mozilla Bug 795418 +

                      + + +
                      Copy this
                      +
                      AB
                      + +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug795418.html b/editor/libeditor/tests/test_bug795418.html new file mode 100644 index 0000000000..8e02d0b49f --- /dev/null +++ b/editor/libeditor/tests/test_bug795418.html @@ -0,0 +1,70 @@ + + + + + + Test for Bug 795418 + + + + + +Mozilla Bug 795418 +

                      + + +
                      Copy this
                      +
                      AB
                      + +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug795785.html b/editor/libeditor/tests/test_bug795785.html new file mode 100644 index 0000000000..485a6a20f6 --- /dev/null +++ b/editor/libeditor/tests/test_bug795785.html @@ -0,0 +1,146 @@ + + + + Test for Bug 795785 + + + + + + +Mozilla Bug 795785 +
                      + +
                      +
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug796839.html b/editor/libeditor/tests/test_bug796839.html new file mode 100644 index 0000000000..8fe1c36d56 --- /dev/null +++ b/editor/libeditor/tests/test_bug796839.html @@ -0,0 +1,17 @@ + + +Test for Bug 796839 + + +Mozilla Bug 796839 +

                      + diff --git a/editor/libeditor/tests/test_bug830600.html b/editor/libeditor/tests/test_bug830600.html new file mode 100644 index 0000000000..166ac187a2 --- /dev/null +++ b/editor/libeditor/tests/test_bug830600.html @@ -0,0 +1,97 @@ + + + + + + Test for Bug 830600 + + + + + + + Mozilla Bug 830600 +

                      + + +
                      +    
                      +  
                      + + diff --git a/editor/libeditor/tests/test_bug832025.html b/editor/libeditor/tests/test_bug832025.html new file mode 100644 index 0000000000..92c8b68b08 --- /dev/null +++ b/editor/libeditor/tests/test_bug832025.html @@ -0,0 +1,43 @@ + + + + + Test for Bug 832025 + + + + + +Mozilla Bug 832025 +
                      header1
                      + + + diff --git a/editor/libeditor/tests/test_bug850043.html b/editor/libeditor/tests/test_bug850043.html new file mode 100644 index 0000000000..681a5cb5fe --- /dev/null +++ b/editor/libeditor/tests/test_bug850043.html @@ -0,0 +1,59 @@ + + + + + Test for Bug 850043 + + + + + + + +Mozilla Bug 850043 +
                      + +
                      b邀󠄏辺󠄁
                      +
                      + + +
                      +
                      + + + diff --git a/editor/libeditor/tests/test_bug857487.html b/editor/libeditor/tests/test_bug857487.html new file mode 100644 index 0000000000..e9cec16ece --- /dev/null +++ b/editor/libeditor/tests/test_bug857487.html @@ -0,0 +1,68 @@ + + + + + Test for Bug 857487 + + + + + +Mozilla Bug 857487 +
                      + + + + + + + + + + + + + + + + + + +
                      abc
                      def
                      ghi
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug858918.html b/editor/libeditor/tests/test_bug858918.html new file mode 100644 index 0000000000..46f841bbce --- /dev/null +++ b/editor/libeditor/tests/test_bug858918.html @@ -0,0 +1,16 @@ + + +Test for Bug 858918 + + + +Mozilla Bug 858918 + + diff --git a/editor/libeditor/tests/test_bug915962.html b/editor/libeditor/tests/test_bug915962.html new file mode 100644 index 0000000000..42cf4e3d67 --- /dev/null +++ b/editor/libeditor/tests/test_bug915962.html @@ -0,0 +1,120 @@ + + + + + Test for Bug 915962 + + + + + + +Mozilla Bug 915962 +

                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug966155.html b/editor/libeditor/tests/test_bug966155.html new file mode 100644 index 0000000000..193d383b96 --- /dev/null +++ b/editor/libeditor/tests/test_bug966155.html @@ -0,0 +1,54 @@ + + + + + Test for Bug 966155 + + + + + +Mozilla Bug 966155 +

                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug966552.html b/editor/libeditor/tests/test_bug966552.html new file mode 100644 index 0000000000..f27ceb92d7 --- /dev/null +++ b/editor/libeditor/tests/test_bug966552.html @@ -0,0 +1,42 @@ + + + + + Test for Bug 966552 + + + + + +Mozilla Bug 966552 +

                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_bug974309.html b/editor/libeditor/tests/test_bug974309.html new file mode 100644 index 0000000000..67f720f2e4 --- /dev/null +++ b/editor/libeditor/tests/test_bug974309.html @@ -0,0 +1,74 @@ + + + + + Test for Bug 974309 + + + + + +Mozilla Bug 974309 +
                      +
                      + + + + + + + + + + + + + + + + + + +
                      abc
                      def
                      ghi
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_bug998188.html b/editor/libeditor/tests/test_bug998188.html new file mode 100644 index 0000000000..8038d2ef64 --- /dev/null +++ b/editor/libeditor/tests/test_bug998188.html @@ -0,0 +1,51 @@ + + + + + Test for Bug 998188 + + + + + +Mozilla Bug 998188 +

                      + +
                      abc
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_cmd_fontFace_with_tt.html b/editor/libeditor/tests/test_cmd_fontFace_with_tt.html new file mode 100644 index 0000000000..495076e9b5 --- /dev/null +++ b/editor/libeditor/tests/test_cmd_fontFace_with_tt.html @@ -0,0 +1,73 @@ + + + + Testing font face "tt" + + + + + +
                      +
                      + +
                      abc
                      + +
                      +
                      + + + + diff --git a/editor/libeditor/tests/test_composition_event_created_in_chrome.html b/editor/libeditor/tests/test_composition_event_created_in_chrome.html new file mode 100644 index 0000000000..11b24d3bc1 --- /dev/null +++ b/editor/libeditor/tests/test_composition_event_created_in_chrome.html @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + diff --git a/editor/libeditor/tests/test_contenteditable_focus.html b/editor/libeditor/tests/test_contenteditable_focus.html new file mode 100644 index 0000000000..34a35365f6 --- /dev/null +++ b/editor/libeditor/tests/test_contenteditable_focus.html @@ -0,0 +1,190 @@ + + + Test for contenteditable focus + + + + +
                      + First text in this document.
                      +
                      +
                      +
                      +
                      +
                      + editable contents.
                      +
                      +
                      +
                      +
                      +
                      + span element in noneditable in editor
                      +
                      +
                      +
                      +
                      +
                      + span element in editor
                      +
                      +
                      + other editor. +
                      +
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_contenteditable_text_input_handling.html b/editor/libeditor/tests/test_contenteditable_text_input_handling.html new file mode 100644 index 0000000000..cc579c56f2 --- /dev/null +++ b/editor/libeditor/tests/test_contenteditable_text_input_handling.html @@ -0,0 +1,314 @@ + + + Test for text input event handling on contenteditable editor + + + + + +
                      +

                      static content

                      +

                      content editable

                      +
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_cut_copy_delete_command_enabled.html b/editor/libeditor/tests/test_cut_copy_delete_command_enabled.html new file mode 100644 index 0000000000..98a591f56f --- /dev/null +++ b/editor/libeditor/tests/test_cut_copy_delete_command_enabled.html @@ -0,0 +1,71 @@ + + + + + + + Test for enabled state of cut/copy/delete commands + + + + + + + Mozilla Bug 1067255 + +
                      +    
                      +  
                      + + + + + diff --git a/editor/libeditor/tests/test_cut_copy_delete_command_enabled.xhtml b/editor/libeditor/tests/test_cut_copy_delete_command_enabled.xhtml new file mode 100644 index 0000000000..46c91e87d0 --- /dev/null +++ b/editor/libeditor/tests/test_cut_copy_delete_command_enabled.xhtml @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + diff --git a/editor/libeditor/tests/test_cut_copy_password.html b/editor/libeditor/tests/test_cut_copy_password.html new file mode 100644 index 0000000000..e15682cf97 --- /dev/null +++ b/editor/libeditor/tests/test_cut_copy_password.html @@ -0,0 +1,92 @@ + + + + Test for cut/copy in password field + + + + + + + + diff --git a/editor/libeditor/tests/test_documentCharacterSet.html b/editor/libeditor/tests/test_documentCharacterSet.html new file mode 100644 index 0000000000..d8ee10b06b --- /dev/null +++ b/editor/libeditor/tests/test_documentCharacterSet.html @@ -0,0 +1,59 @@ + + + + + + + +

                      + + + + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_dom_input_event_on_htmleditor.html b/editor/libeditor/tests/test_dom_input_event_on_htmleditor.html new file mode 100644 index 0000000000..05c3edcd1a --- /dev/null +++ b/editor/libeditor/tests/test_dom_input_event_on_htmleditor.html @@ -0,0 +1,1716 @@ + + + Test for input event of text editor + + + + + +
                      + + + + + +
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_dom_input_event_on_texteditor.html b/editor/libeditor/tests/test_dom_input_event_on_texteditor.html new file mode 100644 index 0000000000..983229e25a --- /dev/null +++ b/editor/libeditor/tests/test_dom_input_event_on_texteditor.html @@ -0,0 +1,942 @@ + + + Test for input event of text editor + + + + + +
                      + + +
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_dragdrop.html b/editor/libeditor/tests/test_dragdrop.html new file mode 100644 index 0000000000..df5cb487db --- /dev/null +++ b/editor/libeditor/tests/test_dragdrop.html @@ -0,0 +1,2641 @@ + + + + + + + + + + + +
                      +
                      + + + + diff --git a/editor/libeditor/tests/test_execCommandPaste_noTarget.html b/editor/libeditor/tests/test_execCommandPaste_noTarget.html new file mode 100644 index 0000000000..6586ca768d --- /dev/null +++ b/editor/libeditor/tests/test_execCommandPaste_noTarget.html @@ -0,0 +1,45 @@ + + + + + + + + + + + diff --git a/editor/libeditor/tests/test_handle_new_lines.html b/editor/libeditor/tests/test_handle_new_lines.html new file mode 100644 index 0000000000..0e5825aaad --- /dev/null +++ b/editor/libeditor/tests/test_handle_new_lines.html @@ -0,0 +1,129 @@ + + + + Test for TextEditor::HandleNewLinesInStringForSingleLineEditor() + + + + + +

                      + + +
                      + + + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_htmleditor_keyevent_handling.html b/editor/libeditor/tests/test_htmleditor_keyevent_handling.html new file mode 100644 index 0000000000..7b8df7bda9 --- /dev/null +++ b/editor/libeditor/tests/test_htmleditor_keyevent_handling.html @@ -0,0 +1,655 @@ + + + Test for key event handler of HTML editor + + + + + +
                      +

                      +
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_inlineTableEditing.html b/editor/libeditor/tests/test_inlineTableEditing.html new file mode 100644 index 0000000000..67bad26965 --- /dev/null +++ b/editor/libeditor/tests/test_inlineTableEditing.html @@ -0,0 +1,45 @@ + + + + + + + + +

                      + + +
                      + + + + +
                      ABCDEFGHIJKLMN
                      ABCDEFGHIJKLMN
                      ABCDEFGHIJKLMN
                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_inline_style_cache.html b/editor/libeditor/tests/test_inline_style_cache.html new file mode 100644 index 0000000000..188e879587 --- /dev/null +++ b/editor/libeditor/tests/test_inline_style_cache.html @@ -0,0 +1,227 @@ + + + + Tests for inline style cache + + + + + +

                      + + +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_insertParagraph_in_inline_editing_host.html b/editor/libeditor/tests/test_insertParagraph_in_inline_editing_host.html new file mode 100644 index 0000000000..ae276fd3ad --- /dev/null +++ b/editor/libeditor/tests/test_insertParagraph_in_inline_editing_host.html @@ -0,0 +1,67 @@ + + + + Test "insertParagraph" command in inline editing host + + + + + +foobar +
                      +

                      foobar

                      +
                      +
                      foobar
                      +
                      +

                      foobar

                      + +

                      +

                      + + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_keypress_untrusted_event.html b/editor/libeditor/tests/test_keypress_untrusted_event.html new file mode 100644 index 0000000000..5884e15db3 --- /dev/null +++ b/editor/libeditor/tests/test_keypress_untrusted_event.html @@ -0,0 +1,93 @@ + + + + + Test for untrusted keypress events + + + + +Mozilla Bug 622245 +

                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_label_contenteditable.html b/editor/libeditor/tests/test_label_contenteditable.html new file mode 100644 index 0000000000..43bf9d4292 --- /dev/null +++ b/editor/libeditor/tests/test_label_contenteditable.html @@ -0,0 +1,18 @@ + + + + + + diff --git a/editor/libeditor/tests/test_middle_click_paste.html b/editor/libeditor/tests/test_middle_click_paste.html new file mode 100644 index 0000000000..5bd527ede7 --- /dev/null +++ b/editor/libeditor/tests/test_middle_click_paste.html @@ -0,0 +1,667 @@ + + + + Test for paste with middle button click + + + + + +

                      + + +
                      + + + + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_nsIEditorMailSupport_insertAsCitedQuotation.html b/editor/libeditor/tests/test_nsIEditorMailSupport_insertAsCitedQuotation.html new file mode 100644 index 0000000000..118347f2ce --- /dev/null +++ b/editor/libeditor/tests/test_nsIEditorMailSupport_insertAsCitedQuotation.html @@ -0,0 +1,175 @@ + + + + Test for nsIEditorMailSupport.insertAsCitedQuotation() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsIEditor_insertLineBreak.html b/editor/libeditor/tests/test_nsIEditor_insertLineBreak.html new file mode 100644 index 0000000000..d09155efe9 --- /dev/null +++ b/editor/libeditor/tests/test_nsIEditor_insertLineBreak.html @@ -0,0 +1,420 @@ + + + + Test for nsIEditor.insertLineBreak() + + + + +
                      +
                      + + +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsIHTMLEditor_getElementOrParentByTagName.html b/editor/libeditor/tests/test_nsIHTMLEditor_getElementOrParentByTagName.html new file mode 100644 index 0000000000..c78ec6763d --- /dev/null +++ b/editor/libeditor/tests/test_nsIHTMLEditor_getElementOrParentByTagName.html @@ -0,0 +1,449 @@ + + + + Test for nsIHTMLEditor.getElementOrParentByTagName() + + + + +
                      +
                      +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsIHTMLEditor_getParagraphState.html b/editor/libeditor/tests/test_nsIHTMLEditor_getParagraphState.html new file mode 100644 index 0000000000..0297464c3f --- /dev/null +++ b/editor/libeditor/tests/test_nsIHTMLEditor_getParagraphState.html @@ -0,0 +1,156 @@ + + + + Test for nsIHTMLEditor.getParagraphState() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsIHTMLEditor_getSelectedElement.html b/editor/libeditor/tests/test_nsIHTMLEditor_getSelectedElement.html new file mode 100644 index 0000000000..009591c252 --- /dev/null +++ b/editor/libeditor/tests/test_nsIHTMLEditor_getSelectedElement.html @@ -0,0 +1,816 @@ + + + + Test for nsIHTMLEditor.getSelectedElement() + + + + + +
                      +
                      +
                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsIHTMLEditor_removeInlineProperty.html b/editor/libeditor/tests/test_nsIHTMLEditor_removeInlineProperty.html new file mode 100644 index 0000000000..1c0040c491 --- /dev/null +++ b/editor/libeditor/tests/test_nsIHTMLEditor_removeInlineProperty.html @@ -0,0 +1,424 @@ + + + + Test for nsIHTMLEditor.removeInlineProperty() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsIHTMLEditor_selectElement.html b/editor/libeditor/tests/test_nsIHTMLEditor_selectElement.html new file mode 100644 index 0000000000..1ac21635ea --- /dev/null +++ b/editor/libeditor/tests/test_nsIHTMLEditor_selectElement.html @@ -0,0 +1,131 @@ + + + + Test for nsIHTMLEditor.selectElement() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsIHTMLEditor_setBackgroundColor.html b/editor/libeditor/tests/test_nsIHTMLEditor_setBackgroundColor.html new file mode 100644 index 0000000000..1d67e7b688 --- /dev/null +++ b/editor/libeditor/tests/test_nsIHTMLEditor_setBackgroundColor.html @@ -0,0 +1,187 @@ + + + + Test for nsIHTMLEditor.setBackgroundColor() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsIHTMLEditor_setCaretAfterElement.html b/editor/libeditor/tests/test_nsIHTMLEditor_setCaretAfterElement.html new file mode 100644 index 0000000000..ff6bc4094b --- /dev/null +++ b/editor/libeditor/tests/test_nsIHTMLEditor_setCaretAfterElement.html @@ -0,0 +1,149 @@ + + + + Test for nsIHTMLEditor.setCaretAfterElement() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsIHTMLObjectResizer_hideResizers.html b/editor/libeditor/tests/test_nsIHTMLObjectResizer_hideResizers.html new file mode 100644 index 0000000000..39679a546d --- /dev/null +++ b/editor/libeditor/tests/test_nsIHTMLObjectResizer_hideResizers.html @@ -0,0 +1,54 @@ + + + + Test for nsIHTMLObjectResizer.hideResizers() + + + + + +

                      + + +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_nsITableEditor_deleteTableCell.html b/editor/libeditor/tests/test_nsITableEditor_deleteTableCell.html new file mode 100644 index 0000000000..3971b82d2b --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_deleteTableCell.html @@ -0,0 +1,722 @@ + + + + Test for nsITableEditor.deleteTableCell() + + + + +
                      +
                      +
                      out of table
                      default content
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_deleteTableCellContents.html b/editor/libeditor/tests/test_nsITableEditor_deleteTableCellContents.html new file mode 100644 index 0000000000..463d895a14 --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_deleteTableCellContents.html @@ -0,0 +1,301 @@ + + + + Test for nsITableEditor.deleteTableCellContents() + + + + +
                      +
                      +
                      out of table
                      default content
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_deleteTableColumn.html b/editor/libeditor/tests/test_nsITableEditor_deleteTableColumn.html new file mode 100644 index 0000000000..a87f6329bd --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_deleteTableColumn.html @@ -0,0 +1,525 @@ + + + + Test for nsITableEditor.deleteTableColumn() + + + + +
                      +
                      +
                      out of table
                      default content
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_deleteTableRow.html b/editor/libeditor/tests/test_nsITableEditor_deleteTableRow.html new file mode 100644 index 0000000000..1acf553951 --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_deleteTableRow.html @@ -0,0 +1,532 @@ + + + + Test for nsITableEditor.deleteTableRow() + + + + +
                      +
                      +
                      out of table
                      default content
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_getCellAt.html b/editor/libeditor/tests/test_nsITableEditor_getCellAt.html new file mode 100644 index 0000000000..230dc2b454 --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_getCellAt.html @@ -0,0 +1,139 @@ + + + + Test for nsITableEditor.getCellAt() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_getCellDataAt.html b/editor/libeditor/tests/test_nsITableEditor_getCellDataAt.html new file mode 100644 index 0000000000..3ace893cc7 --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_getCellDataAt.html @@ -0,0 +1,756 @@ + + + + Test for nsITableEditor.getCellDataAt() + + + + +
                      +
                      +
                      out of table
                      default content
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_getCellIndexes.html b/editor/libeditor/tests/test_nsITableEditor_getCellIndexes.html new file mode 100644 index 0000000000..d56e88dfb0 --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_getCellIndexes.html @@ -0,0 +1,92 @@ + + + + Test for nsITableEditor.getCellIndexes() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_getFirstRow.html b/editor/libeditor/tests/test_nsITableEditor_getFirstRow.html new file mode 100644 index 0000000000..9234538733 --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_getFirstRow.html @@ -0,0 +1,105 @@ + + + + Test for nsITableEditor.getFirstRow() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_getFirstSelectedCellInTable.html b/editor/libeditor/tests/test_nsITableEditor_getFirstSelectedCellInTable.html new file mode 100644 index 0000000000..f85c338f99 --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_getFirstSelectedCellInTable.html @@ -0,0 +1,201 @@ + + + + Test for nsITableEditor.getFirstSelectedCellInTable() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_getSelectedCells.html b/editor/libeditor/tests/test_nsITableEditor_getSelectedCells.html new file mode 100644 index 0000000000..cff75652df --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_getSelectedCells.html @@ -0,0 +1,295 @@ + + + + Test for nsITableEditor.getSelectedCells() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_getSelectedCellsType.html b/editor/libeditor/tests/test_nsITableEditor_getSelectedCellsType.html new file mode 100644 index 0000000000..93a6917e72 --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_getSelectedCellsType.html @@ -0,0 +1,274 @@ + + + + Test for nsITableEditor.getSelectedCellsType() + + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_getSelectedOrParentTableElement.html b/editor/libeditor/tests/test_nsITableEditor_getSelectedOrParentTableElement.html new file mode 100644 index 0000000000..665359545c --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_getSelectedOrParentTableElement.html @@ -0,0 +1,283 @@ + + + + Test for nsITableEditor.getSelectedOrParentTableElement() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_getTableSize.html b/editor/libeditor/tests/test_nsITableEditor_getTableSize.html new file mode 100644 index 0000000000..bc0974012c --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_getTableSize.html @@ -0,0 +1,95 @@ + + + + Test for nsITableEditor.getTableSize() + + + + +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_insertTableCell.html b/editor/libeditor/tests/test_nsITableEditor_insertTableCell.html new file mode 100644 index 0000000000..75c1ad4ca4 --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_insertTableCell.html @@ -0,0 +1,400 @@ + + + + Test for nsITableEditor.insertTableCell() + + + + +
                      +
                      +
                      out of table
                      default content
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_insertTableColumn.html b/editor/libeditor/tests/test_nsITableEditor_insertTableColumn.html new file mode 100644 index 0000000000..a7b8533481 --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_insertTableColumn.html @@ -0,0 +1,287 @@ + + + + Test for nsITableEditor.insertTableColumn() + + + + +
                      +
                      +
                      out of table
                      default content
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_nsITableEditor_insertTableRow.html b/editor/libeditor/tests/test_nsITableEditor_insertTableRow.html new file mode 100644 index 0000000000..8168355b1d --- /dev/null +++ b/editor/libeditor/tests/test_nsITableEditor_insertTableRow.html @@ -0,0 +1,307 @@ + + + + Test for nsITableEditor.insertTableRow() + + + + +
                      +
                      +
                      out of table
                      default content
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_password_input_with_unmasked_range.html b/editor/libeditor/tests/test_password_input_with_unmasked_range.html new file mode 100644 index 0000000000..205884219b --- /dev/null +++ b/editor/libeditor/tests/test_password_input_with_unmasked_range.html @@ -0,0 +1,417 @@ + + + + Test for inputting new text while there is unmasked range + + + + + + + + +
                      + + diff --git a/editor/libeditor/tests/test_password_paste.html b/editor/libeditor/tests/test_password_paste.html new file mode 100644 index 0000000000..3370e6da7b --- /dev/null +++ b/editor/libeditor/tests/test_password_paste.html @@ -0,0 +1,65 @@ + + + + Test for masking password + + + + + +

                      + + + + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_password_per_word_operation.html b/editor/libeditor/tests/test_password_per_word_operation.html new file mode 100644 index 0000000000..847f2e9854 --- /dev/null +++ b/editor/libeditor/tests/test_password_per_word_operation.html @@ -0,0 +1,148 @@ + + + + Test for operations in a password field + + + + + + + + + diff --git a/editor/libeditor/tests/test_password_unmask_API.html b/editor/libeditor/tests/test_password_unmask_API.html new file mode 100644 index 0000000000..2d1aa34015 --- /dev/null +++ b/editor/libeditor/tests/test_password_unmask_API.html @@ -0,0 +1,164 @@ + + + + Test for unmasking password API + + + + + + + + + diff --git a/editor/libeditor/tests/test_pasteImgTextarea.html b/editor/libeditor/tests/test_pasteImgTextarea.html new file mode 100644 index 0000000000..c19417e4c0 --- /dev/null +++ b/editor/libeditor/tests/test_pasteImgTextarea.html @@ -0,0 +1,19 @@ + + + + + + diff --git a/editor/libeditor/tests/test_pasteImgTextarea.xhtml b/editor/libeditor/tests/test_pasteImgTextarea.xhtml new file mode 100644 index 0000000000..2dbf0b6427 --- /dev/null +++ b/editor/libeditor/tests/test_pasteImgTextarea.xhtml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/editor/libeditor/tests/test_pasting_table_rows.html b/editor/libeditor/tests/test_pasting_table_rows.html new file mode 100644 index 0000000000..69c5d5c4dc --- /dev/null +++ b/editor/libeditor/tests/test_pasting_table_rows.html @@ -0,0 +1,532 @@ + + + + + Test pasting table rows + + + + + + + +

                      +

                      Test for bug 1639972

                      +
                      +
                      Table with tbody and td: + + + + + + + + + + + + + + + + + + + + + + + +
                      r1c1r1c2r1c3
                      r2c1r2c2r2c3
                      r3c1r3c2r3c3
                      r4c1r4c2r4c3
                      +
                      + +
                      Table with tbody, td and th: + + + + + + + + + + + + + + + + + + + + + + + +
                      r1c1r1c2r1c3
                      r2c1r2c2r2c3
                      r3c1r3c2r3c3
                      r4c1r4c2r4c3
                      +
                      + +
                      Table with thead, tbody, td: + + + + + + + + + + + + + + + + + + + + + + + + + +
                      r1c1r1c2r1c3
                      r2c1r2c2r2c3
                      r3c1r3c2r3c3
                      r4c1r4c2r4c3
                      +
                      + +
                      Table with thead, tbody, td and th: + + + + + + + + + + + + + + + + + + + + + + + + + +
                      r1c1r1c2r1c3
                      r2c1r2c2r2c3
                      r3c1r3c2r3c3
                      r4c1r4c2r4c3
                      +
                      +
                      Table with thead, + tbody, tfoot, and td: + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                      r1c1r1c2r1c3
                      r2c1r2c2r2c3
                      r3c1r3c2r3c3
                      r4c1r4c2r4c3
                      +
                      +

                      Target for pasting: +

                      X
                      +

                      +
                      + diff --git a/editor/libeditor/tests/test_pasting_text_longer_than_maxlength.html b/editor/libeditor/tests/test_pasting_text_longer_than_maxlength.html new file mode 100644 index 0000000000..d25875431e --- /dev/null +++ b/editor/libeditor/tests/test_pasting_text_longer_than_maxlength.html @@ -0,0 +1,53 @@ + + + + + Test pasting text longer than maxlength + + + + + +Mozilla Bug 1320229 +

                      +
                      +
                      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_resizers_appearance.html b/editor/libeditor/tests/test_resizers_appearance.html new file mode 100644 index 0000000000..e09c80f530 --- /dev/null +++ b/editor/libeditor/tests/test_resizers_appearance.html @@ -0,0 +1,109 @@ + + + + Test for resizers appearance + + + + + +

                      + + +
                      +
                      + +
                      +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_resizers_resizing_elements.html b/editor/libeditor/tests/test_resizers_resizing_elements.html new file mode 100644 index 0000000000..3e26f63527 --- /dev/null +++ b/editor/libeditor/tests/test_resizers_resizing_elements.html @@ -0,0 +1,312 @@ + + + + Test for resizers of some elements + + + + + + +

                      +
                      +
                      + +
                      +
                      +
                      + + diff --git a/editor/libeditor/tests/test_root_element_replacement.html b/editor/libeditor/tests/test_root_element_replacement.html new file mode 100644 index 0000000000..45765d9ab2 --- /dev/null +++ b/editor/libeditor/tests/test_root_element_replacement.html @@ -0,0 +1,140 @@ + + + Test for root element replacement + + + + + +

                      +

                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_sanitizer_on_paste.html b/editor/libeditor/tests/test_sanitizer_on_paste.html new file mode 100644 index 0000000000..09c6ff4fb2 --- /dev/null +++ b/editor/libeditor/tests/test_sanitizer_on_paste.html @@ -0,0 +1,48 @@ + + + + + Test pasting table rows + + + + + + +
                      Paste target
                      + + \ No newline at end of file diff --git a/editor/libeditor/tests/test_select_all_without_body.html b/editor/libeditor/tests/test_select_all_without_body.html new file mode 100644 index 0000000000..0e8dca9f3d --- /dev/null +++ b/editor/libeditor/tests/test_select_all_without_body.html @@ -0,0 +1,26 @@ + + + Test select all in HTML editor without body element + + + + +

                      +

                      + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_selection_move_commands.html b/editor/libeditor/tests/test_selection_move_commands.html new file mode 100644 index 0000000000..cb2f769a2a --- /dev/null +++ b/editor/libeditor/tests/test_selection_move_commands.html @@ -0,0 +1,225 @@ + +Test for nsSelectionMoveCommands + + + +Mozilla Bug 454004 + + + + diff --git a/editor/libeditor/tests/test_setting_value_longer_than_maxlength_with_setUserInput.html b/editor/libeditor/tests/test_setting_value_longer_than_maxlength_with_setUserInput.html new file mode 100644 index 0000000000..b7b9b40a6c --- /dev/null +++ b/editor/libeditor/tests/test_setting_value_longer_than_maxlength_with_setUserInput.html @@ -0,0 +1,75 @@ + + + + + + Test setting value longer than maxlength with setUserInput + + + + + + + Mozilla Bug 1320229 +
                      +
                      +
                      +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_spellcheck_pref.html b/editor/libeditor/tests/test_spellcheck_pref.html new file mode 100644 index 0000000000..8b0ea7f303 --- /dev/null +++ b/editor/libeditor/tests/test_spellcheck_pref.html @@ -0,0 +1,22 @@ + + + Test if spellcheck is turned on + + + + + + +
                      +
                      + + + + + diff --git a/editor/libeditor/tests/test_state_change_on_reframe.html b/editor/libeditor/tests/test_state_change_on_reframe.html new file mode 100644 index 0000000000..c74bf46ea7 --- /dev/null +++ b/editor/libeditor/tests/test_state_change_on_reframe.html @@ -0,0 +1,29 @@ + +Test for state change not bogusly changing during reframe (bug 1528644) + + + +
                      + +
                      + diff --git a/editor/libeditor/tests/test_textarea_value_not_include_cr.html b/editor/libeditor/tests/test_textarea_value_not_include_cr.html new file mode 100644 index 0000000000..492f583458 --- /dev/null +++ b/editor/libeditor/tests/test_textarea_value_not_include_cr.html @@ -0,0 +1,93 @@ + + + + Test for HTMLTextAreaElement.value not returning value including CR + + + + + +

                      + + + + + +

                  + + diff --git a/editor/libeditor/tests/test_texteditor_keyevent_handling.html b/editor/libeditor/tests/test_texteditor_keyevent_handling.html new file mode 100644 index 0000000000..2ecdf55254 --- /dev/null +++ b/editor/libeditor/tests/test_texteditor_keyevent_handling.html @@ -0,0 +1,376 @@ + + + Test for key event handler of text editor + + + + + +
                  + + + +
                  + +
                  +
                  + + + + + diff --git a/editor/libeditor/tests/test_typing_at_edge_of_anchor.html b/editor/libeditor/tests/test_typing_at_edge_of_anchor.html new file mode 100644 index 0000000000..2ea3f21d40 --- /dev/null +++ b/editor/libeditor/tests/test_typing_at_edge_of_anchor.html @@ -0,0 +1,476 @@ + + + + Test for typing after a link + + + + + +

                  +
                  +
                  + +
                  + +
                  +
                  +
                  + + diff --git a/editor/libeditor/tests/test_undo_after_spellchecker_replaces_word.html b/editor/libeditor/tests/test_undo_after_spellchecker_replaces_word.html new file mode 100644 index 0000000000..a34e6b21f1 --- /dev/null +++ b/editor/libeditor/tests/test_undo_after_spellchecker_replaces_word.html @@ -0,0 +1,179 @@ + + + + + + + + +
                  + +
                  abc abx abc
                  +
                  +
                  + + + + diff --git a/editor/libeditor/tests/test_undo_redo_stack_after_setting_value.html b/editor/libeditor/tests/test_undo_redo_stack_after_setting_value.html new file mode 100644 index 0000000000..3f98642bac --- /dev/null +++ b/editor/libeditor/tests/test_undo_redo_stack_after_setting_value.html @@ -0,0 +1,166 @@ + + + + + Test for Bug 1473515 + + + + + +Mozilla Bug 1473515 +

                  + + + + + +
                  +
                  +
                  +
                  + + diff --git a/editor/libeditor/tests/test_undo_with_editingui.html b/editor/libeditor/tests/test_undo_with_editingui.html new file mode 100644 index 0000000000..fe3565880e --- /dev/null +++ b/editor/libeditor/tests/test_undo_with_editingui.html @@ -0,0 +1,160 @@ + + + + Test for undo with editing UI + + + + + +

                  + + +
                  + + + +
                  ABCDEFGHIJKLMN
                  ABCDEFGHIJKLMN
                  +
                  test
                  + +
                  +
                  +
                  +
                  +
                  +
                  + + -- cgit v1.2.3