From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- editor/libeditor/CSSEditUtils.cpp | 1422 ++++ editor/libeditor/CSSEditUtils.h | 473 ++ editor/libeditor/ChangeAttributeTransaction.cpp | 98 + editor/libeditor/ChangeAttributeTransaction.h | 72 + editor/libeditor/ChangeStyleTransaction.cpp | 287 + editor/libeditor/ChangeStyleTransaction.h | 123 + editor/libeditor/CompositionTransaction.cpp | 332 + editor/libeditor/CompositionTransaction.h | 104 + editor/libeditor/CreateElementTransaction.cpp | 147 + editor/libeditor/CreateElementTransaction.h | 80 + editor/libeditor/DeleteNodeTransaction.cpp | 123 + editor/libeditor/DeleteNodeTransaction.h | 66 + editor/libeditor/DeleteRangeTransaction.cpp | 239 + editor/libeditor/DeleteRangeTransaction.h | 78 + editor/libeditor/DeleteTextTransaction.cpp | 102 + editor/libeditor/DeleteTextTransaction.h | 76 + editor/libeditor/EditActionListener.h | 17 + editor/libeditor/EditAggregateTransaction.cpp | 145 + editor/libeditor/EditAggregateTransaction.h | 58 + editor/libeditor/EditTransactionBase.cpp | 55 + editor/libeditor/EditTransactionBase.h | 44 + editor/libeditor/EditorBase.cpp | 5244 ++++++++++++ editor/libeditor/EditorBase.h | 1046 +++ editor/libeditor/EditorCommands.cpp | 1169 +++ editor/libeditor/EditorCommands.h | 106 + editor/libeditor/EditorController.cpp | 146 + editor/libeditor/EditorController.h | 37 + editor/libeditor/EditorEventListener.cpp | 1215 +++ editor/libeditor/EditorEventListener.h | 102 + editor/libeditor/EditorUtils.cpp | 227 + editor/libeditor/EditorUtils.h | 315 + editor/libeditor/EditorUtils.js | 34 + editor/libeditor/EditorUtils.manifest | 2 + editor/libeditor/HTMLAbsPositionEditor.cpp | 682 ++ editor/libeditor/HTMLAnonymousNodeEditor.cpp | 548 ++ editor/libeditor/HTMLEditRules.cpp | 8785 ++++++++++++++++++++ editor/libeditor/HTMLEditRules.h | 377 + editor/libeditor/HTMLEditUtils.cpp | 842 ++ editor/libeditor/HTMLEditUtils.h | 69 + editor/libeditor/HTMLEditor.cpp | 5289 ++++++++++++ editor/libeditor/HTMLEditor.h | 1109 +++ editor/libeditor/HTMLEditorDataTransfer.cpp | 2409 ++++++ editor/libeditor/HTMLEditorEventListener.cpp | 215 + editor/libeditor/HTMLEditorEventListener.h | 43 + editor/libeditor/HTMLEditorObjectResizer.cpp | 1059 +++ editor/libeditor/HTMLEditorObjectResizerUtils.h | 82 + editor/libeditor/HTMLInlineTableEditor.cpp | 283 + editor/libeditor/HTMLStyleEditor.cpp | 1752 ++++ editor/libeditor/HTMLTableEditor.cpp | 3458 ++++++++ editor/libeditor/HTMLURIRefObject.cpp | 262 + editor/libeditor/HTMLURIRefObject.h | 48 + editor/libeditor/InsertNodeTransaction.cpp | 97 + editor/libeditor/InsertNodeTransaction.h | 58 + editor/libeditor/InsertTextTransaction.cpp | 125 + editor/libeditor/InsertTextTransaction.h | 88 + editor/libeditor/InternetCiter.cpp | 366 + editor/libeditor/InternetCiter.h | 40 + editor/libeditor/JoinNodeTransaction.cpp | 109 + editor/libeditor/JoinNodeTransaction.h | 68 + editor/libeditor/PlaceholderTransaction.cpp | 270 + editor/libeditor/PlaceholderTransaction.h | 92 + editor/libeditor/SelectionState.cpp | 695 ++ editor/libeditor/SelectionState.h | 357 + editor/libeditor/SetDocumentTitleTransaction.cpp | 229 + editor/libeditor/SetDocumentTitleTransaction.h | 60 + editor/libeditor/SplitNodeTransaction.cpp | 128 + editor/libeditor/SplitNodeTransaction.h | 71 + editor/libeditor/StyleSheetTransactions.cpp | 157 + editor/libeditor/StyleSheetTransactions.h | 73 + editor/libeditor/TextEditRules.cpp | 1494 ++++ editor/libeditor/TextEditRules.h | 357 + editor/libeditor/TextEditRulesBidi.cpp | 100 + editor/libeditor/TextEditUtils.cpp | 113 + editor/libeditor/TextEditUtils.h | 47 + editor/libeditor/TextEditor.cpp | 1638 ++++ editor/libeditor/TextEditor.h | 246 + editor/libeditor/TextEditorDataTransfer.cpp | 472 ++ editor/libeditor/TextEditorTest.cpp | 259 + editor/libeditor/TextEditorTest.h | 42 + editor/libeditor/TypeInState.cpp | 397 + editor/libeditor/TypeInState.h | 111 + editor/libeditor/WSRunObject.cpp | 1926 +++++ editor/libeditor/WSRunObject.h | 411 + 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/1272490.html | 20 + editor/libeditor/crashtests/1317704.html | 36 + 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/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/crashtests.list | 71 + editor/libeditor/moz.build | 100 + editor/libeditor/nsIAbsorbingTransaction.h | 57 + editor/libeditor/nsIEditRules.h | 68 + editor/libeditor/tests/browser.ini | 6 + editor/libeditor/tests/browser_bug527935.js | 63 + editor/libeditor/tests/browser_bug629172.js | 106 + .../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 | 23 + .../browserscope/lib/richtext2/currentStatus.js | 1850 +++++ .../browserscope/lib/richtext2/current_revision | 1 + .../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 | 772 ++ .../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 | 233 + editor/libeditor/tests/bug527935.html | 11 + editor/libeditor/tests/bug629172.html | 15 + editor/libeditor/tests/chrome.ini | 14 + 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_bug549262.html | 8 + editor/libeditor/tests/file_bug586662.html | 7 + editor/libeditor/tests/file_bug674770-1.html | 5 + editor/libeditor/tests/file_bug915962.html | 13 + .../tests/file_select_all_without_body.html | 41 + editor/libeditor/tests/green.png | Bin 0 -> 334 bytes editor/libeditor/tests/mochitest.ini | 245 + editor/libeditor/tests/spellcheck.js | 20 + editor/libeditor/tests/test_CF_HTML_clipboard.html | 159 + editor/libeditor/tests/test_backspace_vs.html | 130 + editor/libeditor/tests/test_bug1026397.html | 103 + editor/libeditor/tests/test_bug1053048.html | 73 + editor/libeditor/tests/test_bug1067255.html | 57 + editor/libeditor/tests/test_bug1068979.html | 72 + editor/libeditor/tests/test_bug1094000.html | 104 + editor/libeditor/tests/test_bug1100966.html | 65 + editor/libeditor/tests/test_bug1101392.html | 78 + editor/libeditor/tests/test_bug1102906.html | 51 + editor/libeditor/tests/test_bug1109465.html | 69 + editor/libeditor/tests/test_bug1140105.html | 71 + editor/libeditor/tests/test_bug1140617.html | 37 + editor/libeditor/tests/test_bug1153237.html | 49 + editor/libeditor/tests/test_bug1154791.html | 67 + 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 | 81 + editor/libeditor/tests/test_bug1230473.html | 124 + editor/libeditor/tests/test_bug1247483.html | 61 + editor/libeditor/tests/test_bug1248128.html | 52 + editor/libeditor/tests/test_bug1248185.html | 57 + editor/libeditor/tests/test_bug1250010.html | 93 + editor/libeditor/tests/test_bug1257363.html | 182 + editor/libeditor/tests/test_bug1258085.html | 66 + editor/libeditor/tests/test_bug1268736.html | 64 + editor/libeditor/tests/test_bug1270235.html | 46 + editor/libeditor/tests/test_bug1310912.html | 93 + editor/libeditor/tests/test_bug1314790.html | 65 + editor/libeditor/tests/test_bug1315065.html | 145 + editor/libeditor/tests/test_bug1328023.html | 64 + editor/libeditor/tests/test_bug1330796.html | 101 + editor/libeditor/tests/test_bug1332876.html | 49 + editor/libeditor/tests/test_bug200416.html | 15 + editor/libeditor/tests/test_bug289384.html | 49 + editor/libeditor/tests/test_bug290026.html | 52 + editor/libeditor/tests/test_bug291780.html | 50 + 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_bug366682.html | 67 + editor/libeditor/tests/test_bug372345.html | 59 + editor/libeditor/tests/test_bug404320.html | 91 + editor/libeditor/tests/test_bug408231.html | 250 + editor/libeditor/tests/test_bug410986.html | 80 + editor/libeditor/tests/test_bug414526.html | 247 + editor/libeditor/tests/test_bug417418.html | 78 + editor/libeditor/tests/test_bug432225.html | 71 + editor/libeditor/tests/test_bug439808.html | 37 + editor/libeditor/tests/test_bug442186.html | 103 + editor/libeditor/tests/test_bug449243.html | 136 + editor/libeditor/tests/test_bug455992.html | 97 + editor/libeditor/tests/test_bug456244.html | 70 + editor/libeditor/tests/test_bug460740.html | 124 + editor/libeditor/tests/test_bug46555.html | 47 + editor/libeditor/tests/test_bug468353.html | 117 + editor/libeditor/tests/test_bug471319.html | 80 + editor/libeditor/tests/test_bug471722.html | 81 + editor/libeditor/tests/test_bug478725.html | 131 + editor/libeditor/tests/test_bug480647.html | 110 + editor/libeditor/tests/test_bug480972.html | 98 + editor/libeditor/tests/test_bug483651.html | 53 + editor/libeditor/tests/test_bug484181.html | 78 + editor/libeditor/tests/test_bug487524.html | 65 + editor/libeditor/tests/test_bug489202.xul | 81 + editor/libeditor/tests/test_bug490879.html | 45 + editor/libeditor/tests/test_bug502673.html | 108 + editor/libeditor/tests/test_bug514156.html | 50 + editor/libeditor/tests/test_bug520189.html | 621 ++ editor/libeditor/tests/test_bug525389.html | 198 + editor/libeditor/tests/test_bug537046.html | 51 + editor/libeditor/tests/test_bug549262.html | 132 + editor/libeditor/tests/test_bug550434.html | 42 + editor/libeditor/tests/test_bug551704.html | 125 + editor/libeditor/tests/test_bug552782.html | 47 + editor/libeditor/tests/test_bug567213.html | 58 + editor/libeditor/tests/test_bug569988.html | 99 + editor/libeditor/tests/test_bug570144.html | 123 + editor/libeditor/tests/test_bug578771.html | 63 + editor/libeditor/tests/test_bug586662.html | 60 + 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 | 55 + editor/libeditor/tests/test_bug596333.html | 124 + editor/libeditor/tests/test_bug596506.html | 60 + editor/libeditor/tests/test_bug597331.html | 72 + 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.xul | 70 + editor/libeditor/tests/test_bug600570.html | 80 + editor/libeditor/tests/test_bug602130.html | 45 + editor/libeditor/tests/test_bug603556.html | 48 + editor/libeditor/tests/test_bug604532.html | 42 + editor/libeditor/tests/test_bug607584.html | 41 + editor/libeditor/tests/test_bug607584.xul | 115 + editor/libeditor/tests/test_bug611182.html | 239 + editor/libeditor/tests/test_bug612128.html | 42 + editor/libeditor/tests/test_bug612447.html | 74 + editor/libeditor/tests/test_bug616590.xul | 105 + editor/libeditor/tests/test_bug620906.html | 50 + editor/libeditor/tests/test_bug622371.html | 40 + editor/libeditor/tests/test_bug625452.html | 66 + editor/libeditor/tests/test_bug629845.html | 60 + editor/libeditor/tests/test_bug635636.html | 65 + editor/libeditor/tests/test_bug636465.html | 54 + editor/libeditor/tests/test_bug638596.html | 37 + editor/libeditor/tests/test_bug640321.html | 190 + editor/libeditor/tests/test_bug641466.html | 46 + editor/libeditor/tests/test_bug645914.html | 63 + editor/libeditor/tests/test_bug646194.html | 38 + editor/libeditor/tests/test_bug668599.html | 73 + editor/libeditor/tests/test_bug674770-1.html | 86 + editor/libeditor/tests/test_bug674770-2.html | 395 + editor/libeditor/tests/test_bug674861.html | 185 + editor/libeditor/tests/test_bug676401.html | 119 + editor/libeditor/tests/test_bug677752.html | 107 + editor/libeditor/tests/test_bug681229.html | 51 + editor/libeditor/tests/test_bug686203.html | 50 + editor/libeditor/tests/test_bug692520.html | 42 + editor/libeditor/tests/test_bug697842.html | 117 + editor/libeditor/tests/test_bug725069.html | 35 + editor/libeditor/tests/test_bug735059.html | 22 + editor/libeditor/tests/test_bug738366.html | 24 + editor/libeditor/tests/test_bug740784.html | 48 + 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 | 223 + editor/libeditor/tests/test_bug773262.html | 63 + editor/libeditor/tests/test_bug780035.html | 22 + editor/libeditor/tests/test_bug780908.xul | 113 + editor/libeditor/tests/test_bug787432.html | 17 + editor/libeditor/tests/test_bug790475.html | 95 + editor/libeditor/tests/test_bug795418-2.html | 88 + editor/libeditor/tests/test_bug795418-3.html | 88 + editor/libeditor/tests/test_bug795418-4.html | 67 + editor/libeditor/tests/test_bug795418-5.html | 67 + editor/libeditor/tests/test_bug795418-6.html | 67 + editor/libeditor/tests/test_bug795418.html | 67 + editor/libeditor/tests/test_bug795785.html | 168 + editor/libeditor/tests/test_bug796839.html | 17 + editor/libeditor/tests/test_bug830600.html | 100 + editor/libeditor/tests/test_bug832025.html | 42 + editor/libeditor/tests/test_bug850043.html | 65 + editor/libeditor/tests/test_bug857487.html | 72 + editor/libeditor/tests/test_bug858918.html | 16 + editor/libeditor/tests/test_bug915962.html | 100 + editor/libeditor/tests/test_bug966155.html | 57 + editor/libeditor/tests/test_bug966552.html | 45 + editor/libeditor/tests/test_bug974309.html | 78 + editor/libeditor/tests/test_bug998188.html | 52 + .../test_composition_event_created_in_chrome.html | 82 + .../tests/test_contenteditable_focus.html | 209 + .../test_contenteditable_text_input_handling.html | 329 + .../tests/test_css_chrome_load_access.html | 67 + .../tests/test_dom_input_event_on_htmleditor.html | 182 + .../tests/test_dom_input_event_on_texteditor.html | 140 + editor/libeditor/tests/test_dragdrop.html | 178 + .../tests/test_htmleditor_keyevent_handling.html | 664 ++ .../tests/test_keypress_untrusted_event.html | 99 + .../tests/test_root_element_replacement.html | 148 + .../tests/test_select_all_without_body.html | 27 + .../tests/test_selection_move_commands.html | 219 + .../tests/test_set_document_title_transaction.html | 79 + editor/libeditor/tests/test_spellcheck_pref.html | 23 + .../tests/test_texteditor_keyevent_handling.html | 386 + 404 files changed, 89558 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/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/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/EditorUtils.js create mode 100644 editor/libeditor/EditorUtils.manifest create mode 100644 editor/libeditor/HTMLAbsPositionEditor.cpp create mode 100644 editor/libeditor/HTMLAnonymousNodeEditor.cpp create mode 100644 editor/libeditor/HTMLEditRules.cpp create mode 100644 editor/libeditor/HTMLEditRules.h 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/HTMLEditorDataTransfer.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/HTMLEditorObjectResizerUtils.h 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/HTMLURIRefObject.cpp create mode 100644 editor/libeditor/HTMLURIRefObject.h 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/PlaceholderTransaction.cpp create mode 100644 editor/libeditor/PlaceholderTransaction.h create mode 100644 editor/libeditor/SelectionState.cpp create mode 100644 editor/libeditor/SelectionState.h create mode 100644 editor/libeditor/SetDocumentTitleTransaction.cpp create mode 100644 editor/libeditor/SetDocumentTitleTransaction.h create mode 100644 editor/libeditor/SplitNodeTransaction.cpp create mode 100644 editor/libeditor/SplitNodeTransaction.h create mode 100644 editor/libeditor/StyleSheetTransactions.cpp create mode 100644 editor/libeditor/StyleSheetTransactions.h create mode 100644 editor/libeditor/TextEditRules.cpp create mode 100644 editor/libeditor/TextEditRules.h create mode 100644 editor/libeditor/TextEditRulesBidi.cpp create mode 100644 editor/libeditor/TextEditUtils.cpp create mode 100644 editor/libeditor/TextEditUtils.h 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/TextEditorTest.cpp create mode 100644 editor/libeditor/TextEditorTest.h 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/1272490.html create mode 100644 editor/libeditor/crashtests/1317704.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/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/crashtests.list create mode 100644 editor/libeditor/moz.build create mode 100644 editor/libeditor/nsIAbsorbingTransaction.h create mode 100644 editor/libeditor/nsIEditRules.h create mode 100644 editor/libeditor/tests/browser.ini create mode 100644 editor/libeditor/tests/browser_bug527935.js create mode 100644 editor/libeditor/tests/browser_bug629172.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/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/bug629172.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_bug549262.html create mode 100644 editor/libeditor/tests/file_bug586662.html create mode 100644 editor/libeditor/tests/file_bug674770-1.html create mode 100644 editor/libeditor/tests/file_bug915962.html 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_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_bug1067255.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_bug1101392.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_bug1140105.html create mode 100644 editor/libeditor/tests/test_bug1140617.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_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_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_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_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_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_bug468353.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_bug487524.html create mode 100644 editor/libeditor/tests/test_bug489202.xul 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.xul 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.xul 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.xul 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_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_bug640321.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.xul 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_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_css_chrome_load_access.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_htmleditor_keyevent_handling.html create mode 100644 editor/libeditor/tests/test_keypress_untrusted_event.html create mode 100644 editor/libeditor/tests/test_root_element_replacement.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_set_document_title_transaction.html create mode 100644 editor/libeditor/tests/test_spellcheck_pref.html create mode 100644 editor/libeditor/tests/test_texteditor_keyevent_handling.html (limited to 'editor/libeditor') diff --git a/editor/libeditor/CSSEditUtils.cpp b/editor/libeditor/CSSEditUtils.cpp new file mode 100644 index 000000000..5199838c0 --- /dev/null +++ b/editor/libeditor/CSSEditUtils.cpp @@ -0,0 +1,1422 @@ +/* -*- 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/DeclarationBlockInlines.h" +#include "mozilla/css/StyleRule.h" +#include "mozilla/dom/Element.h" +#include "mozilla/mozalloc.h" +#include "nsAString.h" +#include "nsCOMPtr.h" +#include "nsColor.h" +#include "nsComputedDOMStyle.h" +#include "nsDebug.h" +#include "nsDependentSubstring.h" +#include "nsError.h" +#include "nsGkAtoms.h" +#include "nsIAtom.h" +#include "nsIContent.h" +#include "nsIDOMCSSStyleDeclaration.h" +#include "nsIDOMElement.h" +#include "nsIDOMNode.h" +#include "nsIDOMWindow.h" +#include "nsIDocument.h" +#include "nsIEditor.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 "nsSubstringTuple.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(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(aPrependString, aOutputString); + } + aOutputString.Append(*aInputString); + if (aAppendString) { + AppendASCIItoUTF16(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"); + } + } +} + +const CSSEditUtils::CSSEquivTable boldEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_font_weight, ProcessBValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable italicEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_font_style, ProcessDefaultValue, "italic", nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable underlineEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_text_decoration, ProcessDefaultValue, "underline", nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable strikeEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_text_decoration, ProcessDefaultValue, "line-through", nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable ttEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_font_family, ProcessDefaultValue, "monospace", nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable fontColorEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_color, ProcessSameValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable fontFaceEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_font_family, ProcessSameValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable bgcolorEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_background_color, ProcessSameValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable backgroundImageEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_background_image, ProcessExtendedValue, nullptr, "url(", ")", true, true }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable textColorEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_color, ProcessSameValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable borderEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_border, ProcessExtendedValue, nullptr, nullptr, "px solid", true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable textAlignEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_text_align, ProcessSameValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable captionAlignEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_caption_side, ProcessSameValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable verticalAlignEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_vertical_align, ProcessSameValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable nowrapEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_whitespace, ProcessDefaultValue, "nowrap", nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable widthEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_width, ProcessLengthValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable heightEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_height, ProcessLengthValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable listStyleTypeEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_list_style_type, ProcessListStyleTypeValue, nullptr, nullptr, nullptr, true, true }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable tableAlignEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_text_align, ProcessDefaultValue, "left", nullptr, nullptr, false, false }, + { CSSEditUtils::eCSSEditableProperty_margin_left, ProcessMarginLeftValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_margin_right, ProcessMarginRightValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +const CSSEditUtils::CSSEquivTable hrAlignEquivTable[] = { + { CSSEditUtils::eCSSEditableProperty_margin_left, ProcessMarginLeftValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_margin_right, ProcessMarginRightValue, nullptr, nullptr, nullptr, true, false }, + { CSSEditUtils::eCSSEditableProperty_NONE, 0 } +}; + +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); +} + +CSSEditUtils::~CSSEditUtils() +{ +} + +// Answers true if we have some CSS equivalence for the HTML style defined +// by aProperty and/or aAttribute for the node aNode +bool +CSSEditUtils::IsCSSEditableProperty(nsINode* aNode, + nsIAtom* aProperty, + const nsAString* aAttribute) +{ + MOZ_ASSERT(aNode); + + nsINode* node = aNode; + // we need an element node here + if (node->NodeType() == nsIDOMNode::TEXT_NODE) { + node = node->GetParentNode(); + NS_ENSURE_TRUE(node, 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->EqualsLiteral("color") || + aAttribute->EqualsLiteral("face")))) { + return true; + } + + // ALIGN attribute on elements supporting it + if (aAttribute && (aAttribute->EqualsLiteral("align")) && + node->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 && (aAttribute->EqualsLiteral("valign")) && + node->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 (aAttribute && node->IsHTMLElement(nsGkAtoms::body) && + (aAttribute->EqualsLiteral("text") + || aAttribute->EqualsLiteral("background") + || aAttribute->EqualsLiteral("bgcolor"))) { + return true; + } + + // attribute BGCOLOR on other elements + if (aAttribute && aAttribute->EqualsLiteral("bgcolor")) { + return true; + } + + // attributes HEIGHT, WIDTH and NOWRAP on TD and TH + if (aAttribute && + node->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th) && + (aAttribute->EqualsLiteral("height") + || aAttribute->EqualsLiteral("width") + || aAttribute->EqualsLiteral("nowrap"))) { + return true; + } + + // attributes HEIGHT and WIDTH on TABLE + if (aAttribute && node->IsHTMLElement(nsGkAtoms::table) && + (aAttribute->EqualsLiteral("height") + || aAttribute->EqualsLiteral("width"))) { + return true; + } + + // attributes SIZE and WIDTH on HR + if (aAttribute && node->IsHTMLElement(nsGkAtoms::hr) && + (aAttribute->EqualsLiteral("size") + || aAttribute->EqualsLiteral("width"))) { + return true; + } + + // attribute TYPE on OL UL LI + if (aAttribute && + node->IsAnyOfHTMLElements(nsGkAtoms::ol, nsGkAtoms::ul, + nsGkAtoms::li) && + aAttribute->EqualsLiteral("type")) { + return true; + } + + if (aAttribute && node->IsHTMLElement(nsGkAtoms::img) && + (aAttribute->EqualsLiteral("border") + || aAttribute->EqualsLiteral("width") + || aAttribute->EqualsLiteral("height"))) { + return true; + } + + // other elements that we can align using CSS even if they + // can't carry the html ALIGN attribute + if (aAttribute && aAttribute->EqualsLiteral("align") && + node->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 aElement +nsresult +CSSEditUtils::SetCSSProperty(Element& aElement, + nsIAtom& aProperty, + const nsAString& aValue, + bool aSuppressTxn) +{ + RefPtr transaction = + CreateCSSPropertyTxn(aElement, aProperty, aValue, + ChangeStyleTransaction::eSet); + if (aSuppressTxn) { + return transaction->DoTransaction(); + } + return mHTMLEditor->DoTransaction(transaction); +} + +nsresult +CSSEditUtils::SetCSSPropertyPixels(Element& aElement, + nsIAtom& aProperty, + int32_t aIntValue) +{ + nsAutoString s; + s.AppendInt(aIntValue); + return SetCSSProperty(aElement, aProperty, s + NS_LITERAL_STRING("px"), + /* suppress txn */ false); +} + +// 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::RemoveCSSProperty(Element& aElement, + nsIAtom& aProperty, + const nsAString& aValue, + bool aSuppressTxn) +{ + RefPtr transaction = + CreateCSSPropertyTxn(aElement, aProperty, aValue, + ChangeStyleTransaction::eRemove); + if (aSuppressTxn) { + return transaction->DoTransaction(); + } + return mHTMLEditor->DoTransaction(transaction); +} + +already_AddRefed +CSSEditUtils::CreateCSSPropertyTxn( + Element& aElement, + nsIAtom& aAttribute, + const nsAString& aValue, + ChangeStyleTransaction::EChangeType aChangeType) +{ + RefPtr transaction = + new ChangeStyleTransaction(aElement, aAttribute, aValue, aChangeType); + return transaction.forget(); +} + +nsresult +CSSEditUtils::GetSpecifiedProperty(nsINode& aNode, + nsIAtom& aProperty, + nsAString& aValue) +{ + return GetCSSInlinePropertyBase(&aNode, &aProperty, aValue, eSpecified); +} + +nsresult +CSSEditUtils::GetComputedProperty(nsINode& aNode, + nsIAtom& aProperty, + nsAString& aValue) +{ + return GetCSSInlinePropertyBase(&aNode, &aProperty, aValue, eComputed); +} + +nsresult +CSSEditUtils::GetCSSInlinePropertyBase(nsINode* aNode, + nsIAtom* aProperty, + nsAString& aValue, + StyleType aStyleType) +{ + MOZ_ASSERT(aNode && aProperty); + aValue.Truncate(); + + nsCOMPtr element = GetElementContainerOrSelf(aNode); + NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER); + + if (aStyleType == eComputed) { + // Get the all the computed css styles attached to the element node + RefPtr cssDecl = GetComputedStyle(element); + NS_ENSURE_STATE(cssDecl); + + // from these declarations, get the one we want and that one only + MOZ_ALWAYS_SUCCEEDS( + cssDecl->GetPropertyValue(nsDependentAtomString(aProperty), aValue)); + + return NS_OK; + } + + MOZ_ASSERT(aStyleType == eSpecified); + RefPtr decl = element->GetInlineStyleDeclaration(); + if (!decl) { + return NS_OK; + } + if (decl->IsServo()) { + MOZ_CRASH("stylo: not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; + } + nsCSSPropertyID prop = + nsCSSProps::LookupProperty(nsDependentAtomString(aProperty), + CSSEnabledState::eForAllContent); + MOZ_ASSERT(prop != eCSSProperty_UNKNOWN); + decl->AsGecko()->GetPropertyValueByID(prop, aValue); + + return NS_OK; +} + +already_AddRefed +CSSEditUtils::GetComputedStyle(Element* aElement) +{ + MOZ_ASSERT(aElement); + + nsIDocument* doc = aElement->GetUncomposedDoc(); + NS_ENSURE_TRUE(doc, nullptr); + + nsIPresShell* presShell = doc->GetShell(); + NS_ENSURE_TRUE(presShell, nullptr); + + RefPtr style = + NS_NewComputedDOMStyle(aElement, EmptyString(), presShell); + + return style.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::RemoveCSSInlineStyle(nsIDOMNode* aNode, + nsIAtom* aProperty, + const nsAString& aPropertyValue) +{ + nsCOMPtr element = do_QueryInterface(aNode); + NS_ENSURE_STATE(element); + + // remove the property from the style attribute + nsresult rv = RemoveCSSProperty(*element, *aProperty, aPropertyValue); + NS_ENSURE_SUCCESS(rv, rv); + + if (!element->IsHTMLElement(nsGkAtoms::span) || + HTMLEditor::HasAttributes(element)) { + return NS_OK; + } + + return mHTMLEditor->RemoveContainer(element); +} + +// Answers true if the property can be removed by setting a "none" CSS value +// on a node +bool +CSSEditUtils::IsCSSInvertible(nsIAtom& aProperty, + const nsAString* aAttribute) +{ + return nsGkAtoms::b == &aProperty; +} + +// Get the default browser background color if we need it for GetCSSBackgroundColorState +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 +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"); + } +} + +// Unfortunately, CSSStyleDeclaration::GetPropertyCSSValue is not yet +// implemented... We need then a way to determine the number part and the unit +// from aString, aString being the result of a GetPropertyValue query... +void +CSSEditUtils::ParseLength(const nsAString& aString, + float* aValue, + nsIAtom** 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(); +} + +void +CSSEditUtils::GetCSSPropertyAtom(nsCSSEditableProperty aProperty, + nsIAtom** aAtom) +{ + *aAtom = nullptr; + switch (aProperty) { + case eCSSEditableProperty_background_color: + *aAtom = nsGkAtoms::backgroundColor; + break; + case eCSSEditableProperty_background_image: + *aAtom = nsGkAtoms::background_image; + break; + case eCSSEditableProperty_border: + *aAtom = nsGkAtoms::border; + break; + case eCSSEditableProperty_caption_side: + *aAtom = nsGkAtoms::caption_side; + break; + case eCSSEditableProperty_color: + *aAtom = nsGkAtoms::color; + break; + case eCSSEditableProperty_float: + *aAtom = nsGkAtoms::_float; + break; + case eCSSEditableProperty_font_family: + *aAtom = nsGkAtoms::font_family; + break; + case eCSSEditableProperty_font_size: + *aAtom = nsGkAtoms::font_size; + break; + case eCSSEditableProperty_font_style: + *aAtom = nsGkAtoms::font_style; + break; + case eCSSEditableProperty_font_weight: + *aAtom = nsGkAtoms::fontWeight; + break; + case eCSSEditableProperty_height: + *aAtom = nsGkAtoms::height; + break; + case eCSSEditableProperty_list_style_type: + *aAtom = nsGkAtoms::list_style_type; + break; + case eCSSEditableProperty_margin_left: + *aAtom = nsGkAtoms::marginLeft; + break; + case eCSSEditableProperty_margin_right: + *aAtom = nsGkAtoms::marginRight; + break; + case eCSSEditableProperty_text_align: + *aAtom = nsGkAtoms::textAlign; + break; + case eCSSEditableProperty_text_decoration: + *aAtom = nsGkAtoms::text_decoration; + break; + case eCSSEditableProperty_vertical_align: + *aAtom = nsGkAtoms::vertical_align; + break; + case eCSSEditableProperty_whitespace: + *aAtom = nsGkAtoms::white_space; + break; + case eCSSEditableProperty_width: + *aAtom = nsGkAtoms::width; + break; + case eCSSEditableProperty_NONE: + // intentionally empty + break; + } +} + +// Populate aProperty and aValueArray with the CSS declarations equivalent to the +// value aValue according to the equivalence table aEquivTable +void +CSSEditUtils::BuildCSSDeclarations(nsTArray& aPropertyArray, + nsTArray& aValueArray, + const CSSEquivTable* aEquivTable, + const nsAString* aValue, + bool aGetOrRemoveRequest) +{ + // clear arrays + aPropertyArray.Clear(); + aValueArray.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; + nsIAtom * cssPropertyAtom; + // 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); + GetCSSPropertyAtom(cssProperty, &cssPropertyAtom); + aPropertyArray.AppendElement(cssPropertyAtom); + aValueArray.AppendElement(cssValue); + } + index++; + cssProperty = aEquivTable[index].cssProperty; + } +} + +// Populate cssPropertyArray and cssValueArray with the declarations equivalent +// to aHTMLProperty/aAttribute/aValue for the node aNode +void +CSSEditUtils::GenerateCSSDeclarationsFromHTMLStyle( + Element* aElement, + nsIAtom* aHTMLProperty, + const nsAString* aAttribute, + const nsAString* aValue, + nsTArray& cssPropertyArray, + nsTArray& cssValueArray, + bool aGetOrRemoveRequest) +{ + MOZ_ASSERT(aElement); + 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->EqualsLiteral("color")) { + equivTable = fontColorEquivTable; + } else if (nsGkAtoms::font == aHTMLProperty && + aAttribute->EqualsLiteral("face")) { + equivTable = fontFaceEquivTable; + } else if (aAttribute->EqualsLiteral("bgcolor")) { + equivTable = bgcolorEquivTable; + } else if (aAttribute->EqualsLiteral("background")) { + equivTable = backgroundImageEquivTable; + } else if (aAttribute->EqualsLiteral("text")) { + equivTable = textColorEquivTable; + } else if (aAttribute->EqualsLiteral("border")) { + equivTable = borderEquivTable; + } else if (aAttribute->EqualsLiteral("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->EqualsLiteral("valign")) { + equivTable = verticalAlignEquivTable; + } else if (aAttribute->EqualsLiteral("nowrap")) { + equivTable = nowrapEquivTable; + } else if (aAttribute->EqualsLiteral("width")) { + equivTable = widthEquivTable; + } else if (aAttribute->EqualsLiteral("height") || + (aElement->IsHTMLElement(nsGkAtoms::hr) && + aAttribute->EqualsLiteral("size"))) { + equivTable = heightEquivTable; + } else if (aAttribute->EqualsLiteral("type") && + aElement->IsAnyOfHTMLElements(nsGkAtoms::ol, + nsGkAtoms::ul, + nsGkAtoms::li)) { + equivTable = listStyleTypeEquivTable; + } + } + if (equivTable) { + BuildCSSDeclarations(cssPropertyArray, cssValueArray, 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. +int32_t +CSSEditUtils::SetCSSEquivalentToHTMLStyle(Element* aElement, + nsIAtom* aProperty, + const nsAString* aAttribute, + const nsAString* aValue, + bool aSuppressTransaction) +{ + MOZ_ASSERT(aElement && aProperty); + MOZ_ASSERT_IF(aAttribute, aValue); + int32_t count; + // This can only fail if SetCSSProperty fails, which should only happen if + // something is pretty badly wrong. In this case we assert so that hopefully + // someone will notice, but there's nothing more sensible to do than just + // return the count and carry on. + nsresult rv = SetCSSEquivalentToHTMLStyle(aElement->AsDOMNode(), + aProperty, aAttribute, + aValue, &count, + aSuppressTransaction); + NS_ASSERTION(NS_SUCCEEDED(rv), "SetCSSEquivalentToHTMLStyle failed"); + NS_ENSURE_SUCCESS(rv, count); + return count; +} + +nsresult +CSSEditUtils::SetCSSEquivalentToHTMLStyle(nsIDOMNode* aNode, + nsIAtom* aHTMLProperty, + const nsAString* aAttribute, + const nsAString* aValue, + int32_t* aCount, + bool aSuppressTransaction) +{ + nsCOMPtr element = do_QueryInterface(aNode); + *aCount = 0; + if (!element || !IsCSSEditableProperty(element, 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(element, aHTMLProperty, aAttribute, + aValue, cssPropertyArray, cssValueArray, + false); + + // set the individual CSS inline styles + *aCount = cssPropertyArray.Length(); + for (int32_t index = 0; index < *aCount; index++) { + nsresult rv = SetCSSProperty(*element, *cssPropertyArray[index], + cssValueArray[index], aSuppressTransaction); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} + +// Remove from aNode the CSS inline style equivalent to HTMLProperty/aAttribute/aValue for the node +nsresult +CSSEditUtils::RemoveCSSEquivalentToHTMLStyle(nsIDOMNode* aNode, + nsIAtom* aHTMLProperty, + const nsAString* aAttribute, + const nsAString* aValue, + bool aSuppressTransaction) +{ + nsCOMPtr element = do_QueryInterface(aNode); + NS_ENSURE_TRUE(element, NS_OK); + + return RemoveCSSEquivalentToHTMLStyle(element, aHTMLProperty, aAttribute, + aValue, aSuppressTransaction); +} + +nsresult +CSSEditUtils::RemoveCSSEquivalentToHTMLStyle(Element* aElement, + nsIAtom* aHTMLProperty, + const nsAString* aAttribute, + const nsAString* aValue, + bool aSuppressTransaction) +{ + MOZ_ASSERT(aElement); + + if (!IsCSSEditableProperty(aElement, 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(aElement, aHTMLProperty, aAttribute, + aValue, cssPropertyArray, cssValueArray, + true); + + // remove the individual CSS inline styles + int32_t count = cssPropertyArray.Length(); + for (int32_t index = 0; index < count; index++) { + nsresult rv = RemoveCSSProperty(*aElement, + *cssPropertyArray[index], + cssValueArray[index], + aSuppressTransaction); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} + +// returns in aValueString the list of values for the CSS equivalences to +// the HTML style aHTMLProperty/aAttribute/aValueString for the node aNode; +// the value of aStyleType controls the styles we retrieve : specified or +// computed. +nsresult +CSSEditUtils::GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode, + nsIAtom* aHTMLProperty, + const nsAString* aAttribute, + nsAString& aValueString, + StyleType aStyleType) +{ + aValueString.Truncate(); + nsCOMPtr theElement = GetElementContainerOrSelf(aNode); + NS_ENSURE_TRUE(theElement, NS_ERROR_NULL_POINTER); + + 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 + nsresult rv = GetCSSInlinePropertyBase(theElement, cssPropertyArray[index], + valueString, aStyleType); + NS_ENSURE_SUCCESS(rv, rv); + // append the value to aValueString (possibly with a leading whitespace) + if (index) { + aValueString.Append(char16_t(' ')); + } + aValueString.Append(valueString); + } + return NS_OK; +} + +// Does the node aNode (or its parent, if it's not an element node) have a CSS +// style equivalent to the HTML style aHTMLProperty/aHTMLAttribute/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. +bool +CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode, + nsIAtom* aProperty, + const nsAString* aAttribute, + const nsAString& aValue, + StyleType aStyleType) +{ + // Use aValue as only an in param, not in-out + nsAutoString value(aValue); + return IsCSSEquivalentToHTMLInlineStyleSet(aNode, aProperty, aAttribute, + value, aStyleType); +} + +bool +CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode, + nsIAtom* aProperty, + const nsAString* aAttribute, + nsAString& aValue, + StyleType aStyleType) +{ + MOZ_ASSERT(aNode && aProperty); + bool isSet; + nsresult rv = IsCSSEquivalentToHTMLInlineStyleSet(aNode->AsDOMNode(), + aProperty, aAttribute, + isSet, aValue, aStyleType); + NS_ENSURE_SUCCESS(rv, false); + return isSet; +} + +nsresult +CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet( + nsIDOMNode* aNode, + nsIAtom* aHTMLProperty, + const nsAString* aHTMLAttribute, + bool& aIsSet, + nsAString& valueString, + StyleType aStyleType) +{ + NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER); + + nsAutoString htmlValueString(valueString); + aIsSet = false; + nsCOMPtr node = do_QueryInterface(aNode); + do { + valueString.Assign(htmlValueString); + // get the value of the CSS equivalent styles + nsresult rv = + GetCSSEquivalentToHTMLInlineStyleSet(node, aHTMLProperty, aHTMLAttribute, + valueString, aStyleType); + NS_ENSURE_SUCCESS(rv, rv); + + // early way out if we can + if (valueString.IsEmpty()) { + return NS_OK; + } + + if (nsGkAtoms::b == aHTMLProperty) { + if (valueString.EqualsLiteral("bold")) { + aIsSet = true; + } else if (valueString.EqualsLiteral("normal")) { + aIsSet = false; + } else if (valueString.EqualsLiteral("bolder")) { + aIsSet = true; + valueString.AssignLiteral("bold"); + } else { + int32_t weight = 0; + nsresult errorCode; + nsAutoString value(valueString); + weight = value.ToInteger(&errorCode); + if (400 < weight) { + aIsSet = true; + valueString.AssignLiteral("bold"); + } else { + aIsSet = false; + valueString.AssignLiteral("normal"); + } + } + } else if (nsGkAtoms::i == aHTMLProperty) { + if (valueString.EqualsLiteral("italic") || + valueString.EqualsLiteral("oblique")) { + aIsSet = true; + } + } else if (nsGkAtoms::u == aHTMLProperty) { + nsAutoString val; + val.AssignLiteral("underline"); + aIsSet = ChangeStyleTransaction::ValueIncludes(valueString, val); + } else if (nsGkAtoms::strike == aHTMLProperty) { + nsAutoString val; + val.AssignLiteral("line-through"); + aIsSet = ChangeStyleTransaction::ValueIncludes(valueString, val); + } else if (aHTMLAttribute && + ((nsGkAtoms::font == aHTMLProperty && + aHTMLAttribute->EqualsLiteral("color")) || + aHTMLAttribute->EqualsLiteral("bgcolor"))) { + if (htmlValueString.IsEmpty()) { + aIsSet = 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("); + + NS_NAMED_LITERAL_STRING(comma, ", "); + + 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(')')); + } + + aIsSet = htmlColor.Equals(valueString, + nsCaseInsensitiveStringComparator()); + } else { + aIsSet = htmlValueString.Equals(valueString, + nsCaseInsensitiveStringComparator()); + } + } + } else if (nsGkAtoms::tt == aHTMLProperty) { + aIsSet = StringBeginsWith(valueString, NS_LITERAL_STRING("monospace")); + } else if (nsGkAtoms::font == aHTMLProperty && aHTMLAttribute && + aHTMLAttribute->EqualsLiteral("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(valueString); + valueStringNorm.ReplaceSubstring(commaSpace, comma); + aIsSet = htmlValueString.Equals(valueStringNorm, + nsCaseInsensitiveStringComparator()); + } else { + aIsSet = true; + } + return NS_OK; + } else if (aHTMLAttribute && aHTMLAttribute->EqualsLiteral("align")) { + aIsSet = true; + } else { + aIsSet = false; + return NS_OK; + } + + if (!htmlValueString.IsEmpty() && + htmlValueString.Equals(valueString, + nsCaseInsensitiveStringComparator())) { + aIsSet = true; + } + + if (htmlValueString.EqualsLiteral("-moz-editor-invert-value")) { + aIsSet = !aIsSet; + } + + if (nsGkAtoms::u == aHTMLProperty || nsGkAtoms::strike == aHTMLProperty) { + // 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 + node = node->GetParentElement(); // set to null if it's not a dom element + } + } while ((nsGkAtoms::u == aHTMLProperty || + nsGkAtoms::strike == aHTMLProperty) && !aIsSet && node); + return NS_OK; +} + +void +CSSEditUtils::SetCSSEnabled(bool aIsCSSPrefChecked) +{ + mIsCSSPrefChecked = aIsCSSPrefChecked; +} + +bool +CSSEditUtils::IsCSSPrefChecked() +{ + 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 +bool +CSSEditUtils::ElementsSameStyle(nsIDOMNode* aFirstNode, + nsIDOMNode* aSecondNode) +{ + nsCOMPtr firstElement = do_QueryInterface(aFirstNode); + nsCOMPtr secondElement = do_QueryInterface(aSecondNode); + + NS_ASSERTION((firstElement && secondElement), "Non element nodes passed to ElementsSameStyle."); + NS_ENSURE_TRUE(firstElement, false); + NS_ENSURE_TRUE(secondElement, false); + + return ElementsSameStyle(firstElement, secondElement); +} + +bool +CSSEditUtils::ElementsSameStyle(Element* aFirstElement, + Element* aSecondElement) +{ + MOZ_ASSERT(aFirstElement); + MOZ_ASSERT(aSecondElement); + + if (aFirstElement->HasAttr(kNameSpaceID_None, nsGkAtoms::id) || + aSecondElement->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, secondClass; + bool isFirstClassSet = aFirstElement->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, firstClass); + bool isSecondClassSet = aSecondElement->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, secondClass); + if (isFirstClassSet && isSecondClassSet) { + // both spans carry a class, let's compare them + if (!firstClass.Equals(secondClass)) { + // 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 (isFirstClassSet || isSecondClassSet) { + // one span only carries a class, early way out + return false; + } + + nsCOMPtr firstCSSDecl, secondCSSDecl; + uint32_t firstLength, secondLength; + nsresult rv = GetInlineStyles(aFirstElement, getter_AddRefs(firstCSSDecl), &firstLength); + if (NS_FAILED(rv) || !firstCSSDecl) { + return false; + } + rv = GetInlineStyles(aSecondElement, getter_AddRefs(secondCSSDecl), &secondLength); + if (NS_FAILED(rv) || !secondCSSDecl) { + return false; + } + + if (firstLength != secondLength) { + // early way out if we can + return false; + } + + if (!firstLength) { + // no inline style ! + return true; + } + + nsAutoString propertyNameString; + nsAutoString firstValue, secondValue; + for (uint32_t i = 0; i < firstLength; i++) { + firstCSSDecl->Item(i, propertyNameString); + firstCSSDecl->GetPropertyValue(propertyNameString, firstValue); + secondCSSDecl->GetPropertyValue(propertyNameString, secondValue); + if (!firstValue.Equals(secondValue)) { + return false; + } + } + for (uint32_t i = 0; i < secondLength; i++) { + secondCSSDecl->Item(i, propertyNameString); + secondCSSDecl->GetPropertyValue(propertyNameString, secondValue); + firstCSSDecl->GetPropertyValue(propertyNameString, firstValue); + if (!firstValue.Equals(secondValue)) { + return false; + } + } + + return true; +} + +nsresult +CSSEditUtils::GetInlineStyles(Element* aElement, + nsIDOMCSSStyleDeclaration** aCssDecl, + uint32_t* aLength) +{ + return GetInlineStyles(static_cast(aElement), aCssDecl, aLength); +} + +nsresult +CSSEditUtils::GetInlineStyles(nsIDOMElement* aElement, + nsIDOMCSSStyleDeclaration** aCssDecl, + uint32_t* aLength) +{ + return GetInlineStyles(static_cast(aElement), aCssDecl, aLength); +} + +nsresult +CSSEditUtils::GetInlineStyles(nsISupports* aElement, + nsIDOMCSSStyleDeclaration** aCssDecl, + uint32_t* aLength) +{ + NS_ENSURE_TRUE(aElement && aLength, NS_ERROR_NULL_POINTER); + *aLength = 0; + nsCOMPtr inlineStyles = do_QueryInterface(aElement); + NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER); + + nsCOMPtr cssDecl = + do_QueryInterface(inlineStyles->Style()); + MOZ_ASSERT(cssDecl); + + cssDecl.forget(aCssDecl); + (*aCssDecl)->GetLength(aLength); + return NS_OK; +} + +already_AddRefed +CSSEditUtils::GetElementContainerOrSelf(nsIDOMNode* aNode) +{ + nsCOMPtr node = do_QueryInterface(aNode); + NS_ENSURE_TRUE(node, nullptr); + nsCOMPtr element = + do_QueryInterface(GetElementContainerOrSelf(node)); + return element.forget(); +} + +Element* +CSSEditUtils::GetElementContainerOrSelf(nsINode* aNode) +{ + MOZ_ASSERT(aNode); + if (nsIDOMNode::DOCUMENT_NODE == aNode->NodeType()) { + return nullptr; + } + + nsINode* node = aNode; + // Loop until we find an element. + while (node && !node->IsElement()) { + node = node->GetParentNode(); + } + + NS_ENSURE_TRUE(node, nullptr); + return node->AsElement(); +} + +nsresult +CSSEditUtils::SetCSSProperty(nsIDOMElement* aElement, + const nsAString& aProperty, + const nsAString& aValue) +{ + nsCOMPtr cssDecl; + uint32_t length; + nsresult rv = GetInlineStyles(aElement, getter_AddRefs(cssDecl), &length); + if (NS_FAILED(rv) || !cssDecl) { + return rv; + } + + return cssDecl->SetProperty(aProperty, + aValue, + EmptyString()); +} + +nsresult +CSSEditUtils::SetCSSPropertyPixels(nsIDOMElement* aElement, + const nsAString& aProperty, + int32_t aIntValue) +{ + nsAutoString s; + s.AppendInt(aIntValue); + return SetCSSProperty(aElement, aProperty, s + NS_LITERAL_STRING("px")); +} + +} // namespace mozilla diff --git a/editor/libeditor/CSSEditUtils.h b/editor/libeditor/CSSEditUtils.h new file mode 100644 index 000000000..0b9a12952 --- /dev/null +++ b/editor/libeditor/CSSEditUtils.h @@ -0,0 +1,473 @@ +/* -*- 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 "nsTArray.h" // for nsTArray +#include "nscore.h" // for nsAString, nsresult, nullptr + +class nsComputedDOMStyle; +class nsIAtom; +class nsIContent; +class nsIDOMCSSStyleDeclaration; +class nsIDOMElement; +class nsIDOMNode; +class nsINode; +class nsString; + +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); + ~CSSEditUtils(); + + 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 + }; + + enum StyleType { eSpecified, eComputed }; + + + struct CSSEquivTable + { + nsCSSEditableProperty cssProperty; + nsProcessValueFunc processValueFunctor; + const char* defaultValue; + const char* prependValue; + const char* appendValue; + bool gettable; + bool caseSensitiveValue; + }; + + /** + * 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] A string containing the name of a HTML + * attribute carried by the element above. + * @return A boolean saying if the tag/attribute has a CSS + * equiv. + */ + bool IsCSSEditableProperty(nsINode* aNode, nsIAtom* aProperty, + const nsAString* aAttribute); + + /** + * Adds/remove a CSS declaration to the STYLE atrribute carried by a given + * element. + * + * @param aElement [IN] A DOM element. + * @param aProperty [IN] An atom containing the CSS property to set. + * @param aValue [IN] A string containing the value of the CSS + * property. + * @param aSuppressTransaction [IN] A boolean indicating, when true, + * that no transaction should be recorded. + */ + nsresult SetCSSProperty(dom::Element& aElement, nsIAtom& aProperty, + const nsAString& aValue, bool aSuppressTxn = false); + nsresult SetCSSPropertyPixels(dom::Element& aElement, + nsIAtom& aProperty, int32_t aIntValue); + nsresult RemoveCSSProperty(dom::Element& aElement, + nsIAtom& aProperty, + const nsAString& aPropertyValue, + bool aSuppressTxn = false); + + /** + * Directly adds/remove a CSS declaration to the STYLE atrribute carried by + * a given element without going through the transaction manager. + * + * @param aElement [IN] A DOM element. + * @param aProperty [IN] A string containing the CSS property to + * set/remove. + * @param aValue [IN] A string containing the new value of the CSS + * property. + */ + nsresult SetCSSProperty(nsIDOMElement* aElement, + const nsAString& aProperty, + const nsAString& aValue); + nsresult SetCSSPropertyPixels(nsIDOMElement* aElement, + const nsAString& aProperty, + int32_t aIntValue); + + /** + * 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 aNode [IN] A DOM node. + * @param aProperty [IN] An atom containing the CSS property to get. + * @param aPropertyValue [OUT] The retrieved value of the property. + */ + nsresult GetSpecifiedProperty(nsINode& aNode, nsIAtom& aProperty, + nsAString& aValue); + nsresult GetComputedProperty(nsINode& aNode, nsIAtom& aProperty, + nsAString& aValue); + + /** + * Removes a CSS property from the specified declarations in STYLE attribute + * and removes the node if it is an useless span. + * + * @param aNode [IN] The specific node 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. + */ + nsresult RemoveCSSInlineStyle(nsIDOMNode* aNode, nsIAtom* 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. + */ + bool IsCSSInvertible(nsIAtom& aProperty, const nsAString* 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. + */ + 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. + */ + void GetDefaultLengthUnit(nsAString & aLengthUnit); + + /** + * Returns the list of values for the CSS equivalences to + * the passed HTML style for the passed node. + * + * @param aNode [IN] A DOM node. + * @param aHTMLProperty [IN] An atom containing an HTML property. + * @param aAttribute [IN] A pointer to an attribute name or nullptr if + * irrelevant. + * @param aValueString [OUT] The list of CSS values. + * @param aStyleType [IN] eSpecified or eComputed. + */ + nsresult GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode, + nsIAtom* aHTMLProperty, + const nsAString* aAttribute, + nsAString& aValueString, + StyleType aStyleType); + + /** + * 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 aNode [IN] A DOM node. + * @param aHTMLProperty [IN] An atom containing an HTML property. + * @param aAttribute [IN] A pointer to an attribute name or nullptr if + * irrelevant. + * @param aIsSet [OUT] A boolean being true if the css properties are + * set. + * @param aValueString [IN/OUT] The attribute value (in) the list of CSS + * values (out). + * @param aStyleType [IN] eSpecified or eComputed. + * + * The nsIContent variant returns aIsSet instead of using an out parameter. + */ + bool IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aContent, + nsIAtom* aProperty, + const nsAString* aAttribute, + const nsAString& aValue, + StyleType aStyleType); + + bool IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aContent, + nsIAtom* aProperty, + const nsAString* aAttribute, + nsAString& aValue, + StyleType aStyleType); + + nsresult IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode* aNode, + nsIAtom* aHTMLProperty, + const nsAString* aAttribute, + bool& aIsSet, + nsAString& aValueString, + StyleType aStyleType); + + /** + * 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] A pointer to an attribute name or nullptr if + * irrelevant. + * @param aValue [IN] The attribute value. + * @param aCount [OUT] The number of CSS properties set by the call. + * @param aSuppressTransaction [IN] A boolean indicating, when true, + * that no transaction should be recorded. + * + * aCount is returned by the dom::Element variant instead of being an out + * parameter. + */ + int32_t SetCSSEquivalentToHTMLStyle(dom::Element* aElement, + nsIAtom* aProperty, + const nsAString* aAttribute, + const nsAString* aValue, + bool aSuppressTransaction); + nsresult SetCSSEquivalentToHTMLStyle(nsIDOMNode* aNode, + nsIAtom* aHTMLProperty, + const nsAString* aAttribute, + const nsAString* aValue, + int32_t* aCount, + bool aSuppressTransaction); + + /** + * Removes from the node the CSS inline styles equivalent to the HTML style. + * + * @param aNode [IN] A DOM node. + * @param aHTMLProperty [IN] An atom containing an HTML property. + * @param aAttribute [IN] A pointer to an attribute name or nullptr if + * irrelevant. + * @param aValue [IN] The attribute value. + * @param aSuppressTransaction [IN] A boolean indicating, when true, + * that no transaction should be recorded. + */ + nsresult RemoveCSSEquivalentToHTMLStyle(nsIDOMNode* aNode, + nsIAtom* aHTMLProperty, + const nsAString* aAttribute, + const nsAString* aValue, + bool aSuppressTransaction); + + /** + * Removes from the node the CSS inline styles equivalent to the HTML style. + * + * @param aElement [IN] A DOM Element (must not be null). + * @param aHTMLProperty [IN] An atom containing an HTML property. + * @param aAttribute [IN] A pointer to an attribute name or nullptr if + * irrelevant. + * @param aValue [IN] The attribute value. + * @param aSuppressTransaction [IN] A boolean indicating, when true, + * that no transaction should be recorded. + */ + nsresult RemoveCSSEquivalentToHTMLStyle(dom::Element* aElement, + nsIAtom* aHTMLProperty, + const nsAString* aAttribute, + const nsAString* aValue, + bool aSuppressTransaction); + + /** + * Parses a "xxxx.xxxxxuuu" string where x is a digit and u an alpha char + * we need such a parser because + * nsIDOMCSSStyleDeclaration::GetPropertyCSSValue() is not implemented. + * + * @param aString [IN] Input string to parse. + * @param aValue [OUT] Numeric part. + * @param aUnit [OUT] Unit part. + */ + void ParseLength(const nsAString& aString, float* aValue, nsIAtom** 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(); + + /** + * ElementsSameStyle 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 aFirstNode [IN] A DOM node. + * @param aSecondNode [IN] A DOM node. + * @return true if the two elements are considered to + * have same styles. + */ + bool ElementsSameStyle(dom::Element* aFirstNode, + dom::Element* aSecondNode); + bool ElementsSameStyle(nsIDOMNode* aFirstNode, nsIDOMNode* aSecondNode); + + /** + * Get the specified inline styles (style attribute) for an element. + * + * @param aElement [IN] The element node. + * @param aCssDecl [OUT] The CSS declaration corresponding to the + * style attribute. + * @param aLength [OUT] The number of declarations in aCssDecl. + */ + nsresult GetInlineStyles(dom::Element* aElement, + nsIDOMCSSStyleDeclaration** aCssDecl, + uint32_t* aLength); + nsresult GetInlineStyles(nsIDOMElement* aElement, + nsIDOMCSSStyleDeclaration** aCssDecl, + uint32_t* aLength); +private: + nsresult GetInlineStyles(nsISupports* aElement, + nsIDOMCSSStyleDeclaration** aCssDecl, + uint32_t* aLength); + +public: + /** + * Returns aNode itself if it is an element node, or the first ancestors + * being an element node if aNode is not one itself. + * + * @param aNode [IN] A node + * @param aElement [OUT] The deepest element node containing aNode + * (possibly aNode itself) + */ + dom::Element* GetElementContainerOrSelf(nsINode* aNode); + already_AddRefed GetElementContainerOrSelf(nsIDOMNode* aNode); + + /** + * Gets the computed style for a given element. Can return null. + */ + already_AddRefed GetComputedStyle(dom::Element* aElement); + +private: + /** + * Retrieves the CSS property atom from an enum. + * + * @param aProperty [IN] The enum value for the property. + * @param aAtom [OUT] The corresponding atom. + */ + void GetCSSPropertyAtom(nsCSSEditableProperty aProperty, nsIAtom** aAtom); + + /** + * Retrieves the CSS declarations equivalent to a HTML style value for + * a given equivalence table. + * + * @param aPropertyArray [OUT] The array of css properties. + * @param aValueArray [OUT] The array of values for the CSS properties + * above. + * @param aEquivTable [IN] The equivalence table. + * @param aValue [IN] The HTML style value. + * @param aGetOrRemoveRequest [IN] A boolean value being true if the call to + * the current method is made for + * GetCSSEquivalentToHTMLInlineStyleSet() or + * RemoveCSSEquivalentToHTMLInlineStyleSet(). + */ + void BuildCSSDeclarations(nsTArray& aPropertyArray, + nsTArray& cssValueArray, + 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 aNode [IN] The DOM node. + * @param aHTMLProperty [IN] An atom containing an HTML property. + * @param aAttribute [IN] A pointer to an attribute name or nullptr + * if irrelevant + * @param aValue [IN] The attribute value. + * @param aPropertyArray [OUT] The array of CSS properties. + * @param aValueArray [OUT] The array of values for the CSS properties + * above. + * @param aGetOrRemoveRequest [IN] A boolean value being true if the call to + * the current method is made for + * GetCSSEquivalentToHTMLInlineStyleSet() or + * RemoveCSSEquivalentToHTMLInlineStyleSet(). + */ + void GenerateCSSDeclarationsFromHTMLStyle(dom::Element* aNode, + nsIAtom* aHTMLProperty, + const nsAString* aAttribute, + const nsAString* aValue, + nsTArray& aPropertyArray, + nsTArray& aValueArray, + bool aGetOrRemoveRequest); + + /** + * Creates a Transaction for setting or removing a CSS property. Never + * returns null. + * + * @param aElement [IN] A DOM element. + * @param aProperty [IN] A CSS property. + * @param aValue [IN] The value to set for this CSS property. + * @param aChangeType [IN] eSet to set, eRemove to remove. + */ + already_AddRefed + CreateCSSPropertyTxn(dom::Element& aElement, + nsIAtom& aProperty, const nsAString& aValue, + ChangeStyleTransaction::EChangeType aChangeType); + + /** + * 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. + * @param aStyleType [IN] eSpecified or eComputed. + */ + nsresult GetCSSInlinePropertyBase(nsINode* aNode, nsIAtom* aProperty, + nsAString& aValue, StyleType aStyleType); + +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 000000000..04f539856 --- /dev/null +++ b/editor/libeditor/ChangeAttributeTransaction.cpp @@ -0,0 +1,98 @@ +/* -*- 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; + +ChangeAttributeTransaction::ChangeAttributeTransaction(Element& aElement, + nsIAtom& aAttribute, + const nsAString* aValue) + : EditTransactionBase() + , mElement(&aElement) + , mAttribute(&aAttribute) + , mValue(aValue ? *aValue : EmptyString()) + , mRemoveAttribute(!aValue) + , mAttributeWasSet(false) + , mUndoValue() +{ +} + +ChangeAttributeTransaction::~ChangeAttributeTransaction() +{ +} + +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) { + return mElement->UnsetAttr(kNameSpaceID_None, mAttribute, true); + } + + return mElement->SetAttr(kNameSpaceID_None, mAttribute, mValue, true); +} + +NS_IMETHODIMP +ChangeAttributeTransaction::UndoTransaction() +{ + if (mAttributeWasSet) { + return mElement->SetAttr(kNameSpaceID_None, mAttribute, mUndoValue, true); + } + return mElement->UnsetAttr(kNameSpaceID_None, mAttribute, true); +} + +NS_IMETHODIMP +ChangeAttributeTransaction::RedoTransaction() +{ + if (mRemoveAttribute) { + return mElement->UnsetAttr(kNameSpaceID_None, mAttribute, true); + } + + return mElement->SetAttr(kNameSpaceID_None, mAttribute, mValue, true); +} + +NS_IMETHODIMP +ChangeAttributeTransaction::GetTxnDescription(nsAString& aString) +{ + aString.AssignLiteral("ChangeAttributeTransaction: [mRemoveAttribute == "); + + if (mRemoveAttribute) { + aString.AppendLiteral("true] "); + } else { + aString.AppendLiteral("false] "); + } + aString += nsDependentAtomString(mAttribute); + return NS_OK; +} + +} // namespace mozilla diff --git a/editor/libeditor/ChangeAttributeTransaction.h b/editor/libeditor/ChangeAttributeTransaction.h new file mode 100644 index 000000000..bb0c26c38 --- /dev/null +++ b/editor/libeditor/ChangeAttributeTransaction.h @@ -0,0 +1,72 @@ +/* -*- 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 nsIAtom; + +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 +{ +public: + /** + * @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, or null to remove + */ + ChangeAttributeTransaction(dom::Element& aElement, + nsIAtom& aAttribute, + const nsAString* aValue); + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeAttributeTransaction, + EditTransactionBase) + + NS_DECL_EDITTRANSACTIONBASE + + NS_IMETHOD RedoTransaction() override; + +private: + virtual ~ChangeAttributeTransaction(); + + // The element to operate upon + nsCOMPtr mElement; + + // The attribute to change + nsCOMPtr mAttribute; + + // The value to set the attribute to (ignored if mRemoveAttribute==true) + nsString mValue; + + // 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; + + // The value to set the attribute to for undo + nsString mUndoValue; +}; + +} // namespace mozilla + +#endif // #ifndef ChangeAttributeTransaction_h diff --git a/editor/libeditor/ChangeStyleTransaction.cpp b/editor/libeditor/ChangeStyleTransaction.cpp new file mode 100644 index 000000000..103d9c455 --- /dev/null +++ b/editor/libeditor/ChangeStyleTransaction.cpp @@ -0,0 +1,287 @@ +/* -*- 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_internal::Append, etc. +#include "nsCRT.h" // for nsCRT::IsAsciiSpace +#include "nsDebug.h" // for NS_ENSURE_SUCCESS, 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; + +#define kNullCh (char16_t('\0')) + +NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeStyleTransaction, EditTransactionBase, + mElement) + +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) + +ChangeStyleTransaction::~ChangeStyleTransaction() +{ +} + +// Answers true if aValue is in the string list of white-space separated values +// aValueList. +bool +ChangeStyleTransaction::ValueIncludes(const nsAString& aValueList, + const nsAString& aValue) +{ + nsAutoString valueList(aValueList); + bool result = false; + + // put an extra null at the end + valueList.Append(kNullCh); + + char16_t* value = ToNewUnicode(aValue); + char16_t* start = valueList.BeginWriting(); + char16_t* 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 (nsDependentString(value).Equals(nsDependentString(start), + nsCaseInsensitiveStringComparator())) { + result = true; + break; + } + } + start = ++end; + } + free(value); + return result; +} + +// Removes the value aRemoveValue from the string list of white-space separated +// values aValueList +void +ChangeStyleTransaction::RemoveValueFromListOfValues( + nsAString& aValues, + const nsAString& aRemoveValue) +{ + nsAutoString classStr(aValues); + nsAutoString outString; + // put an extra null at the end + classStr.Append(kNullCh); + + char16_t* start = classStr.BeginWriting(); + char16_t* 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(char16_t(' ')); + } + + start = ++end; + } + aValues.Assign(outString); +} + +ChangeStyleTransaction::ChangeStyleTransaction(Element& aElement, + nsIAtom& aProperty, + const nsAString& aValue, + EChangeType aChangeType) + : EditTransactionBase() + , mElement(&aElement) + , mProperty(&aProperty) + , mValue(aValue) + , mRemoveProperty(aChangeType == eRemove) + , mUndoValue() + , mRedoValue() + , mUndoAttributeWasSet(false) + , mRedoAttributeWasSet(false) +{ +} + +NS_IMETHODIMP +ChangeStyleTransaction::DoTransaction() +{ + nsCOMPtr inlineStyles = do_QueryInterface(mElement); + NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER); + + nsCOMPtr cssDecl = inlineStyles->Style(); + + nsAutoString propertyNameString; + mProperty->ToString(propertyNameString); + + mUndoAttributeWasSet = mElement->HasAttr(kNameSpaceID_None, + nsGkAtoms::style); + + nsAutoString values; + nsresult rv = cssDecl->GetPropertyValue(propertyNameString, values); + NS_ENSURE_SUCCESS(rv, rv); + mUndoValue.Assign(values); + + // Does this property accept more than one value? (bug 62682) + bool multiple = AcceptsMoreThanOneValue(*mProperty); + + if (mRemoveProperty) { + nsAutoString returnString; + if (multiple) { + // Let's remove only the value we have to remove and not the others + + // The two lines below are a workaround because + // nsDOMCSSDeclaration::GetPropertyCSSValue is not yet implemented (bug + // 62682) + RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none")); + RemoveValueFromListOfValues(values, mValue); + if (values.IsEmpty()) { + rv = cssDecl->RemoveProperty(propertyNameString, returnString); + NS_ENSURE_SUCCESS(rv, rv); + } else { + nsAutoString priority; + cssDecl->GetPropertyPriority(propertyNameString, priority); + rv = cssDecl->SetProperty(propertyNameString, values, priority); + NS_ENSURE_SUCCESS(rv, rv); + } + } else { + rv = cssDecl->RemoveProperty(propertyNameString, returnString); + NS_ENSURE_SUCCESS(rv, rv); + } + } else { + nsAutoString priority; + cssDecl->GetPropertyPriority(propertyNameString, priority); + if (multiple) { + // Let's add the value we have to add to the others + + // The line below is a workaround because + // nsDOMCSSDeclaration::GetPropertyCSSValue is not yet implemented (bug + // 62682) + AddValueToMultivalueProperty(values, mValue); + } else { + values.Assign(mValue); + } + rv = cssDecl->SetProperty(propertyNameString, values, priority); + NS_ENSURE_SUCCESS(rv, rv); + } + + // Let's be sure we don't keep an empty style attribute + uint32_t length; + rv = cssDecl->GetLength(&length); + NS_ENSURE_SUCCESS(rv, rv); + if (!length) { + rv = mElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::style, true); + NS_ENSURE_SUCCESS(rv, rv); + } else { + mRedoAttributeWasSet = true; + } + + return cssDecl->GetPropertyValue(propertyNameString, mRedoValue); +} + +nsresult +ChangeStyleTransaction::SetStyle(bool aAttributeWasSet, + nsAString& aValue) +{ + if (aAttributeWasSet) { + // The style attribute was not empty, let's recreate the declaration + nsAutoString propertyNameString; + mProperty->ToString(propertyNameString); + + nsCOMPtr inlineStyles = do_QueryInterface(mElement); + NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER); + nsCOMPtr cssDecl = inlineStyles->Style(); + + if (aValue.IsEmpty()) { + // An empty value means we have to remove the property + nsAutoString returnString; + return cssDecl->RemoveProperty(propertyNameString, returnString); + } + // Let's recreate the declaration as it was + nsAutoString priority; + cssDecl->GetPropertyPriority(propertyNameString, priority); + return cssDecl->SetProperty(propertyNameString, aValue, priority); + } + return mElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::style, true); +} + +NS_IMETHODIMP +ChangeStyleTransaction::UndoTransaction() +{ + return SetStyle(mUndoAttributeWasSet, mUndoValue); +} + +NS_IMETHODIMP +ChangeStyleTransaction::RedoTransaction() +{ + return SetStyle(mRedoAttributeWasSet, mRedoValue); +} + +NS_IMETHODIMP +ChangeStyleTransaction::GetTxnDescription(nsAString& aString) +{ + aString.AssignLiteral("ChangeStyleTransaction: [mRemoveProperty == "); + + if (mRemoveProperty) { + aString.AppendLiteral("true] "); + } else { + aString.AppendLiteral("false] "); + } + aString += nsDependentAtomString(mProperty); + return NS_OK; +} + +// True if the CSS property accepts more than one value +bool +ChangeStyleTransaction::AcceptsMoreThanOneValue(nsIAtom& aCSSProperty) +{ + return &aCSSProperty == nsGkAtoms::text_decoration; +} + +// Adds the value aNewValue to the list of white-space separated values aValues +void +ChangeStyleTransaction::AddValueToMultivalueProperty(nsAString& aValues, + const nsAString& 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 000000000..14c2cdcb5 --- /dev/null +++ b/editor/libeditor/ChangeStyleTransaction.h @@ -0,0 +1,123 @@ +/* -*- 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 nsAString; +class nsIAtom; + +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 +{ +public: + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeStyleTransaction, + EditTransactionBase) + + NS_DECL_ISUPPORTS_INHERITED + + NS_DECL_EDITTRANSACTIONBASE + + NS_IMETHOD RedoTransaction() override; + + enum EChangeType { eSet, eRemove }; + + /** + * @param aNode [IN] the node whose style attribute will be changed + * @param aProperty [IN] the name of the property to change + * @param aValue [IN] new value for aProperty, or value to remove + * @param aChangeType [IN] whether to set or remove + */ + ChangeStyleTransaction(dom::Element& aElement, + nsIAtom& aProperty, + const nsAString& aValue, + EChangeType aChangeType); + + /** + * 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 nsAString& aValueList, + const nsAString& aValue); + +private: + virtual ~ChangeStyleTransaction(); + + /* + * 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(nsAString& aValues, + const nsAString& 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(nsIAtom& 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(nsAString& aValues, + const nsAString& 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. + */ + nsresult SetStyle(bool aAttributeWasSet, nsAString& aValue); + + // The element to operate upon. + nsCOMPtr mElement; + + // The CSS property to change. + nsCOMPtr mProperty; + + // The value to set the property to (ignored if mRemoveProperty==true). + nsString mValue; + + // true if the operation is to remove mProperty from mElement. + bool mRemoveProperty; + + // The value to set the property to for undo. + nsString mUndoValue; + // The value to set the property to for redo. + nsString mRedoValue; + // 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 000000000..25938fa60 --- /dev/null +++ b/editor/libeditor/CompositionTransaction.cpp @@ -0,0 +1,332 @@ +/* -*- 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/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 "nsIPresShell.h" // nsISelectionController constants +#include "nsRange.h" // local var +#include "nsQueryObject.h" // for do_QueryObject + +namespace mozilla { + +using namespace dom; + +CompositionTransaction::CompositionTransaction( + Text& aTextNode, + uint32_t aOffset, + uint32_t aReplaceLength, + TextRangeArray* aTextRangeArray, + const nsAString& aStringToInsert, + EditorBase& aEditorBase, + RangeUpdater* aRangeUpdater) + : mTextNode(&aTextNode) + , mOffset(aOffset) + , mReplaceLength(aReplaceLength) + , mRanges(aTextRangeArray) + , mStringToInsert(aStringToInsert) + , mEditorBase(aEditorBase) + , mRangeUpdater(aRangeUpdater) + , mFixed(false) +{ + MOZ_ASSERT(mTextNode->TextLength() >= mOffset); +} + +CompositionTransaction::~CompositionTransaction() +{ +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(CompositionTransaction, EditTransactionBase, + mTextNode) +// mRangeList can't lead to cycles + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CompositionTransaction) + if (aIID.Equals(NS_GET_IID(CompositionTransaction))) { + foundInterface = static_cast(this); + } else +NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase) + +NS_IMPL_ADDREF_INHERITED(CompositionTransaction, EditTransactionBase) +NS_IMPL_RELEASE_INHERITED(CompositionTransaction, EditTransactionBase) + +NS_IMETHODIMP +CompositionTransaction::DoTransaction() +{ + // Fail before making any changes if there's no selection controller + nsCOMPtr selCon; + mEditorBase.GetSelectionController(getter_AddRefs(selCon)); + NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED); + + // Advance caret: This requires the presentation shell to get the selection. + if (mReplaceLength == 0) { + nsresult rv = mTextNode->InsertData(mOffset, mStringToInsert); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert); + } else { + uint32_t replaceableLength = mTextNode->TextLength() - mOffset; + nsresult rv = + mTextNode->ReplaceData(mOffset, mReplaceLength, mStringToInsert); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + mRangeUpdater->SelAdjDeleteText(mTextNode, mOffset, mReplaceLength); + mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert); + + // If IME text node is multiple node, ReplaceData doesn't remove all IME + // text. So we need remove remained text into other text node. + if (replaceableLength < mReplaceLength) { + int32_t remainLength = mReplaceLength - replaceableLength; + nsCOMPtr node = mTextNode->GetNextSibling(); + while (node && node->IsNodeOfType(nsINode::eTEXT) && + remainLength > 0) { + Text* text = static_cast(node.get()); + uint32_t textLength = text->TextLength(); + text->DeleteData(0, remainLength); + mRangeUpdater->SelAdjDeleteText(text, 0, remainLength); + remainLength -= textLength; + node = node->GetNextSibling(); + } + } + } + + nsresult rv = SetSelectionForRanges(); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +NS_IMETHODIMP +CompositionTransaction::UndoTransaction() +{ + // Get the selection first so we'll fail before making any changes if we + // can't get it + RefPtr selection = mEditorBase.GetSelection(); + NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED); + + nsresult rv = mTextNode->DeleteData(mOffset, mStringToInsert.Length()); + NS_ENSURE_SUCCESS(rv, rv); + + // set the selection to the insertion point where the string was removed + rv = selection->Collapse(mTextNode, mOffset); + NS_ASSERTION(NS_SUCCEEDED(rv), + "Selection could not be collapsed after undo of IME insert."); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +NS_IMETHODIMP +CompositionTransaction::Merge(nsITransaction* aTransaction, + bool* aDidMerge) +{ + NS_ENSURE_ARG_POINTER(aTransaction && aDidMerge); + + // Check to make sure we aren't fixed, if we are then nothing gets absorbed + if (mFixed) { + *aDidMerge = false; + return NS_OK; + } + + // If aTransaction is another CompositionTransaction then absorb it + RefPtr otherTransaction = + do_QueryObject(aTransaction); + if (otherTransaction) { + // We absorb the next IME transaction by adopting its insert string + mStringToInsert = otherTransaction->mStringToInsert; + mRanges = otherTransaction->mRanges; + *aDidMerge = true; + return NS_OK; + } + + *aDidMerge = false; + return NS_OK; +} + +void +CompositionTransaction::MarkFixed() +{ + mFixed = true; +} + +NS_IMETHODIMP +CompositionTransaction::GetTxnDescription(nsAString& aString) +{ + aString.AssignLiteral("CompositionTransaction: "); + aString += mStringToInsert; + return NS_OK; +} + +/* ============ private methods ================== */ + +nsresult +CompositionTransaction::SetSelectionForRanges() +{ + return SetIMESelection(mEditorBase, mTextNode, mOffset, + mStringToInsert.Length(), mRanges); +} + +// static +nsresult +CompositionTransaction::SetIMESelection(EditorBase& aEditorBase, + Text* aTextNode, + uint32_t aOffsetInNode, + uint32_t aLengthOfCompositionString, + const TextRangeArray* aRanges) +{ + RefPtr selection = aEditorBase.GetSelection(); + NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED); + + nsresult rv = selection->StartBatchChanges(); + NS_ENSURE_SUCCESS(rv, rv); + + // 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 selCon; + aEditorBase.GetSelectionController(getter_AddRefs(selCon)); + NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED); + + for (uint32_t i = 0; i < ArrayLength(kIMESelections); ++i) { + nsCOMPtr selectionOfIME; + if (NS_FAILED(selCon->GetSelection(kIMESelections[i], + getter_AddRefs(selectionOfIME)))) { + continue; + } + rv = selectionOfIME->RemoveAllRanges(); + NS_ASSERTION(NS_SUCCEEDED(rv), + "Failed to remove all ranges of IME selection"); + } + + // 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. + 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->Collapse(aTextNode, caretOffset); + setCaret = setCaret || NS_SUCCEEDED(rv); + if (NS_WARN_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); + rv = nsRange::CreateRange(aTextNode, startOffset, + aTextNode, endOffset, + getter_AddRefs(clauseRange)); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to create a DOM range for a clause of composition"); + break; + } + + // Set the range of the clause to selection. + nsCOMPtr selectionOfIME; + rv = selCon->GetSelection(ToRawSelectionType(textRange.mRangeType), + getter_AddRefs(selectionOfIME)); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to get IME selection"); + break; + } + + rv = selectionOfIME->AddRange(clauseRange); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to add selection range for a clause of composition"); + break; + } + + // Set the style of the clause. + nsCOMPtr selectionOfIMEPriv = + do_QueryInterface(selectionOfIME); + if (!selectionOfIMEPriv) { + NS_WARNING("Failed to get nsISelectionPrivate interface from selection"); + continue; // Since this is additional feature, we can continue this job. + } + rv = selectionOfIMEPriv->SetTextRangeStyle(clauseRange, + textRange.mRangeStyle); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to set selection style"); + 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->Collapse(aTextNode, caretOffset); + NS_ASSERTION(NS_SUCCEEDED(rv), + "Failed to set caret at the end of composition string"); + + // 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); + } + } + + rv = selection->EndBatchChangesInternal(); + NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to end batch changes"); + + return rv; +} + +} // namespace mozilla diff --git a/editor/libeditor/CompositionTransaction.h b/editor/libeditor/CompositionTransaction.h new file mode 100644 index 000000000..acb3d8beb --- /dev/null +++ b/editor/libeditor/CompositionTransaction.h @@ -0,0 +1,104 @@ +/* -*- 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 "nsCycleCollectionParticipant.h" // various macros +#include "nsString.h" // mStringToInsert + +#define NS_IMETEXTTXN_IID \ + { 0xb391355d, 0x346c, 0x43d1, \ + { 0x85, 0xed, 0x9e, 0x65, 0xbe, 0xe7, 0x7e, 0x48 } } + +namespace mozilla { + +class EditorBase; +class RangeUpdater; +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: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMETEXTTXN_IID) + + /** + * @param aTextNode The start node of text content. + * @param aOffset The location in aTextNode to do the insertion. + * @param aReplaceLength The length of text to replace. 0 means not + * replacing existing text. + * @param aTextRangeArray Clauses and/or caret information. This may be + * null. + * @param aString The new text to insert. + * @param aEditorBase Used to get and set the selection. + * @param aRangeUpdater The range updater + */ + CompositionTransaction(dom::Text& aTextNode, + uint32_t aOffset, uint32_t aReplaceLength, + TextRangeArray* aTextRangeArray, + const nsAString& aString, + EditorBase& aEditorBase, + RangeUpdater* aRangeUpdater); + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CompositionTransaction, + EditTransactionBase) + + NS_DECL_ISUPPORTS_INHERITED + + NS_DECL_EDITTRANSACTIONBASE + + NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override; + + void MarkFixed(); + + static nsresult SetIMESelection(EditorBase& aEditorBase, + dom::Text* aTextNode, + uint32_t aOffsetInNode, + uint32_t aLengthOfCompositionString, + const TextRangeArray* aRanges); + +private: + ~CompositionTransaction(); + + 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. + EditorBase& mEditorBase; + + RangeUpdater* mRangeUpdater; + + bool mFixed; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(CompositionTransaction, NS_IMETEXTTXN_IID) + +} // namespace mozilla + +#endif // #ifndef CompositionTransaction_h diff --git a/editor/libeditor/CreateElementTransaction.cpp b/editor/libeditor/CreateElementTransaction.cpp new file mode 100644 index 000000000..5e4bd961c --- /dev/null +++ b/editor/libeditor/CreateElementTransaction.cpp @@ -0,0 +1,147 @@ +/* -*- 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 "nsAlgorithm.h" +#include "nsAString.h" +#include "nsDebug.h" +#include "nsError.h" +#include "nsIContent.h" +#include "nsIDOMCharacterData.h" +#include "nsIEditor.h" +#include "nsINode.h" +#include "nsISupportsUtils.h" +#include "nsMemory.h" +#include "nsReadableUtils.h" +#include "nsStringFwd.h" +#include "nsString.h" + +namespace mozilla { + +using namespace dom; + +CreateElementTransaction::CreateElementTransaction(EditorBase& aEditorBase, + nsIAtom& aTag, + nsINode& aParent, + int32_t aOffsetInParent) + : EditTransactionBase() + , mEditorBase(&aEditorBase) + , mTag(&aTag) + , mParent(&aParent) + , mOffsetInParent(aOffsetInParent) +{ +} + +CreateElementTransaction::~CreateElementTransaction() +{ +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(CreateElementTransaction, + EditTransactionBase, + mParent, + mNewNode, + mRefNode) + +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() +{ + MOZ_ASSERT(mEditorBase && mTag && mParent); + + mNewNode = mEditorBase->CreateHTMLContent(mTag); + NS_ENSURE_STATE(mNewNode); + + // Try to insert formatting whitespace for the new node: + mEditorBase->MarkNodeDirty(GetAsDOMNode(mNewNode)); + + // Insert the new node + ErrorResult rv; + if (mOffsetInParent == -1) { + mParent->AppendChild(*mNewNode, rv); + return rv.StealNSResult(); + } + + mOffsetInParent = std::min(mOffsetInParent, + static_cast(mParent->GetChildCount())); + + // Note, it's ok for mRefNode to be null. That means append + mRefNode = mParent->GetChildAt(mOffsetInParent); + + nsCOMPtr refNode = mRefNode; + mParent->InsertBefore(*mNewNode, refNode, rv); + NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult()); + + // Only set selection to insertion point if editor gives permission + if (!mEditorBase->GetShouldTxnSetSelection()) { + // Do nothing - DOM range gravity will adjust selection + return NS_OK; + } + + RefPtr selection = mEditorBase->GetSelection(); + NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); + + rv = selection->CollapseNative(mParent, mParent->IndexOf(mNewNode) + 1); + NS_ASSERTION(!rv.Failed(), + "selection could not be collapsed after insert"); + return NS_OK; +} + +NS_IMETHODIMP +CreateElementTransaction::UndoTransaction() +{ + MOZ_ASSERT(mEditorBase && mParent); + + ErrorResult rv; + mParent->RemoveChild(*mNewNode, rv); + + return rv.StealNSResult(); +} + +NS_IMETHODIMP +CreateElementTransaction::RedoTransaction() +{ + MOZ_ASSERT(mEditorBase && mParent); + + // First, reset mNewNode so it has no attributes or content + // XXX We never actually did this, we only cleared mNewNode's contents if it + // was a CharacterData node (which it's not, it's an Element) + + // Now, reinsert mNewNode + ErrorResult rv; + nsCOMPtr refNode = mRefNode; + mParent->InsertBefore(*mNewNode, refNode, rv); + return rv.StealNSResult(); +} + +NS_IMETHODIMP +CreateElementTransaction::GetTxnDescription(nsAString& aString) +{ + aString.AssignLiteral("CreateElementTransaction: "); + aString += nsDependentAtomString(mTag); + return NS_OK; +} + +already_AddRefed +CreateElementTransaction::GetNewNode() +{ + return nsCOMPtr(mNewNode).forget(); +} + +} // namespace mozilla diff --git a/editor/libeditor/CreateElementTransaction.h b/editor/libeditor/CreateElementTransaction.h new file mode 100644 index 000000000..70fecceae --- /dev/null +++ b/editor/libeditor/CreateElementTransaction.h @@ -0,0 +1,80 @@ +/* -*- 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/EditTransactionBase.h" +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsISupportsImpl.h" + +class nsIAtom; +class nsIContent; +class nsINode; + +/** + * A transaction that creates a new node in the content tree. + */ +namespace mozilla { + +class EditorBase; +namespace dom { +class Element; +} // namespace dom + +class CreateElementTransaction final : public EditTransactionBase +{ +public: + /** + * Initialize the transaction. + * @param aEditorBase The provider of basic editing functionality. + * @param aTag The tag (P, HR, TABLE, etc.) for the new element. + * @param aParent The node into which the new element will be + * inserted. + * @param aOffsetInParent The location in aParent to insert the new element. + * If eAppend, the new element is appended as the last + * child. + */ + CreateElementTransaction(EditorBase& aEditorBase, + nsIAtom& aTag, + nsINode& aParent, + int32_t aOffsetInParent); + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CreateElementTransaction, + EditTransactionBase) + + NS_DECL_EDITTRANSACTIONBASE + + NS_IMETHOD RedoTransaction() override; + + already_AddRefed GetNewNode(); + +protected: + virtual ~CreateElementTransaction(); + + // The document into which the new node will be inserted. + EditorBase* mEditorBase; + + // The tag (mapping to object type) for the new element. + nsCOMPtr mTag; + + // The node into which the new node will be inserted. + nsCOMPtr mParent; + + // The index in mParent for the new node. + int32_t mOffsetInParent; + + // The new node to insert. + nsCOMPtr mNewNode; + + // The node we will insert mNewNode before. We compute this ourselves. + nsCOMPtr mRefNode; +}; + +} // namespace mozilla + +#endif // #ifndef CreateElementTransaction_h diff --git a/editor/libeditor/DeleteNodeTransaction.cpp b/editor/libeditor/DeleteNodeTransaction.cpp new file mode 100644 index 000000000..7f485b066 --- /dev/null +++ b/editor/libeditor/DeleteNodeTransaction.cpp @@ -0,0 +1,123 @@ +/* -*- 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 "mozilla/EditorBase.h" +#include "mozilla/SelectionState.h" // RangeUpdater +#include "nsDebug.h" +#include "nsError.h" +#include "nsAString.h" + +namespace mozilla { + +DeleteNodeTransaction::DeleteNodeTransaction() + : mEditorBase(nullptr) + , mRangeUpdater(nullptr) +{ +} + +DeleteNodeTransaction::~DeleteNodeTransaction() +{ +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteNodeTransaction, EditTransactionBase, + mNode, + mParent, + mRefNode) + +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) + +nsresult +DeleteNodeTransaction::Init(EditorBase* aEditorBase, + nsINode* aNode, + RangeUpdater* aRangeUpdater) +{ + NS_ENSURE_TRUE(aEditorBase && aNode, NS_ERROR_NULL_POINTER); + mEditorBase = aEditorBase; + mNode = aNode; + mParent = aNode->GetParentNode(); + + // do nothing if the node has a parent and it's read-only + NS_ENSURE_TRUE(!mParent || mEditorBase->IsModifiableNode(mParent), + NS_ERROR_FAILURE); + + mRangeUpdater = aRangeUpdater; + return NS_OK; +} + +NS_IMETHODIMP +DeleteNodeTransaction::DoTransaction() +{ + NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED); + + if (!mParent) { + // this is a no-op, there's no parent to delete mNode from + return NS_OK; + } + + // remember which child mNode was (by remembering which child was next); + // mRefNode can be null + mRefNode = mNode->GetNextSibling(); + + // give range updater a chance. SelAdjDeleteNode() needs to be called + // *before* we do the action, unlike some of the other RangeItem update + // methods. + if (mRangeUpdater) { + mRangeUpdater->SelAdjDeleteNode(mNode->AsDOMNode()); + } + + ErrorResult error; + mParent->RemoveChild(*mNode, error); + return error.StealNSResult(); +} + +NS_IMETHODIMP +DeleteNodeTransaction::UndoTransaction() +{ + if (!mParent) { + // this is a legal state, the txn is a no-op + return NS_OK; + } + if (!mNode) { + return NS_ERROR_NULL_POINTER; + } + + ErrorResult error; + nsCOMPtr refNode = mRefNode; + mParent->InsertBefore(*mNode, refNode, error); + return error.StealNSResult(); +} + +NS_IMETHODIMP +DeleteNodeTransaction::RedoTransaction() +{ + if (!mParent) { + // this is a legal state, the txn is a no-op + return NS_OK; + } + if (!mNode) { + return NS_ERROR_NULL_POINTER; + } + + if (mRangeUpdater) { + mRangeUpdater->SelAdjDeleteNode(mNode->AsDOMNode()); + } + + ErrorResult error; + mParent->RemoveChild(*mNode, error); + return error.StealNSResult(); +} + +NS_IMETHODIMP +DeleteNodeTransaction::GetTxnDescription(nsAString& aString) +{ + aString.AssignLiteral("DeleteNodeTransaction"); + return NS_OK; +} + +} // namespace mozilla diff --git a/editor/libeditor/DeleteNodeTransaction.h b/editor/libeditor/DeleteNodeTransaction.h new file mode 100644 index 000000000..d0bc0dd46 --- /dev/null +++ b/editor/libeditor/DeleteNodeTransaction.h @@ -0,0 +1,66 @@ +/* -*- 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; +class RangeUpdater; + +/** + * A transaction that deletes a single element + */ +class DeleteNodeTransaction final : public EditTransactionBase +{ +public: + /** + * Initialize the transaction. + * @param aElement The node to delete. + */ + nsresult Init(EditorBase* aEditorBase, nsINode* aNode, + RangeUpdater* aRangeUpdater); + + DeleteNodeTransaction(); + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteNodeTransaction, + EditTransactionBase) + + NS_DECL_EDITTRANSACTIONBASE + + NS_IMETHOD RedoTransaction() override; + +protected: + virtual ~DeleteNodeTransaction(); + + // The element to delete. + nsCOMPtr mNode; + + // Parent of node to delete. + nsCOMPtr mParent; + + // Next sibling to remember for undo/redo purposes. + nsCOMPtr mRefNode; + + // The editor for this transaction. + EditorBase* mEditorBase; + + // Range updater object. + RangeUpdater* mRangeUpdater; +}; + +} // namespace mozilla + +#endif // #ifndef DeleteNodeTransaction_h diff --git a/editor/libeditor/DeleteRangeTransaction.cpp b/editor/libeditor/DeleteRangeTransaction.cpp new file mode 100644 index 000000000..977de4873 --- /dev/null +++ b/editor/libeditor/DeleteRangeTransaction.cpp @@ -0,0 +1,239 @@ +/* -*- 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/EditorBase.h" +#include "mozilla/dom/Selection.h" +#include "mozilla/mozalloc.h" +#include "nsCOMPtr.h" +#include "nsDebug.h" +#include "nsError.h" +#include "nsIContent.h" +#include "nsIContentIterator.h" +#include "nsIDOMCharacterData.h" +#include "nsINode.h" +#include "nsAString.h" + +namespace mozilla { + +using namespace dom; + +// note that aEditorBase is not refcounted +DeleteRangeTransaction::DeleteRangeTransaction() + : mEditorBase(nullptr) + , mRangeUpdater(nullptr) +{ +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteRangeTransaction, + EditAggregateTransaction, + mRange) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteRangeTransaction) +NS_INTERFACE_MAP_END_INHERITING(EditAggregateTransaction) + +nsresult +DeleteRangeTransaction::Init(EditorBase* aEditorBase, + nsRange* aRange, + RangeUpdater* aRangeUpdater) +{ + MOZ_ASSERT(aEditorBase && aRange); + + mEditorBase = aEditorBase; + mRange = aRange->CloneRange(); + mRangeUpdater = aRangeUpdater; + + NS_ENSURE_TRUE(mEditorBase->IsModifiableNode(mRange->GetStartParent()), + NS_ERROR_FAILURE); + NS_ENSURE_TRUE(mEditorBase->IsModifiableNode(mRange->GetEndParent()), + NS_ERROR_FAILURE); + NS_ENSURE_TRUE(mEditorBase->IsModifiableNode(mRange->GetCommonAncestor()), + NS_ERROR_FAILURE); + + return NS_OK; +} + +NS_IMETHODIMP +DeleteRangeTransaction::DoTransaction() +{ + MOZ_ASSERT(mRange && mEditorBase); + + // build the child transactions + nsCOMPtr startParent = mRange->GetStartParent(); + int32_t startOffset = mRange->StartOffset(); + nsCOMPtr endParent = mRange->GetEndParent(); + int32_t endOffset = mRange->EndOffset(); + MOZ_ASSERT(startParent && endParent); + + if (startParent == endParent) { + // the selection begins and ends in the same node + nsresult rv = + CreateTxnsToDeleteBetween(startParent, startOffset, endOffset); + NS_ENSURE_SUCCESS(rv, rv); + } else { + // the selection ends in a different node from where it started. delete + // the relevant content in the start node + nsresult rv = + CreateTxnsToDeleteContent(startParent, startOffset, nsIEditor::eNext); + NS_ENSURE_SUCCESS(rv, rv); + // delete the intervening nodes + rv = CreateTxnsToDeleteNodesBetween(); + NS_ENSURE_SUCCESS(rv, rv); + // delete the relevant content in the end node + rv = CreateTxnsToDeleteContent(endParent, endOffset, nsIEditor::ePrevious); + NS_ENSURE_SUCCESS(rv, rv); + } + + // if we've successfully built this aggregate transaction, then do it. + nsresult rv = EditAggregateTransaction::DoTransaction(); + NS_ENSURE_SUCCESS(rv, rv); + + // only set selection to deletion point if editor gives permission + bool bAdjustSelection; + mEditorBase->ShouldTxnSetSelection(&bAdjustSelection); + if (bAdjustSelection) { + RefPtr selection = mEditorBase->GetSelection(); + NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); + rv = selection->Collapse(startParent, startOffset); + NS_ENSURE_SUCCESS(rv, rv); + } + // else do nothing - dom range gravity will adjust selection + + return NS_OK; +} + +NS_IMETHODIMP +DeleteRangeTransaction::UndoTransaction() +{ + MOZ_ASSERT(mRange && mEditorBase); + + return EditAggregateTransaction::UndoTransaction(); +} + +NS_IMETHODIMP +DeleteRangeTransaction::RedoTransaction() +{ + MOZ_ASSERT(mRange && mEditorBase); + + return EditAggregateTransaction::RedoTransaction(); +} + +NS_IMETHODIMP +DeleteRangeTransaction::GetTxnDescription(nsAString& aString) +{ + aString.AssignLiteral("DeleteRangeTransaction"); + return NS_OK; +} + +nsresult +DeleteRangeTransaction::CreateTxnsToDeleteBetween(nsINode* aNode, + int32_t aStartOffset, + int32_t aEndOffset) +{ + // see what kind of node we have + if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) { + // if the node is a chardata node, then delete chardata content + int32_t numToDel; + if (aStartOffset == aEndOffset) { + numToDel = 1; + } else { + numToDel = aEndOffset - aStartOffset; + } + + RefPtr charDataNode = + static_cast(aNode); + + RefPtr transaction = + new DeleteTextTransaction(*mEditorBase, *charDataNode, aStartOffset, + numToDel, mRangeUpdater); + + nsresult rv = transaction->Init(); + NS_ENSURE_SUCCESS(rv, rv); + + AppendChild(transaction); + return NS_OK; + } + + nsCOMPtr child = aNode->GetChildAt(aStartOffset); + NS_ENSURE_STATE(child); + + // XXX This looks odd. Only when the last transaction causes error at + // calling Init(), the result becomes error. Otherwise, always NS_OK. + nsresult rv = NS_OK; + for (int32_t i = aStartOffset; i < aEndOffset; ++i) { + RefPtr transaction = new DeleteNodeTransaction(); + rv = transaction->Init(mEditorBase, child, mRangeUpdater); + if (NS_SUCCEEDED(rv)) { + AppendChild(transaction); + } + + child = child->GetNextSibling(); + } + + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; +} + +nsresult +DeleteRangeTransaction::CreateTxnsToDeleteContent(nsINode* aNode, + int32_t aOffset, + nsIEditor::EDirection aAction) +{ + // see what kind of node we have + if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) { + // if the node is a chardata node, then delete chardata content + uint32_t start, numToDelete; + if (nsIEditor::eNext == aAction) { + start = aOffset; + numToDelete = aNode->Length() - aOffset; + } else { + start = 0; + numToDelete = aOffset; + } + + if (numToDelete) { + RefPtr dataNode = + static_cast(aNode); + RefPtr transaction = + new DeleteTextTransaction(*mEditorBase, *dataNode, start, numToDelete, + mRangeUpdater); + + nsresult rv = transaction->Init(); + NS_ENSURE_SUCCESS(rv, rv); + + AppendChild(transaction); + } + } + + return NS_OK; +} + +nsresult +DeleteRangeTransaction::CreateTxnsToDeleteNodesBetween() +{ + nsCOMPtr iter = NS_NewContentSubtreeIterator(); + + nsresult rv = iter->Init(mRange); + NS_ENSURE_SUCCESS(rv, rv); + + while (!iter->IsDone()) { + nsCOMPtr node = iter->GetCurrentNode(); + NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); + + RefPtr transaction = new DeleteNodeTransaction(); + rv = transaction->Init(mEditorBase, node, mRangeUpdater); + NS_ENSURE_SUCCESS(rv, rv); + AppendChild(transaction); + + iter->Next(); + } + return NS_OK; +} + +} // namespace mozilla diff --git a/editor/libeditor/DeleteRangeTransaction.h b/editor/libeditor/DeleteRangeTransaction.h new file mode 100644 index 000000000..9b60a5ba2 --- /dev/null +++ b/editor/libeditor/DeleteRangeTransaction.h @@ -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/. */ + +#ifndef DeleteRangeTransaction_h +#define DeleteRangeTransaction_h + +#include "EditAggregateTransaction.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 +{ +public: + /** + * Initialize the transaction. + * @param aEditorBase The object providing basic editing operations. + * @param aRange The range to delete. + */ + nsresult Init(EditorBase* aEditorBase, + nsRange* aRange, + RangeUpdater* aRangeUpdater); + + DeleteRangeTransaction(); + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteRangeTransaction, + EditAggregateTransaction) + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; + + NS_DECL_EDITTRANSACTIONBASE + + NS_IMETHOD RedoTransaction() override; + + virtual void LastRelease() override + { + mRange = nullptr; + EditAggregateTransaction::LastRelease(); + } + +protected: + nsresult CreateTxnsToDeleteBetween(nsINode* aNode, + int32_t aStartOffset, + int32_t aEndOffset); + + nsresult CreateTxnsToDeleteNodesBetween(); + + nsresult CreateTxnsToDeleteContent(nsINode* aParent, + int32_t aOffset, + nsIEditor::EDirection aAction); + + // P1 in the range. + RefPtr mRange; + + // The editor for this transaction. + EditorBase* mEditorBase; + + // Range updater object. + RangeUpdater* mRangeUpdater; +}; + +} // namespace mozilla + +#endif // #ifndef DeleteRangeTransaction_h diff --git a/editor/libeditor/DeleteTextTransaction.cpp b/editor/libeditor/DeleteTextTransaction.cpp new file mode 100644 index 000000000..6de3181da --- /dev/null +++ b/editor/libeditor/DeleteTextTransaction.cpp @@ -0,0 +1,102 @@ +/* -*- 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 "mozilla/Assertions.h" +#include "mozilla/EditorBase.h" +#include "mozilla/SelectionState.h" +#include "mozilla/dom/Selection.h" +#include "nsDebug.h" +#include "nsError.h" +#include "nsIEditor.h" +#include "nsISupportsImpl.h" +#include "nsAString.h" + +namespace mozilla { + +using namespace dom; + +DeleteTextTransaction::DeleteTextTransaction( + EditorBase& aEditorBase, + nsGenericDOMDataNode& aCharData, + uint32_t aOffset, + uint32_t aNumCharsToDelete, + RangeUpdater* aRangeUpdater) + : mEditorBase(aEditorBase) + , mCharData(&aCharData) + , mOffset(aOffset) + , mNumCharsToDelete(aNumCharsToDelete) + , mRangeUpdater(aRangeUpdater) +{ + NS_ASSERTION(mCharData->Length() >= aOffset + aNumCharsToDelete, + "Trying to delete more characters than in node"); +} + +NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteTextTransaction, EditTransactionBase, + mCharData) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteTextTransaction) +NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase) + +nsresult +DeleteTextTransaction::Init() +{ + // Do nothing if the node is read-only + if (!mEditorBase.IsModifiableNode(mCharData)) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +NS_IMETHODIMP +DeleteTextTransaction::DoTransaction() +{ + MOZ_ASSERT(mCharData); + + // Get the text that we're about to delete + nsresult rv = mCharData->SubstringData(mOffset, mNumCharsToDelete, + mDeletedText); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + rv = mCharData->DeleteData(mOffset, mNumCharsToDelete); + NS_ENSURE_SUCCESS(rv, rv); + + if (mRangeUpdater) { + mRangeUpdater->SelAdjDeleteText(mCharData, mOffset, mNumCharsToDelete); + } + + // Only set selection to deletion point if editor gives permission + if (mEditorBase.GetShouldTxnSetSelection()) { + RefPtr selection = mEditorBase.GetSelection(); + NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); + rv = selection->Collapse(mCharData, mOffset); + NS_ASSERTION(NS_SUCCEEDED(rv), + "Selection could not be collapsed after undo of deletetext"); + NS_ENSURE_SUCCESS(rv, rv); + } + // Else do nothing - DOM Range gravity will adjust selection + return NS_OK; +} + +//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() +{ + MOZ_ASSERT(mCharData); + + return mCharData->InsertData(mOffset, mDeletedText); +} + +NS_IMETHODIMP +DeleteTextTransaction::GetTxnDescription(nsAString& aString) +{ + aString.AssignLiteral("DeleteTextTransaction: "); + aString += mDeletedText; + return NS_OK; +} + +} // namespace mozilla diff --git a/editor/libeditor/DeleteTextTransaction.h b/editor/libeditor/DeleteTextTransaction.h new file mode 100644 index 000000000..855d14349 --- /dev/null +++ b/editor/libeditor/DeleteTextTransaction.h @@ -0,0 +1,76 @@ +/* -*- 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 "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsGenericDOMDataNode.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 +{ +public: + /** + * Initialize the transaction. + * @param aEditorBase The provider of basic editing operations. + * @param aElement The content node to remove text from. + * @param aOffset The location in aElement to begin the deletion. + * @param aNumCharsToDelete The number of characters to delete. Not the + * number of bytes! + */ + DeleteTextTransaction(EditorBase& aEditorBase, + nsGenericDOMDataNode& aCharData, + uint32_t aOffset, + uint32_t aNumCharsToDelete, + RangeUpdater* aRangeUpdater); + + nsresult Init(); + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteTextTransaction, + EditTransactionBase) + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; + + NS_DECL_EDITTRANSACTIONBASE + + uint32_t GetOffset() { return mOffset; } + + uint32_t GetNumCharsToDelete() { return mNumCharsToDelete; } + +protected: + // The provider of basic editing operations. + EditorBase& mEditorBase; + + // The CharacterData node to operate upon. + RefPtr mCharData; + + // The offset into mCharData where the deletion is to take place. + uint32_t mOffset; + + // The number of characters to delete. + uint32_t mNumCharsToDelete; + + // The text that was deleted. + nsString mDeletedText; + + // Range updater object. + RangeUpdater* mRangeUpdater; +}; + +} // namespace mozilla + +#endif // #ifndef DeleteTextTransaction_h diff --git a/editor/libeditor/EditActionListener.h b/editor/libeditor/EditActionListener.h new file mode 100644 index 000000000..834ec76b9 --- /dev/null +++ b/editor/libeditor/EditActionListener.h @@ -0,0 +1,17 @@ +/* -*- 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 000000000..f50e8a67c --- /dev/null +++ b/editor/libeditor/EditAggregateTransaction.cpp @@ -0,0 +1,145 @@ +/* -*- 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 "nsAString.h" +#include "nsCOMPtr.h" // for nsCOMPtr +#include "nsError.h" // for NS_OK, etc. +#include "nsISupportsUtils.h" // for NS_ADDREF +#include "nsITransaction.h" // for nsITransaction +#include "nsString.h" // for nsAutoString + +namespace mozilla { + +EditAggregateTransaction::EditAggregateTransaction() +{ +} + +EditAggregateTransaction::~EditAggregateTransaction() +{ +} + +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 (uint32_t i = 0, length = mChildren.Length(); i < length; ++i) { + nsITransaction *txn = mChildren[i]; + if (!txn) { + return NS_ERROR_NULL_POINTER; + } + nsresult rv = txn->DoTransaction(); + if (NS_FAILED(rv)) { + 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. + for (uint32_t i = mChildren.Length(); i--; ) { + nsITransaction *txn = mChildren[i]; + if (!txn) { + return NS_ERROR_NULL_POINTER; + } + nsresult rv = txn->UndoTransaction(); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +NS_IMETHODIMP +EditAggregateTransaction::RedoTransaction() +{ + // It's legal (but not very useful) to have an empty child list. + for (uint32_t i = 0, length = mChildren.Length(); i < length; ++i) { + nsITransaction *txn = mChildren[i]; + if (!txn) { + return NS_ERROR_NULL_POINTER; + } + nsresult rv = txn->RedoTransaction(); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +NS_IMETHODIMP +EditAggregateTransaction::Merge(nsITransaction* aTransaction, + 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. + nsITransaction *txn = mChildren[0]; + if (!txn) { + return NS_ERROR_NULL_POINTER; + } + return txn->Merge(aTransaction, aDidMerge); +} + +NS_IMETHODIMP +EditAggregateTransaction::GetTxnDescription(nsAString& aString) +{ + aString.AssignLiteral("EditAggregateTransaction: "); + + if (mName) { + nsAutoString name; + mName->ToString(name); + aString += name; + } + + return NS_OK; +} + +NS_IMETHODIMP +EditAggregateTransaction::AppendChild(EditTransactionBase* aTransaction) +{ + if (!aTransaction) { + return NS_ERROR_NULL_POINTER; + } + + RefPtr* slot = mChildren.AppendElement(); + if (!slot) { + return NS_ERROR_OUT_OF_MEMORY; + } + + *slot = aTransaction; + return NS_OK; +} + +NS_IMETHODIMP +EditAggregateTransaction::GetName(nsIAtom** aName) +{ + if (aName && mName) { + *aName = mName; + NS_ADDREF(*aName); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} + +} // namespace mozilla diff --git a/editor/libeditor/EditAggregateTransaction.h b/editor/libeditor/EditAggregateTransaction.h new file mode 100644 index 000000000..6ba27a01f --- /dev/null +++ b/editor/libeditor/EditAggregateTransaction.h @@ -0,0 +1,58 @@ +/* -*- 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 "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIAtom.h" +#include "nsISupportsImpl.h" +#include "nsTArray.h" +#include "nscore.h" + +class nsITransaction; + +namespace mozilla { + +/** + * base class for all document editing transactions that require aggregation. + * provides a list of child transactions. + */ +class EditAggregateTransaction : public EditTransactionBase +{ +public: + EditAggregateTransaction(); + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(EditAggregateTransaction, + EditTransactionBase) + + NS_DECL_EDITTRANSACTIONBASE + + NS_IMETHOD RedoTransaction() override; + NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override; + + /** + * Append a transaction to this aggregate. + */ + NS_IMETHOD AppendChild(EditTransactionBase* aTransaction); + + /** + * Get the name assigned to this transaction. + */ + NS_IMETHOD GetName(nsIAtom** aName); + +protected: + virtual ~EditAggregateTransaction(); + + nsTArray> mChildren; + nsCOMPtr mName; +}; + +} // namespace mozilla + +#endif // #ifndef EditAggregateTransaction_h diff --git a/editor/libeditor/EditTransactionBase.cpp b/editor/libeditor/EditTransactionBase.cpp new file mode 100644 index 000000000..2905baa8c --- /dev/null +++ b/editor/libeditor/EditTransactionBase.cpp @@ -0,0 +1,55 @@ +/* -*- 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 "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(nsPIEditorTransaction) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITransaction) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(EditTransactionBase) +NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(EditTransactionBase, + LastRelease()) + +EditTransactionBase::~EditTransactionBase() +{ +} + +NS_IMETHODIMP +EditTransactionBase::RedoTransaction() +{ + return DoTransaction(); +} + +NS_IMETHODIMP +EditTransactionBase::GetIsTransient(bool* aIsTransient) +{ + *aIsTransient = false; + + return NS_OK; +} + +NS_IMETHODIMP +EditTransactionBase::Merge(nsITransaction* aTransaction, bool* aDidMerge) +{ + *aDidMerge = false; + + return NS_OK; +} + +} // namespace mozilla diff --git a/editor/libeditor/EditTransactionBase.h b/editor/libeditor/EditTransactionBase.h new file mode 100644 index 000000000..f09449f07 --- /dev/null +++ b/editor/libeditor/EditTransactionBase.h @@ -0,0 +1,44 @@ +/* -*- 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 "nsPIEditorTransaction.h" +#include "nscore.h" + +namespace mozilla { + +/** + * Base class for all document editing transactions. + */ +class EditTransactionBase : public nsITransaction + , public nsPIEditorTransaction +{ +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditTransactionBase, nsITransaction) + + virtual void LastRelease() {} + + NS_IMETHOD RedoTransaction(void) override; + NS_IMETHOD GetIsTransient(bool* aIsTransient) override; + NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override; + +protected: + virtual ~EditTransactionBase(); +}; + +} // namespace mozilla + +#define NS_DECL_EDITTRANSACTIONBASE \ + NS_IMETHOD DoTransaction() override; \ + NS_IMETHOD UndoTransaction() override; \ + NS_IMETHOD GetTxnDescription(nsAString& aTransactionDescription) override; + +#endif // #ifndef mozilla_EditTransactionBase_h diff --git a/editor/libeditor/EditorBase.cpp b/editor/libeditor/EditorBase.cpp new file mode 100644 index 000000000..13505b2d3 --- /dev/null +++ b/editor/libeditor/EditorBase.cpp @@ -0,0 +1,5244 @@ +/* -*- 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/EditorBase.h" + +#include "mozilla/DebugOnly.h" // for DebugOnly + +#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 "EditorEventListener.h" // for EditorEventListener +#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 "StyleSheetTransactions.h" // for AddStyleSheetTransaction, etc. +#include "TextEditUtils.h" // for TextEditUtils +#include "mozFlushType.h" // for mozFlushType::Flush_Frames +#include "mozInlineSpellChecker.h" // for mozInlineSpellChecker +#include "mozilla/CheckedInt.h" // for CheckedInt +#include "mozilla/EditorUtils.h" // for AutoRules, etc. +#include "mozilla/EditTransactionBase.h" // for EditTransactionBase +#include "mozilla/IMEStateManager.h" // for IMEStateManager +#include "mozilla/Preferences.h" // for Preferences +#include "mozilla/dom/Selection.h" // for Selection, etc. +#include "mozilla/Services.h" // for GetObserverService +#include "mozilla/TextComposition.h" // for TextComposition +#include "mozilla/TextEvents.h" +#include "mozilla/dom/Element.h" // for Element, nsINode::AsElement +#include "mozilla/dom/Text.h" +#include "mozilla/dom/Event.h" +#include "mozilla/mozalloc.h" // for operator new, etc. +#include "nsAString.h" // for nsAString_internal::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 "nsComputedDOMStyle.h" // for nsComputedDOMStyle +#include "nsContentUtils.h" // for nsContentUtils +#include "nsDOMString.h" // for DOMStringIsNull +#include "nsDebug.h" // for NS_ENSURE_TRUE, etc. +#include "nsError.h" // for NS_OK, etc. +#include "nsFocusManager.h" // for nsFocusManager +#include "nsFrameSelection.h" // for nsFrameSelection +#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::dir +#include "nsIAbsorbingTransaction.h" // for nsIAbsorbingTransaction +#include "nsIAtom.h" // for nsIAtom +#include "nsIContent.h" // for nsIContent +#include "nsIDOMAttr.h" // for nsIDOMAttr +#include "nsIDOMCharacterData.h" // for nsIDOMCharacterData +#include "nsIDOMDocument.h" // for nsIDOMDocument +#include "nsIDOMElement.h" // for nsIDOMElement +#include "nsIDOMEvent.h" // for nsIDOMEvent +#include "nsIDOMEventListener.h" // for nsIDOMEventListener +#include "nsIDOMEventTarget.h" // for nsIDOMEventTarget +#include "nsIDOMHTMLElement.h" // for nsIDOMHTMLElement +#include "nsIDOMKeyEvent.h" // for nsIDOMKeyEvent, etc. +#include "nsIDOMMozNamedAttrMap.h" // for nsIDOMMozNamedAttrMap +#include "nsIDOMMouseEvent.h" // for nsIDOMMouseEvent +#include "nsIDOMNode.h" // for nsIDOMNode, etc. +#include "nsIDOMNodeList.h" // for nsIDOMNodeList +#include "nsIDOMText.h" // for nsIDOMText +#include "nsIDocument.h" // for nsIDocument +#include "nsIDocumentStateListener.h" // for nsIDocumentStateListener +#include "nsIEditActionListener.h" // for nsIEditActionListener +#include "nsIEditorObserver.h" // for nsIEditorObserver +#include "nsIEditorSpellCheck.h" // for nsIEditorSpellCheck +#include "nsIFrame.h" // for nsIFrame +#include "nsIHTMLDocument.h" // for nsIHTMLDocument +#include "nsIInlineSpellChecker.h" // for nsIInlineSpellChecker, etc. +#include "nsNameSpaceManager.h" // for kNameSpaceID_None, etc. +#include "nsINode.h" // for nsINode, etc. +#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc. +#include "nsIPresShell.h" // for nsIPresShell +#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 "nsITransaction.h" // for nsITransaction +#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 nsAFlatString +#include "nsStyleConsts.h" // for NS_STYLE_DIRECTION_RTL, etc. +#include "nsStyleContext.h" // for nsStyleContext +#include "nsStyleStruct.h" // for nsStyleDisplay, nsStyleText, etc. +#include "nsStyleStructFwd.h" // for nsIFrame::StyleUIReset, etc. +#include "nsTextNode.h" // for nsTextNode +#include "nsThreadUtils.h" // for nsRunnable +#include "nsTransactionManager.h" // for nsTransactionManager +#include "prtime.h" // for PR_Now + +class nsIOutputStream; +class nsIParserService; +class nsITransferable; + +#ifdef DEBUG +#include "nsIDOMHTMLDocument.h" // for nsIDOMHTMLDocument +#endif + +// Defined in nsEditorRegistration.cpp +extern nsIParserService *sParserService; + +namespace mozilla { + +using namespace dom; +using namespace widget; + +/***************************************************************************** + * mozilla::EditorBase + *****************************************************************************/ + +EditorBase::EditorBase() + : mPlaceHolderName(nullptr) + , mSelState(nullptr) + , mPhonetic(nullptr) + , mModCount(0) + , mFlags(0) + , mUpdateCount(0) + , mPlaceHolderBatch(0) + , mAction(EditAction::none) + , mIMETextOffset(0) + , mIMETextLength(0) + , mDirection(eNone) + , mDocDirtyState(-1) + , mSpellcheckCheckboxState(eTriUnset) + , mShouldTxnSetSelection(true) + , mDidPreDestroy(false) + , mDidPostCreate(false) + , mDispatchInputEvent(true) + , mIsInEditAction(false) + , mHidingCaret(false) +{ +} + +EditorBase::~EditorBase() +{ + NS_ASSERTION(!mDocWeak || 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); + mTxnMgr = nullptr; + + delete mPhonetic; +} + +NS_IMPL_CYCLE_COLLECTION_CLASS(EditorBase) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EditorBase) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootElement) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSpellChecker) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mTxnMgr) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mIMETextNode) + 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(mEventListener) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mSavedSel); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mRangeUpdater); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditorBase) + nsIDocument* 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(mInlineSpellChecker) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTxnMgr) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIMETextNode) + 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(mSavedSel); + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRangeUpdater); +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditorBase) + NS_INTERFACE_MAP_ENTRY(nsIPhonetic) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY(nsIEditorIMESupport) + 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) + + +NS_IMETHODIMP +EditorBase::Init(nsIDOMDocument* aDoc, + nsIContent* aRoot, + nsISelectionController* aSelCon, + uint32_t aFlags, + const nsAString& aValue) +{ + MOZ_ASSERT(mAction == EditAction::none, + "Initializing during an edit action is an error"); + MOZ_ASSERT(aDoc); + if (!aDoc) + return NS_ERROR_NULL_POINTER; + + // First only set flags, but other stuff shouldn't be initialized now. + // Don't move this call after initializing mDocWeak. + // SetFlags() can check whether it's called during initialization or not by + // them. Note that SetFlags() will be called by PostCreate(). +#ifdef DEBUG + nsresult rv = +#endif + SetFlags(aFlags); + NS_ASSERTION(NS_SUCCEEDED(rv), "SetFlags() failed"); + + mDocWeak = do_GetWeakReference(aDoc); // weak reference to doc + // 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 selCon; + if (aSelCon) { + mSelConWeak = do_GetWeakReference(aSelCon); // weak reference to selectioncontroller + selCon = aSelCon; + } else { + nsCOMPtr presShell = GetPresShell(); + selCon = do_QueryInterface(presShell); + } + NS_ASSERTION(selCon, "Selection controller should be available at this point"); + + //set up root element if we are passed one. + if (aRoot) + mRootElement = do_QueryInterface(aRoot); + + mUpdateCount=0; + + // If this is an editor for or + diff --git a/editor/libeditor/crashtests/407256-1.html b/editor/libeditor/crashtests/407256-1.html new file mode 100644 index 000000000..824162ac5 --- /dev/null +++ b/editor/libeditor/crashtests/407256-1.html @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/editor/libeditor/crashtests/407277-1.html b/editor/libeditor/crashtests/407277-1.html new file mode 100644 index 000000000..41c6bf280 --- /dev/null +++ b/editor/libeditor/crashtests/407277-1.html @@ -0,0 +1,7 @@ + + + + + diff --git a/editor/libeditor/crashtests/414178-1.html b/editor/libeditor/crashtests/414178-1.html new file mode 100644 index 000000000..19cc205b9 --- /dev/null +++ b/editor/libeditor/crashtests/414178-1.html @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/editor/libeditor/crashtests/418923-1.html b/editor/libeditor/crashtests/418923-1.html new file mode 100644 index 000000000..786ea25d9 --- /dev/null +++ b/editor/libeditor/crashtests/418923-1.html @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/editor/libeditor/crashtests/420439.html b/editor/libeditor/crashtests/420439.html new file mode 100644 index 000000000..e1303307d --- /dev/null +++ b/editor/libeditor/crashtests/420439.html @@ -0,0 +1,30 @@ + + + + + + +
+ + + diff --git a/editor/libeditor/crashtests/428489-1.html b/editor/libeditor/crashtests/428489-1.html new file mode 100644 index 000000000..8eec1268b --- /dev/null +++ b/editor/libeditor/crashtests/428489-1.html @@ -0,0 +1,8 @@ + + +Crash [@ nsHTMLEditor::GetPositionAndDimensions] when window gets removed during click on contenteditable absolute positioned element + + + + + diff --git a/editor/libeditor/crashtests/429586-1.html b/editor/libeditor/crashtests/429586-1.html new file mode 100644 index 000000000..a32df3b72 --- /dev/null +++ b/editor/libeditor/crashtests/429586-1.html @@ -0,0 +1,8 @@ + + +Bug 429586 - Crash [@ nsEditor::EndUpdateViewBatch] with pasting and domattrmodified removing iframe + + + + + diff --git a/editor/libeditor/crashtests/430624-1.html b/editor/libeditor/crashtests/430624-1.html new file mode 100644 index 000000000..bfa95c662 --- /dev/null +++ b/editor/libeditor/crashtests/430624-1.html @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/editor/libeditor/crashtests/431086-1.xhtml b/editor/libeditor/crashtests/431086-1.xhtml new file mode 100644 index 000000000..c6c5d8d99 --- /dev/null +++ b/editor/libeditor/crashtests/431086-1.xhtml @@ -0,0 +1,22 @@ +
+ + + +
diff --git a/editor/libeditor/crashtests/448329-1.html b/editor/libeditor/crashtests/448329-1.html new file mode 100644 index 000000000..99d0f63b3 --- /dev/null +++ b/editor/libeditor/crashtests/448329-1.html @@ -0,0 +1,72 @@ + + + + Testcase for bug 448329 + + + + + + + + + + diff --git a/editor/libeditor/crashtests/448329-2.html b/editor/libeditor/crashtests/448329-2.html new file mode 100644 index 000000000..fd4707b54 --- /dev/null +++ b/editor/libeditor/crashtests/448329-2.html @@ -0,0 +1,21 @@ + + + Testcase for bug 448329 + + + + diff --git a/editor/libeditor/crashtests/448329-3.html b/editor/libeditor/crashtests/448329-3.html new file mode 100644 index 000000000..0a48c1818 --- /dev/null +++ b/editor/libeditor/crashtests/448329-3.html @@ -0,0 +1,112 @@ + + + + Testcase #3 for bug 448329 + + + + + + + + + + diff --git a/editor/libeditor/crashtests/456727-1.html b/editor/libeditor/crashtests/456727-1.html new file mode 100644 index 000000000..d14422c93 --- /dev/null +++ b/editor/libeditor/crashtests/456727-1.html @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/editor/libeditor/crashtests/456727-2.html b/editor/libeditor/crashtests/456727-2.html new file mode 100644 index 000000000..1c8fe5db9 --- /dev/null +++ b/editor/libeditor/crashtests/456727-2.html @@ -0,0 +1,8 @@ + + + + diff --git a/editor/libeditor/crashtests/459613-iframe.html b/editor/libeditor/crashtests/459613-iframe.html new file mode 100644 index 000000000..9f6e558d0 --- /dev/null +++ b/editor/libeditor/crashtests/459613-iframe.html @@ -0,0 +1 @@ + diff --git a/editor/libeditor/crashtests/459613.html b/editor/libeditor/crashtests/459613.html new file mode 100644 index 000000000..7a335f22e --- /dev/null +++ b/editor/libeditor/crashtests/459613.html @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/editor/libeditor/crashtests/467647-1.html b/editor/libeditor/crashtests/467647-1.html new file mode 100644 index 000000000..7bb4271d7 --- /dev/null +++ b/editor/libeditor/crashtests/467647-1.html @@ -0,0 +1,19 @@ + + + + + + +One
+ + diff --git a/editor/libeditor/crashtests/475132-1.xhtml b/editor/libeditor/crashtests/475132-1.xhtml new file mode 100644 index 000000000..8b4dd688c --- /dev/null +++ b/editor/libeditor/crashtests/475132-1.xhtml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/editor/libeditor/crashtests/499844-1.html b/editor/libeditor/crashtests/499844-1.html new file mode 100644 index 000000000..4fa509c4a --- /dev/null +++ b/editor/libeditor/crashtests/499844-1.html @@ -0,0 +1,15 @@ + + + + + + ́ + diff --git a/editor/libeditor/crashtests/503709-1.xhtml b/editor/libeditor/crashtests/503709-1.xhtml new file mode 100644 index 000000000..867bebf1a --- /dev/null +++ b/editor/libeditor/crashtests/503709-1.xhtml @@ -0,0 +1,11 @@ +x y z
diff --git a/editor/libeditor/crashtests/513375-1.xhtml b/editor/libeditor/crashtests/513375-1.xhtml new file mode 100644 index 000000000..25e5e1c34 --- /dev/null +++ b/editor/libeditor/crashtests/513375-1.xhtml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/535632-1.xhtml b/editor/libeditor/crashtests/535632-1.xhtml new file mode 100644 index 000000000..92470b825 --- /dev/null +++ b/editor/libeditor/crashtests/535632-1.xhtml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/libeditor/crashtests/574558-1.xhtml b/editor/libeditor/crashtests/574558-1.xhtml new file mode 100644 index 000000000..6aac47072 --- /dev/null +++ b/editor/libeditor/crashtests/574558-1.xhtml @@ -0,0 +1,15 @@ +
diff --git a/editor/libeditor/crashtests/580151-1.xhtml b/editor/libeditor/crashtests/580151-1.xhtml new file mode 100644 index 000000000..379941111 --- /dev/null +++ b/editor/libeditor/crashtests/580151-1.xhtml @@ -0,0 +1,26 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/582138-1.xhtml b/editor/libeditor/crashtests/582138-1.xhtml new file mode 100644 index 000000000..afcec2eba --- /dev/null +++ b/editor/libeditor/crashtests/582138-1.xhtml @@ -0,0 +1,10 @@ + diff --git a/editor/libeditor/crashtests/612565-1.html b/editor/libeditor/crashtests/612565-1.html new file mode 100644 index 000000000..1b059aa66 --- /dev/null +++ b/editor/libeditor/crashtests/612565-1.html @@ -0,0 +1,17 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/615015-1.html b/editor/libeditor/crashtests/615015-1.html new file mode 100644 index 000000000..a383f9e75 --- /dev/null +++ b/editor/libeditor/crashtests/615015-1.html @@ -0,0 +1,17 @@ + + + + + +T + diff --git a/editor/libeditor/crashtests/615450-1.html b/editor/libeditor/crashtests/615450-1.html new file mode 100644 index 000000000..fb36bddc9 --- /dev/null +++ b/editor/libeditor/crashtests/615450-1.html @@ -0,0 +1,17 @@ + + + + + +
p q r s T
diff --git a/editor/libeditor/crashtests/633709.xhtml b/editor/libeditor/crashtests/633709.xhtml new file mode 100644 index 000000000..139389001 --- /dev/null +++ b/editor/libeditor/crashtests/633709.xhtml @@ -0,0 +1,36 @@ + + +
+ + + + diff --git a/editor/libeditor/crashtests/636074-1.html b/editor/libeditor/crashtests/636074-1.html new file mode 100644 index 000000000..e99c42ea6 --- /dev/null +++ b/editor/libeditor/crashtests/636074-1.html @@ -0,0 +1,18 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/639736-1.xhtml b/editor/libeditor/crashtests/639736-1.xhtml new file mode 100644 index 000000000..4692daee7 --- /dev/null +++ b/editor/libeditor/crashtests/639736-1.xhtml @@ -0,0 +1,14 @@ + + + + + + diff --git a/editor/libeditor/crashtests/643786-1.html b/editor/libeditor/crashtests/643786-1.html new file mode 100644 index 000000000..3f0b27a54 --- /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 000000000..a86f6e618 --- /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 000000000..275269522 --- /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 000000000..66ebc2f62 --- /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 000000000..21da24693 --- /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 000000000..b04a5d773 --- /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 000000000..a5ef5a2cc --- /dev/null +++ b/editor/libeditor/crashtests/716456-1.html @@ -0,0 +1,29 @@ + + + + + + +
+ diff --git a/editor/libeditor/crashtests/759748.html b/editor/libeditor/crashtests/759748.html new file mode 100644 index 000000000..1e85a3877 --- /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 000000000..0c1f3f521 --- /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 000000000..1916ac6fb --- /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 000000000..a5000fe73 --- /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 000000000..76c30456d --- /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 000000000..20ccc60d4 --- /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 000000000..c5d9835e3 --- /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 000000000..b4ade3020 --- /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 000000000..409e21010 --- /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 000000000..3dfad160c --- /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 000000000..09206dce3 --- /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 000000000..060e5161b --- /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 000000000..8ea8a3601 --- /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 000000000..724f6b899 --- /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 000000000..9237364f2 --- /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 000000000..f6259b344 --- /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 000000000..9fc2776c3 --- /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 000000000..4984474db --- /dev/null +++ b/editor/libeditor/crashtests/793866.html @@ -0,0 +1,21 @@ + + + + + + + diff --git a/editor/libeditor/crashtests/crashtests.list b/editor/libeditor/crashtests/crashtests.list new file mode 100644 index 000000000..3fbc6b196 --- /dev/null +++ b/editor/libeditor/crashtests/crashtests.list @@ -0,0 +1,71 @@ +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 +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 1057677.html +needs-focus load 1128787.html +load 1134545.html +load 1158452.html +load 1158651.html +load 1244894.xhtml +load 1272490.html +load 1317704.html diff --git a/editor/libeditor/moz.build b/editor/libeditor/moz.build new file mode 100644 index 000000000..998ef3d39 --- /dev/null +++ b/editor/libeditor/moz.build @@ -0,0 +1,100 @@ +# -*- 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 += [ + 'nsIEditRules.h', +] + +EXPORTS.mozilla += [ + 'ChangeStyleTransaction.h', + 'CSSEditUtils.h', + 'EditorBase.h', + 'EditorController.h', + 'EditorUtils.h', + 'EditTransactionBase.h', + 'HTMLEditor.h', + 'SelectionState.h', + 'TextEditor.h', + 'TextEditRules.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', + 'HTMLEditorDataTransfer.cpp', + 'HTMLEditorEventListener.cpp', + 'HTMLEditorObjectResizer.cpp', + 'HTMLEditRules.cpp', + 'HTMLEditUtils.cpp', + 'HTMLInlineTableEditor.cpp', + 'HTMLStyleEditor.cpp', + 'HTMLTableEditor.cpp', + 'HTMLURIRefObject.cpp', + 'InsertNodeTransaction.cpp', + 'InsertTextTransaction.cpp', + 'InternetCiter.cpp', + 'JoinNodeTransaction.cpp', + 'PlaceholderTransaction.cpp', + 'SelectionState.cpp', + 'SetDocumentTitleTransaction.cpp', + 'SplitNodeTransaction.cpp', + 'StyleSheetTransactions.cpp', + 'TextEditor.cpp', + 'TextEditorDataTransfer.cpp', + 'TextEditorTest.cpp', + 'TextEditRules.cpp', + 'TextEditRulesBidi.cpp', + 'TextEditUtils.cpp', + 'TypeInState.cpp', + 'WSRunObject.cpp', +] + +LOCAL_INCLUDES += [ + '/dom/base', + '/editor/txmgr', + '/extensions/spellcheck/src', + '/layout/generic', + '/layout/style', + '/layout/tables', + '/layout/xul', +] + +EXTRA_COMPONENTS += [ + 'EditorUtils.js', + 'EditorUtils.manifest', +] + +include('/ipc/chromium/chromium-config.mozbuild') + +FINAL_LIBRARY = 'xul' + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wno-error=shadow'] diff --git a/editor/libeditor/nsIAbsorbingTransaction.h b/editor/libeditor/nsIAbsorbingTransaction.h new file mode 100644 index 000000000..e22caed4a --- /dev/null +++ b/editor/libeditor/nsIAbsorbingTransaction.h @@ -0,0 +1,57 @@ +/* -*- 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 nsIAbsorbingTransaction_h__ +#define nsIAbsorbingTransaction_h__ + +#include "nsISupports.h" + +/* +Transaction interface to outside world +*/ + +#define NS_IABSORBINGTRANSACTION_IID \ +{ /* a6cf9116-15b3-11d2-932e-00805f8add32 */ \ + 0xa6cf9116, \ + 0x15b3, \ + 0x11d2, \ + {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} } + +class nsIAtom; + +namespace mozilla { +class EditorBase; +class SelectionState; +} // namespace mozilla + +/** + * A transaction interface mixin - for transactions that can support. + * the placeholder absorbtion idiom. + */ +class nsIAbsorbingTransaction : public nsISupports{ +public: + + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IABSORBINGTRANSACTION_IID) + + NS_IMETHOD Init(nsIAtom* aName, mozilla::SelectionState* aSelState, + mozilla::EditorBase* aEditorBase) = 0; + + NS_IMETHOD EndPlaceHolderBatch()=0; + + NS_IMETHOD GetTxnName(nsIAtom **aName)=0; + + NS_IMETHOD StartSelectionEquals(mozilla::SelectionState* aSelState, + bool* aResult) = 0; + + NS_IMETHOD ForwardEndBatchTo(nsIAbsorbingTransaction *aForwardingAddress)=0; + + NS_IMETHOD Commit()=0; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsIAbsorbingTransaction, + NS_IABSORBINGTRANSACTION_IID) + +#endif // nsIAbsorbingTransaction_h__ + diff --git a/editor/libeditor/nsIEditRules.h b/editor/libeditor/nsIEditRules.h new file mode 100644 index 000000000..b186895ae --- /dev/null +++ b/editor/libeditor/nsIEditRules.h @@ -0,0 +1,68 @@ +/* -*- 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 nsIEditRules_h +#define nsIEditRules_h + +#define NS_IEDITRULES_IID \ +{ 0x3836386d, 0x806a, 0x488d, \ + { 0x8b, 0xab, 0xaf, 0x42, 0xbb, 0x4c, 0x90, 0x66 } } + +#include "mozilla/EditorBase.h" // for EditAction enum + +namespace mozilla { + +class TextEditor; +namespace dom { +class Selection; +} // namespace dom + +/** + * Base for an object to encapsulate any additional info needed to be passed + * to rules system by the editor. + */ +class RulesInfo +{ +public: + explicit RulesInfo(EditAction aAction) + : action(aAction) + {} + virtual ~RulesInfo() {} + + EditAction action; +}; + +} // namespace mozilla + +/** + * Interface of editing rules. + */ +class nsIEditRules : public nsISupports +{ +public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IEDITRULES_IID) + +//Interfaces for addref and release and queryinterface +//NOTE: Use NS_DECL_ISUPPORTS_INHERITED in any class inherited from nsIEditRules + + NS_IMETHOD Init(mozilla::TextEditor* aTextEditor) = 0; + NS_IMETHOD SetInitialValue(const nsAString& aValue) = 0; + NS_IMETHOD DetachEditor() = 0; + NS_IMETHOD BeforeEdit(EditAction action, + nsIEditor::EDirection aDirection) = 0; + NS_IMETHOD AfterEdit(EditAction action, + nsIEditor::EDirection aDirection) = 0; + NS_IMETHOD WillDoAction(mozilla::dom::Selection* aSelection, + mozilla::RulesInfo* aInfo, bool* aCancel, + bool* aHandled) = 0; + NS_IMETHOD DidDoAction(mozilla::dom::Selection* aSelection, + mozilla::RulesInfo* aInfo, nsresult aResult) = 0; + NS_IMETHOD DocumentIsEmpty(bool* aDocumentIsEmpty) = 0; + NS_IMETHOD DocumentModified() = 0; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsIEditRules, NS_IEDITRULES_IID) + +#endif // #ifndef nsIEditRules_h diff --git a/editor/libeditor/tests/browser.ini b/editor/libeditor/tests/browser.ini new file mode 100644 index 000000000..249f59aa8 --- /dev/null +++ b/editor/libeditor/tests/browser.ini @@ -0,0 +1,6 @@ +[browser_bug527935.js] +skip-if = toolkit == 'android' +support-files = bug527935.html +[browser_bug629172.js] +skip-if = toolkit == 'android' +support-files = bug629172.html diff --git a/editor/libeditor/tests/browser_bug527935.js b/editor/libeditor/tests/browser_bug527935.js new file mode 100644 index 000000000..dc6e74d3e --- /dev/null +++ b/editor/libeditor/tests/browser_bug527935.js @@ -0,0 +1,63 @@ +add_task(function*() { + yield new Promise(resolve => waitForFocus(resolve, window)); + + const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug527935.html"; + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: kPageURL + }, function*(aBrowser) { + var popupShown = false; + function listener() { + popupShown = true; + } + SpecialPowers.addAutoCompletePopupEventListener(window, "popupshowing", listener); + + yield ContentTask.spawn(aBrowser, {}, 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("VK_RETURN", {}); + + yield ContentTask.spawn(aBrowser, {}, function*() { + var window = content.window.wrappedJSObject; + var document = window.document; + + yield 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); + }); + + yield 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/browser_bug629172.js b/editor/libeditor/tests/browser_bug629172.js new file mode 100644 index 000000000..0c4f34069 --- /dev/null +++ b/editor/libeditor/tests/browser_bug629172.js @@ -0,0 +1,106 @@ +add_task(function*() { + yield new Promise(resolve => waitForFocus(resolve, window)); + + const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug629172.html"; + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: kPageURL + }, function*(aBrowser) { + yield ContentTask.spawn(aBrowser, {}, function*() { + var window = content.window.wrappedJSObject; + var document = window.document; + + // Note: Using the with keyword, we would have been able to write this as: + // + // with (window) { + // Screenshots = {}; + // // so on + // } + // + // However, browser-chrome tests are somehow forced to run in strict mode, + // which doesn't permit the usage of the with keyword, turning the following + // into the ugliest test you've ever seen. :( + var LTRRef = document.getElementById("ltr-ref"); + var RTLRef = document.getElementById("rtl-ref"); + window.Screenshots = {}; + + // generate the reference screenshots + LTRRef.style.display = ""; + document.body.clientWidth; + window.Screenshots.ltr = window.snapshotWindow(window); + LTRRef.parentNode.removeChild(LTRRef); + RTLRef.style.display = ""; + document.body.clientWidth; + window.Screenshots.rtl = window.snapshotWindow(window); + RTLRef.parentNode.removeChild(RTLRef); + window.Screenshots.get = function(dir, flip) { + if (flip) { + return this[dir == "rtl" ? "ltr" : "rtl"]; + } else { + return this[dir]; + } + }; + }); + + function simulateCtrlShiftX(aBrowser) { + // In e10s, the keypress event will be dispatched to the content process, + // but in non-e10s it is handled by the browser UI code and hence won't + // reach the web page. As a result, we need to observe the event in + // the content process only in e10s mode. + var waitForKeypressContent = BrowserTestUtils.waitForContentEvent(aBrowser, "keypress"); + EventUtils.synthesizeKey("x", {accelKey: true, shiftKey: true}); + if (gMultiProcessBrowser) { + return waitForKeypressContent; + } + return Promise.resolve(); + } + + function* testDirection(initialDir, aBrowser) { + yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) { + var window = content.window.wrappedJSObject; + var document = window.document; + + var t = window.t = document.createElement("textarea"); + t.setAttribute("dir", initialDir); + t.value = "test."; + window.inputEventCount = 0; + t.oninput = function() { window.inputEventCount++; }; + document.getElementById("content").appendChild(t); + document.body.clientWidth; + var s1 = window.snapshotWindow(window); + ok(window.compareSnapshots(s1, window.Screenshots.get(initialDir, false), true)[0], + "Textarea should appear correctly before switching the direction (" + initialDir + ")"); + t.focus(); + is(window.inputEventCount, 0, "input event count must be 0 before"); + }); + yield simulateCtrlShiftX(aBrowser); + yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) { + var window = content.window.wrappedJSObject; + + is(window.t.getAttribute("dir"), initialDir == "ltr" ? "rtl" : "ltr", "The dir attribute must be correctly updated"); + is(window.inputEventCount, 1, "input event count must be 1 after"); + window.t.blur(); + var s2 = window.snapshotWindow(window); + ok(window.compareSnapshots(s2, window.Screenshots.get(initialDir, true), true)[0], + "Textarea should appear correctly after switching the direction (" + initialDir + ")"); + window.t.focus(); + is(window.inputEventCount, 1, "input event count must be 1 before"); + }); + yield simulateCtrlShiftX(aBrowser); + yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) { + var window = content.window.wrappedJSObject; + + is(window.inputEventCount, 2, "input event count must be 2 after"); + is(window.t.getAttribute("dir"), initialDir == "ltr" ? "ltr" : "rtl", "The dir attribute must be correctly updated"); + window.t.blur(); + var s3 = window.snapshotWindow(window); + ok(window.compareSnapshots(s3, window.Screenshots.get(initialDir, false), true)[0], + "Textarea should appear correctly after switching back the direction (" + initialDir + ")"); + window.t.parentNode.removeChild(window.t); + }); + } + + yield testDirection("ltr", aBrowser); + yield testDirection("rtl", aBrowser); + }); +}); diff --git a/editor/libeditor/tests/browserscope/lib/richtext/LICENSE b/editor/libeditor/tests/browserscope/lib/richtext/LICENSE new file mode 100644 index 000000000..57bc88a15 --- /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 000000000..a3bc3110f --- /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 000000000..5d304943f --- /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 000000000..b30775d04 --- /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 000000000..1e2569914 --- /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 000000000..a294f0b56 --- /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 000000000..3e4463e11 --- /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.indexOf("&") != -1)str = str.replace(goog$string$amperRe_, "&"); + if(str.indexOf("<") != -1)str = str.replace(goog$string$ltRe_, "<"); + if(str.indexOf(">") != -1)str = str.replace(goog$string$gtRe_, ">"); + if(str.indexOf('"') != -1)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.indexOf(ss) != -1 +}, 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.indexOf("MSIE") != -1; + goog$userAgent$detectedMobile_ = (goog$userAgent$detectedWebkit_ = !goog$userAgent$detectedOpera_ && JSCompiler_inline_ua_15.indexOf("WebKit") != -1) && JSCompiler_inline_ua_15.indexOf("Mobile") != -1; + 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 000000000..ef0e22f2a --- /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 000000000..2071454a8 --- /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 000000000..57bc88a15 --- /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 000000000..a3bc3110f --- /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 000000000..3e667a0b7 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/README.Mozilla @@ -0,0 +1,23 @@ +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. 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 000000000..570853afa --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js @@ -0,0 +1,1850 @@ +/** + * 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_SB-body": true, + "D-Proposed-DIV:ce:false-1_SB-div": 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_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_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_SB-body": true, + "D-Proposed-DIV:ce:false-1_SB-div": 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 000000000..cc34bb397 --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/current_revision @@ -0,0 +1 @@ +805 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 000000000..e69de29bb 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 000000000..345f9bbb0 --- /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 000000000..2ee1e79ad --- /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 000000000..77c6bb872 --- /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 000000000..a254adc03 --- /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 000000000..e16de3ab9 --- /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 000000000..7dd600dbd --- /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 000000000..99fec4950 --- /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 000000000..2236d9dfc --- /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 000000000..be059cfc8 --- /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 000000000..897efa011 --- /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 000000000..282f0d907 --- /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 000000000..24aef7ae9 --- /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 000000000..f323cf9b6 --- /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 000000000..a1f5279ad --- /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 000000000..3eb465c84 --- /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 000000000..94cdad83f --- /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 000000000..6a76d3d5f --- /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 000000000..4862b9b73 --- /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 000000000..0cc659225 --- /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 000000000..d625a2a7d --- /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 000000000..a2e79c27c --- /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 000000000..eb721923b --- /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 000000000..d1ad8debd --- /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 000000000..297559d62 --- /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 000000000..af23a428c --- /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 000000000..793b7cb6c --- /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 000000000..35891386a --- /dev/null +++ b/editor/libeditor/tests/browserscope/lib/richtext2/richtext2/tests/selection.py @@ -0,0 +1,772 @@ + +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: 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 000000000..adad65617 --- /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 000000000..6f934a0f0 --- /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 000000000..4e27b0554 --- /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 000000000..baeb76745 --- /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 000000000..e6e2db413 --- /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/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] +subsuite = clipboard +skip-if = os == 'android' && debug # 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 000000000..45f8bef38 --- /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 000000000..c0ce07a8f --- /dev/null +++ b/editor/libeditor/tests/browserscope/test_richtext2.html @@ -0,0 +1,233 @@ + + + + + + + + BrowserScope Richtext2 Tests + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/editor/libeditor/tests/bug527935.html b/editor/libeditor/tests/bug527935.html new file mode 100644 index 000000000..4bfa1bac2 --- /dev/null +++ b/editor/libeditor/tests/bug527935.html @@ -0,0 +1,11 @@ + + + +
      + +
      + +
      +
      + + + + + + + + +
      + + +
      + diff --git a/editor/libeditor/tests/chrome.ini b/editor/libeditor/tests/chrome.ini new file mode 100644 index 000000000..98db30001 --- /dev/null +++ b/editor/libeditor/tests/chrome.ini @@ -0,0 +1,14 @@ +[DEFAULT] +skip-if = os == 'android' +support-files = green.png + +[test_bug489202.xul] +[test_bug599983.xul] +[test_bug607584.xul] +[test_bug616590.xul] +[test_bug780908.xul] +[test_contenteditable_text_input_handling.html] +[test_htmleditor_keyevent_handling.html] +[test_set_document_title_transaction.html] +[test_texteditor_keyevent_handling.html] +skip-if = (debug && os=='win') || (os == 'linux') # Bug 1116205, leaks on windows debug, fails delete key on linux diff --git a/editor/libeditor/tests/data/cfhtml-chromium.txt b/editor/libeditor/tests/data/cfhtml-chromium.txt new file mode 100644 index 000000000..7e0253715 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 000000000..cc686d856 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 000000000..a30bc5295 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 000000000..aa4882227 --- /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 000000000..0bcf7616e Binary files /dev/null and b/editor/libeditor/tests/data/cfhtml-ooo.txt differ diff --git a/editor/libeditor/tests/file_bug549262.html b/editor/libeditor/tests/file_bug549262.html new file mode 100644 index 000000000..92a0c76f3 --- /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 000000000..298953197 --- /dev/null +++ b/editor/libeditor/tests/file_bug586662.html @@ -0,0 +1,7 @@ + + + +
      + + + diff --git a/editor/libeditor/tests/file_bug674770-1.html b/editor/libeditor/tests/file_bug674770-1.html new file mode 100644 index 000000000..6750bb878 --- /dev/null +++ b/editor/libeditor/tests/file_bug674770-1.html @@ -0,0 +1,5 @@ + + diff --git a/editor/libeditor/tests/file_bug915962.html b/editor/libeditor/tests/file_bug915962.html new file mode 100644 index 000000000..85c5139d3 --- /dev/null +++ b/editor/libeditor/tests/file_bug915962.html @@ -0,0 +1,13 @@ + + + + + + + + + +

      + + diff --git a/editor/libeditor/tests/file_select_all_without_body.html b/editor/libeditor/tests/file_select_all_without_body.html new file mode 100644 index 000000000..70050a847 --- /dev/null +++ b/editor/libeditor/tests/file_select_all_without_body.html @@ -0,0 +1,41 @@ + + + + + + diff --git a/editor/libeditor/tests/green.png b/editor/libeditor/tests/green.png new file mode 100644 index 000000000..0aaec2093 Binary files /dev/null and b/editor/libeditor/tests/green.png differ diff --git a/editor/libeditor/tests/mochitest.ini b/editor/libeditor/tests/mochitest.ini new file mode 100644 index 000000000..447fb8b65 --- /dev/null +++ b/editor/libeditor/tests/mochitest.ini @@ -0,0 +1,245 @@ +[DEFAULT] +support-files = + data/cfhtml-chromium.txt + data/cfhtml-firefox.txt + data/cfhtml-ie.txt + data/cfhtml-ooo.txt + data/cfhtml-nocontext.txt + file_bug549262.html + file_bug586662.html + file_bug674770-1.html + file_bug915962.html + file_select_all_without_body.html + green.png + spellcheck.js + +[test_bug46555.html] +[test_bug200416.html] +[test_bug289384.html] +skip-if = os != "mac" +[test_bug290026.html] +[test_bug291780.html] +[test_bug309731.html] +[test_bug316447.html] +[test_bug318065.html] +[test_bug332636.html] +support-files = test_bug332636.html^headers^ +[test_bug366682.html] +skip-if = os == 'android' +[test_bug372345.html] +skip-if = toolkit == 'android' +[test_bug404320.html] +[test_bug408231.html] +skip-if = toolkit == 'android' +[test_bug410986.html] +subsuite = clipboard +skip-if = toolkit == 'android' +[test_bug414526.html] +[test_bug417418.html] +skip-if = android_version == '18' # bug 1147989 +[test_bug432225.html] +skip-if = toolkit == 'android' +[test_bug439808.html] +[test_bug442186.html] +[test_bug449243.html] +[test_bug455992.html] +[test_bug456244.html] +[test_bug460740.html] +[test_bug468353.html] +[test_bug471319.html] +[test_bug471722.html] +[test_bug478725.html] +subsuite = clipboard +skip-if = toolkit == 'android' +[test_bug480647.html] +[test_bug480972.html] +subsuite = clipboard +skip-if = toolkit == 'android' +[test_bug483651.html] +[test_bug484181.html] +skip-if = toolkit == 'android' +[test_bug487524.html] +[test_bug490879.html] +subsuite = clipboard +skip-if = toolkit == 'android' # bug 1299578 +[test_bug502673.html] +[test_bug514156.html] +[test_bug520189.html] +subsuite = clipboard +skip-if = toolkit == 'android' +[test_bug525389.html] +subsuite = clipboard +skip-if = toolkit == 'android' +[test_bug537046.html] +[test_bug549262.html] +skip-if = toolkit == 'android' +[test_bug550434.html] +skip-if = android_version == '18' # bug 1147989 +[test_bug551704.html] +subsuite = clipboard +[test_bug552782.html] +[test_bug567213.html] +[test_bug569988.html] +skip-if = os == 'android' +[test_bug570144.html] +[test_bug578771.html] +skip-if = android_version == '18' # bug 1147989 +[test_bug586662.html] +skip-if = toolkit == 'android' +[test_bug587461.html] +[test_bug590554.html] +[test_bug592592.html] +[test_bug596001.html] +subsuite = clipboard +[test_bug596333.html] +skip-if = toolkit == 'android' +[test_bug596506.html] +[test_bug597331.html] +skip-if = toolkit == 'android' || asan || (os == "win" && os_version != "5.1") # Bug 718316, Bug 1211213 +[test_bug597784.html] +[test_bug599322.html] +subsuite = clipboard +skip-if = toolkit == 'android' +[test_bug599983.html] +[test_bug600570.html] +subsuite = clipboard +skip-if = toolkit == 'android' || (os == "win" && os_version != "5.1") # Bug 718316 +[test_bug602130.html] +[test_bug603556.html] +subsuite = clipboard +[test_bug604532.html] +skip-if = toolkit == 'android' +[test_bug607584.html] +[test_bug611182.html] +skip-if = toolkit == 'android' +[test_bug612128.html] +[test_bug612447.html] +[test_bug620906.html] +skip-if = toolkit == 'android' #TIMED_OUT +[test_bug622371.html] +skip-if = toolkit == 'android' #bug 957797 +[test_bug625452.html] +[test_bug629845.html] +[test_bug635636.html] +skip-if = e10s || os == 'android' +[test_bug636465.html] +skip-if = os == 'android' +[test_bug638596.html] +[test_bug640321.html] +skip-if = android_version == '18' # bug 1147989 +[test_bug641466.html] +[test_bug645914.html] +[test_bug646194.html] +[test_bug668599.html] +[test_bug674770-1.html] +subsuite = clipboard +skip-if = toolkit == 'android' +[test_bug674770-2.html] +subsuite = clipboard +skip-if = toolkit == 'android' +[test_bug674861.html] +[test_bug676401.html] +[test_bug677752.html] +[test_bug681229.html] +subsuite = clipboard +[test_bug686203.html] +[test_bug692520.html] +[test_bug697842.html] +[test_bug725069.html] +[test_bug735059.html] +[test_bug738366.html] +[test_bug740784.html] +[test_bug742261.html] +[test_bug757371.html] +[test_bug757771.html] +[test_bug767684.html] +[test_bug772796.html] +skip-if = toolkit == 'android' # bug 1309431 +[test_bug773262.html] +[test_bug780035.html] +[test_bug787432.html] +[test_bug790475.html] +[test_bug795418.html] +[test_bug795418-2.html] +[test_bug795418-3.html] +[test_bug795418-4.html] +[test_bug795418-5.html] +[test_bug795418-6.html] +[test_bug795785.html] +[test_bug796839.html] +[test_bug830600.html] +subsuite = clipboard +skip-if = e10s +[test_bug832025.html] +[test_bug850043.html] +[test_bug857487.html] +[test_bug858918.html] +[test_bug915962.html] +[test_bug974309.html] +skip-if = toolkit == 'android' +[test_bug966155.html] +skip-if = os != "win" +[test_bug966552.html] +skip-if = os != "win" +[test_bug998188.html] +[test_bug1026397.html] +[test_bug1053048.html] +[test_bug1067255.html] +[test_bug1068979.html] +subsuite = clipboard +[test_bug1094000.html] +[test_bug1100966.html] +skip-if = os == 'android' +[test_bug1102906.html] +skip-if = os == 'android' +[test_bug1101392.html] +subsuite = clipboard +[test_bug1109465.html] +[test_bug1140105.html] +[test_bug1140617.html] +subsuite = clipboard +skip-if = toolkit == 'android' # bug 1299578 +[test_bug1153237.html] +[test_bug1154791.html] +skip-if = os == 'android' +[test_bug1162952.html] +[test_bug1181130-1.html] +[test_bug1181130-2.html] +[test_bug1186799.html] +[test_bug1230473.html] +[test_bug1247483.html] +subsuite = clipboard +skip-if = toolkit == 'android' +[test_bug1248128.html] +[test_bug1250010.html] +[test_bug1257363.html] +[test_bug1248185.html] +[test_bug1258085.html] +[test_bug1268736.html] +[test_bug1270235.html] +[test_bug1310912.html] +skip-if = toolkit == 'android' # bug 1315898 +[test_bug1314790.html] +[test_bug1315065.html] +[test_bug1328023.html] +[test_bug1330796.html] +[test_bug1332876.html] + +[test_CF_HTML_clipboard.html] +subsuite = clipboard +[test_composition_event_created_in_chrome.html] +[test_contenteditable_focus.html] +[test_dom_input_event_on_htmleditor.html] +skip-if = toolkit == 'android' # bug 1054087 +[test_dom_input_event_on_texteditor.html] +[test_dragdrop.html] +skip-if = os == 'android' +[test_keypress_untrusted_event.html] +[test_root_element_replacement.html] +[test_select_all_without_body.html] +[test_spellcheck_pref.html] +skip-if = toolkit == 'android' +[test_backspace_vs.html] +[test_css_chrome_load_access.html] +skip-if = toolkit == 'android' # chrome urls not available due to packaging +[test_selection_move_commands.html] diff --git a/editor/libeditor/tests/spellcheck.js b/editor/libeditor/tests/spellcheck.js new file mode 100644 index 000000000..9d36c3254 --- /dev/null +++ b/editor/libeditor/tests/spellcheck.js @@ -0,0 +1,20 @@ +function isSpellingCheckOk(aEditor, aMisspelledWords) { + var selcon = aEditor.selectionController; + var sel = selcon.getSelection(selcon.SELECTION_SPELLCHECK); + var numWords = sel.rangeCount; + + is(numWords, aMisspelledWords.length, "Correct number of misspellings and words."); + + if (numWords !== aMisspelledWords.length) { + return false; + } + + for (var i = 0; i < numWords; ++i) { + var word = String(sel.getRangeAt(i)); + is(word, aMisspelledWords[i], "Misspelling is what we think it is."); + if (word !== aMisspelledWords[i]) { + return false; + } + } + return true; +} diff --git a/editor/libeditor/tests/test_CF_HTML_clipboard.html b/editor/libeditor/tests/test_CF_HTML_clipboard.html new file mode 100644 index 000000000..4949f40b3 --- /dev/null +++ b/editor/libeditor/tests/test_CF_HTML_clipboard.html @@ -0,0 +1,159 @@ + + + + + Test for Bug 572642 + + + + + +Mozilla Bug 572642 +

      +
      +
      + +
      +
      +
      +
      + + diff --git a/editor/libeditor/tests/test_backspace_vs.html b/editor/libeditor/tests/test_backspace_vs.html new file mode 100644 index 000000000..1ee754c95 --- /dev/null +++ b/editor/libeditor/tests/test_backspace_vs.html @@ -0,0 +1,130 @@ + + + + + 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 000000000..487f3e87f --- /dev/null +++ b/editor/libeditor/tests/test_bug1026397.html @@ -0,0 +1,103 @@ + + + + + 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 000000000..4032d32c2 --- /dev/null +++ b/editor/libeditor/tests/test_bug1053048.html @@ -0,0 +1,73 @@ + + + + + + Test for Bug 1053048 + + + + + + +Mozilla Bug 1053048 +

      + + + + +
      +
      + + diff --git a/editor/libeditor/tests/test_bug1067255.html b/editor/libeditor/tests/test_bug1067255.html new file mode 100644 index 000000000..be2d703c5 --- /dev/null +++ b/editor/libeditor/tests/test_bug1067255.html @@ -0,0 +1,57 @@ + + + + + + + Test for Bug 1067255 + + + + + + + Mozilla Bug 1067255 + +
      +    
      +  
      + + + + + diff --git a/editor/libeditor/tests/test_bug1068979.html b/editor/libeditor/tests/test_bug1068979.html new file mode 100644 index 000000000..126c39d27 --- /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 000000000..cc27cc675 --- /dev/null +++ b/editor/libeditor/tests/test_bug1094000.html @@ -0,0 +1,104 @@ + + + + + Test for Bug 1094000 + + + + + +Mozilla Bug 1094000 +

      +
      +
      +

      +
      a
      +
      b
      +
      c
      +
      d
      +
      e
      +
      +
      +
      +
      + + diff --git a/editor/libeditor/tests/test_bug1100966.html b/editor/libeditor/tests/test_bug1100966.html new file mode 100644 index 000000000..28c30c849 --- /dev/null +++ b/editor/libeditor/tests/test_bug1100966.html @@ -0,0 +1,65 @@ + + + + + Test for Bug 1100966 + + + + + +
      +
      +
      +=====
      +correct
      +fivee sixx
      +==== +
      +
      +
      + + + + + diff --git a/editor/libeditor/tests/test_bug1101392.html b/editor/libeditor/tests/test_bug1101392.html new file mode 100644 index 000000000..76917203b --- /dev/null +++ b/editor/libeditor/tests/test_bug1101392.html @@ -0,0 +1,78 @@ + + + + + + Test for Bug 1101392 + + + + + +Mozilla Bug 1101392 +
      abc
      + + + +
      +
      + + diff --git a/editor/libeditor/tests/test_bug1102906.html b/editor/libeditor/tests/test_bug1102906.html new file mode 100644 index 000000000..36bfc8600 --- /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 000000000..dc31e9bf0 --- /dev/null +++ b/editor/libeditor/tests/test_bug1109465.html @@ -0,0 +1,69 @@ + + + + + Test for Bug 1109465 + + + + + +
      + +
      + +
      +
      + + + + + diff --git a/editor/libeditor/tests/test_bug1140105.html b/editor/libeditor/tests/test_bug1140105.html new file mode 100644 index 000000000..21d003054 --- /dev/null +++ b/editor/libeditor/tests/test_bug1140105.html @@ -0,0 +1,71 @@ + + + + + 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 000000000..078458a3a --- /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_bug1153237.html b/editor/libeditor/tests/test_bug1153237.html new file mode 100644 index 000000000..38d631326 --- /dev/null +++ b/editor/libeditor/tests/test_bug1153237.html @@ -0,0 +1,49 @@ + + + + + + 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 000000000..03b605e20 --- /dev/null +++ b/editor/libeditor/tests/test_bug1154791.html @@ -0,0 +1,67 @@ + + + + + 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 000000000..ad119de87 --- /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 000000000..eb27526a3 --- /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 000000000..edb380e98 --- /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 000000000..b0b583a7e --- /dev/null +++ b/editor/libeditor/tests/test_bug1186799.html @@ -0,0 +1,81 @@ + + + + + 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 000000000..bff7826d1 --- /dev/null +++ b/editor/libeditor/tests/test_bug1230473.html @@ -0,0 +1,124 @@ + + + + + + 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 000000000..40dbc36ce --- /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 000000000..08b0139c9 --- /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 000000000..d545cfc53 --- /dev/null +++ b/editor/libeditor/tests/test_bug1248185.html @@ -0,0 +1,57 @@ + + + + + + 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 000000000..d1e0154dc --- /dev/null +++ b/editor/libeditor/tests/test_bug1250010.html @@ -0,0 +1,93 @@ + + + + + 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 000000000..c1610494f --- /dev/null +++ b/editor/libeditor/tests/test_bug1257363.html @@ -0,0 +1,182 @@ + + + + + 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 000000000..342f068ee --- /dev/null +++ b/editor/libeditor/tests/test_bug1258085.html @@ -0,0 +1,66 @@ + +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 000000000..fb1f341b5 --- /dev/null +++ b/editor/libeditor/tests/test_bug1268736.html @@ -0,0 +1,64 @@ + + + + + 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 000000000..da7fd4e7a --- /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_bug1310912.html b/editor/libeditor/tests/test_bug1310912.html new file mode 100644 index 000000000..d73366a63 --- /dev/null +++ b/editor/libeditor/tests/test_bug1310912.html @@ -0,0 +1,93 @@ + + + + + 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 000000000..ff1487244 --- /dev/null +++ b/editor/libeditor/tests/test_bug1314790.html @@ -0,0 +1,65 @@ + + + + + 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 000000000..16f0de4e3 --- /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_bug1328023.html b/editor/libeditor/tests/test_bug1328023.html new file mode 100644 index 000000000..1b7fb7bf5 --- /dev/null +++ b/editor/libeditor/tests/test_bug1328023.html @@ -0,0 +1,64 @@ + + + + + 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 000000000..f8af02087 --- /dev/null +++ b/editor/libeditor/tests/test_bug1330796.html @@ -0,0 +1,101 @@ + + + + + + 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 000000000..76dfa0fc7 --- /dev/null +++ b/editor/libeditor/tests/test_bug1332876.html @@ -0,0 +1,49 @@ + + + + + + Test for Bug 1332876 + + + + + +Mozilla Bug 1332876 +

      + + + + +
      +
      +
      +
      +
      + + diff --git a/editor/libeditor/tests/test_bug200416.html b/editor/libeditor/tests/test_bug200416.html new file mode 100644 index 000000000..9fb656425 --- /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 000000000..1d55e0c3f --- /dev/null +++ b/editor/libeditor/tests/test_bug289384.html @@ -0,0 +1,49 @@ + + + + + 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 000000000..9e7686e72 --- /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 000000000..93f63af61 --- /dev/null +++ b/editor/libeditor/tests/test_bug291780.html @@ -0,0 +1,50 @@ + + + + + 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 000000000..85406905c --- /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 000000000..76d123815 --- /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 000000000..541653ab1 --- /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 000000000..5df386ac4 --- /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 000000000..e853d6cee --- /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_bug366682.html b/editor/libeditor/tests/test_bug366682.html new file mode 100644 index 000000000..bac618941 --- /dev/null +++ b/editor/libeditor/tests/test_bug366682.html @@ -0,0 +1,67 @@ + + + + + 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 000000000..e9b1ac7a9 --- /dev/null +++ b/editor/libeditor/tests/test_bug372345.html @@ -0,0 +1,59 @@ + + + + + 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 000000000..b8249a557 --- /dev/null +++ b/editor/libeditor/tests/test_bug404320.html @@ -0,0 +1,91 @@ + + + + + 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 000000000..d365bfa09 --- /dev/null +++ b/editor/libeditor/tests/test_bug408231.html @@ -0,0 +1,250 @@ + + + + + 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 000000000..a3f3a5602 --- /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 000000000..0975b6a5a --- /dev/null +++ b/editor/libeditor/tests/test_bug414526.html @@ -0,0 +1,247 @@ + + + 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 000000000..146de0920 --- /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_bug432225.html b/editor/libeditor/tests/test_bug432225.html new file mode 100644 index 000000000..58d158722 --- /dev/null +++ b/editor/libeditor/tests/test_bug432225.html @@ -0,0 +1,71 @@ + + + + + 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 000000000..a04d1d4d4 --- /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 000000000..eab81e055 --- /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 000000000..77a7c6a7d --- /dev/null +++ b/editor/libeditor/tests/test_bug449243.html @@ -0,0 +1,136 @@ + + + + + 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 000000000..daf362acf --- /dev/null +++ b/editor/libeditor/tests/test_bug455992.html @@ -0,0 +1,97 @@ + + +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 000000000..03cc2c9e3 --- /dev/null +++ b/editor/libeditor/tests/test_bug456244.html @@ -0,0 +1,70 @@ + + +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 000000000..b9e79c1e0 --- /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 000000000..3838bdb3b --- /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_bug468353.html b/editor/libeditor/tests/test_bug468353.html new file mode 100644 index 000000000..179c41cdc --- /dev/null +++ b/editor/libeditor/tests/test_bug468353.html @@ -0,0 +1,117 @@ + + + + + Test for Bug 468353 + + + + +Mozilla Bug 468353 +

      +
      + +
      +
      +
      +
      + + diff --git a/editor/libeditor/tests/test_bug471319.html b/editor/libeditor/tests/test_bug471319.html new file mode 100644 index 000000000..399ba4611 --- /dev/null +++ b/editor/libeditor/tests/test_bug471319.html @@ -0,0 +1,80 @@ + + + + + + + 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 000000000..74ff55307 --- /dev/null +++ b/editor/libeditor/tests/test_bug471722.html @@ -0,0 +1,81 @@ + + + + + + + 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 000000000..8df85dfff --- /dev/null +++ b/editor/libeditor/tests/test_bug478725.html @@ -0,0 +1,131 @@ + + +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 000000000..33f088a1b --- /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 000000000..3eed97100 --- /dev/null +++ b/editor/libeditor/tests/test_bug480972.html @@ -0,0 +1,98 @@ + + +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 000000000..ee256b807 --- /dev/null +++ b/editor/libeditor/tests/test_bug483651.html @@ -0,0 +1,53 @@ + + + + + + + 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 000000000..55cd8e806 --- /dev/null +++ b/editor/libeditor/tests/test_bug484181.html @@ -0,0 +1,78 @@ + + + + + Test for Bug 484181 + + + + + + +Mozilla Bug 484181 +

      + +
      +
      +
      + +
      I can haz cheezburger
      + + + diff --git a/editor/libeditor/tests/test_bug487524.html b/editor/libeditor/tests/test_bug487524.html new file mode 100644 index 000000000..d4972ba91 --- /dev/null +++ b/editor/libeditor/tests/test_bug487524.html @@ -0,0 +1,65 @@ + + +Test for bug 487524 + + + + + + + +Mozilla Bug 487524 +

      + +
      +
      + +
      + + + diff --git a/editor/libeditor/tests/test_bug489202.xul b/editor/libeditor/tests/test_bug489202.xul new file mode 100644 index 000000000..30e2a730d --- /dev/null +++ b/editor/libeditor/tests/test_bug489202.xul @@ -0,0 +1,81 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug490879.html b/editor/libeditor/tests/test_bug490879.html new file mode 100644 index 000000000..1e412a7d6 --- /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 000000000..3bee4554a --- /dev/null +++ b/editor/libeditor/tests/test_bug502673.html @@ -0,0 +1,108 @@ + + + + + + + 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 000000000..3594d1c8d --- /dev/null +++ b/editor/libeditor/tests/test_bug514156.html @@ -0,0 +1,50 @@ + + + + + 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 000000000..d1b429000 --- /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 000000000..43916eb51 --- /dev/null +++ b/editor/libeditor/tests/test_bug525389.html @@ -0,0 +1,198 @@ + + +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 000000000..6c3c07b29 --- /dev/null +++ b/editor/libeditor/tests/test_bug537046.html @@ -0,0 +1,51 @@ + + + + + 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 000000000..fa1cbabc4 --- /dev/null +++ b/editor/libeditor/tests/test_bug549262.html @@ -0,0 +1,132 @@ + + + + + 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 000000000..0fa3ad159 --- /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 000000000..8f335276f --- /dev/null +++ b/editor/libeditor/tests/test_bug551704.html @@ -0,0 +1,125 @@ + + + + + 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 000000000..5c53e92c1 --- /dev/null +++ b/editor/libeditor/tests/test_bug552782.html @@ -0,0 +1,47 @@ + + + + + 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 000000000..22418f9e2 --- /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 000000000..e42bbb985 --- /dev/null +++ b/editor/libeditor/tests/test_bug569988.html @@ -0,0 +1,99 @@ + + + + + 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 000000000..e3b98b8d6 --- /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 000000000..09f163c51 --- /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 000000000..36c56d759 --- /dev/null +++ b/editor/libeditor/tests/test_bug586662.html @@ -0,0 +1,60 @@ + + + + + + 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 000000000..2cf9f29fc --- /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 000000000..bc98503ed --- /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 000000000..834ecbe1d --- /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 000000000..c677df359 --- /dev/null +++ b/editor/libeditor/tests/test_bug596001.html @@ -0,0 +1,55 @@ + + + + + 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 000000000..a94726325 --- /dev/null +++ b/editor/libeditor/tests/test_bug596333.html @@ -0,0 +1,124 @@ + + + + + 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 000000000..0fc1adabf --- /dev/null +++ b/editor/libeditor/tests/test_bug596506.html @@ -0,0 +1,60 @@ + + + + + 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 000000000..f35413cb6 --- /dev/null +++ b/editor/libeditor/tests/test_bug597331.html @@ -0,0 +1,72 @@ + + + + + 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 000000000..321f2ad1c --- /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 000000000..578bcb11a --- /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 000000000..08fc9a228 --- /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.xul b/editor/libeditor/tests/test_bug599983.xul new file mode 100644 index 000000000..8b5d52a8c --- /dev/null +++ b/editor/libeditor/tests/test_bug599983.xul @@ -0,0 +1,70 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug600570.html b/editor/libeditor/tests/test_bug600570.html new file mode 100644 index 000000000..0a5a814f8 --- /dev/null +++ b/editor/libeditor/tests/test_bug600570.html @@ -0,0 +1,80 @@ + + + + + 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 000000000..a61e5c9c3 --- /dev/null +++ b/editor/libeditor/tests/test_bug602130.html @@ -0,0 +1,45 @@ + + + + + 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 000000000..0e0a70464 --- /dev/null +++ b/editor/libeditor/tests/test_bug603556.html @@ -0,0 +1,48 @@ + + + + + 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 000000000..519a179b1 --- /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 000000000..aa22b6f30 --- /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.xul b/editor/libeditor/tests/test_bug607584.xul new file mode 100644 index 000000000..fb16cee83 --- /dev/null +++ b/editor/libeditor/tests/test_bug607584.xul @@ -0,0 +1,115 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug611182.html b/editor/libeditor/tests/test_bug611182.html new file mode 100644 index 000000000..e6ecc6716 --- /dev/null +++ b/editor/libeditor/tests/test_bug611182.html @@ -0,0 +1,239 @@ + + + + + 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 000000000..b23d6f12a --- /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 000000000..b06739288 --- /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.xul b/editor/libeditor/tests/test_bug616590.xul new file mode 100644 index 000000000..57c29a028 --- /dev/null +++ b/editor/libeditor/tests/test_bug616590.xul @@ -0,0 +1,105 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug620906.html b/editor/libeditor/tests/test_bug620906.html new file mode 100644 index 000000000..208bdfd28 --- /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 000000000..d08ba8214 --- /dev/null +++ b/editor/libeditor/tests/test_bug622371.html @@ -0,0 +1,40 @@ + + + + + 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 000000000..e2292d753 --- /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_bug629845.html b/editor/libeditor/tests/test_bug629845.html new file mode 100644 index 000000000..9eb24f904 --- /dev/null +++ b/editor/libeditor/tests/test_bug629845.html @@ -0,0 +1,60 @@ + + + + + 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 000000000..e5bbb5322 --- /dev/null +++ b/editor/libeditor/tests/test_bug635636.html @@ -0,0 +1,65 @@ + + + + + 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 000000000..37ceebe5a --- /dev/null +++ b/editor/libeditor/tests/test_bug636465.html @@ -0,0 +1,54 @@ + +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 000000000..62ef103f0 --- /dev/null +++ b/editor/libeditor/tests/test_bug638596.html @@ -0,0 +1,37 @@ + + + + + Test for Bug 638596 + + + + + +Mozilla Bug 638596 +

      +
      + +
      +
      +
      +
      + + diff --git a/editor/libeditor/tests/test_bug640321.html b/editor/libeditor/tests/test_bug640321.html new file mode 100644 index 000000000..984ea295a --- /dev/null +++ b/editor/libeditor/tests/test_bug640321.html @@ -0,0 +1,190 @@ + + + + + Test for Bug 640321 + + + + + +Mozilla Bug 640321 +

      +
      + +
      +
      +
      +
      +
      + + diff --git a/editor/libeditor/tests/test_bug641466.html b/editor/libeditor/tests/test_bug641466.html new file mode 100644 index 000000000..4a77b0b89 --- /dev/null +++ b/editor/libeditor/tests/test_bug641466.html @@ -0,0 +1,46 @@ + + + + + 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 000000000..cdf799e56 --- /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 000000000..8a0e4a829 --- /dev/null +++ b/editor/libeditor/tests/test_bug646194.html @@ -0,0 +1,38 @@ + +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 000000000..8405d08ab --- /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 000000000..4ba65f507 --- /dev/null +++ b/editor/libeditor/tests/test_bug674770-1.html @@ -0,0 +1,86 @@ + + + + + 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 000000000..c69311e95 --- /dev/null +++ b/editor/libeditor/tests/test_bug674770-2.html @@ -0,0 +1,395 @@ + + + + + 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 000000000..5974b4aed --- /dev/null +++ b/editor/libeditor/tests/test_bug674861.html @@ -0,0 +1,185 @@ + + + + + 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 000000000..aa468fdc6 --- /dev/null +++ b/editor/libeditor/tests/test_bug676401.html @@ -0,0 +1,119 @@ + + + + + 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 000000000..8809c1ead --- /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 000000000..6debcfde7 --- /dev/null +++ b/editor/libeditor/tests/test_bug681229.html @@ -0,0 +1,51 @@ + + + + + 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 000000000..c1a856aae --- /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 000000000..6dfefd8db --- /dev/null +++ b/editor/libeditor/tests/test_bug692520.html @@ -0,0 +1,42 @@ + + + + + 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 000000000..463ff76dc --- /dev/null +++ b/editor/libeditor/tests/test_bug697842.html @@ -0,0 +1,117 @@ + + + + + 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 000000000..5096ede3c --- /dev/null +++ b/editor/libeditor/tests/test_bug725069.html @@ -0,0 +1,35 @@ + + + + + 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 000000000..3b81ce48b --- /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 000000000..a54aec7a2 --- /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 000000000..26c918241 --- /dev/null +++ b/editor/libeditor/tests/test_bug740784.html @@ -0,0 +1,48 @@ + + + + + + + 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 000000000..9ad41dd52 --- /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 000000000..5ca41a595 --- /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 000000000..9ef980b66 --- /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 000000000..0e65a88a7 --- /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 000000000..9a15dccd2 --- /dev/null +++ b/editor/libeditor/tests/test_bug772796.html @@ -0,0 +1,223 @@ + + + + + + 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 000000000..b0dc82755 --- /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 000000000..7c99b9ff5 --- /dev/null +++ b/editor/libeditor/tests/test_bug780035.html @@ -0,0 +1,22 @@ + + +Test for Bug 780035 + + + +Mozilla Bug 780035 +
      + diff --git a/editor/libeditor/tests/test_bug780908.xul b/editor/libeditor/tests/test_bug780908.xul new file mode 100644 index 000000000..312f02787 --- /dev/null +++ b/editor/libeditor/tests/test_bug780908.xul @@ -0,0 +1,113 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_bug787432.html b/editor/libeditor/tests/test_bug787432.html new file mode 100644 index 000000000..c73bb3c7e --- /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 000000000..d7685458b --- /dev/null +++ b/editor/libeditor/tests/test_bug790475.html @@ -0,0 +1,95 @@ + + + + + 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 000000000..3f44900ee --- /dev/null +++ b/editor/libeditor/tests/test_bug795418-2.html @@ -0,0 +1,88 @@ + + + + + + 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 000000000..bbe1a58b3 --- /dev/null +++ b/editor/libeditor/tests/test_bug795418-3.html @@ -0,0 +1,88 @@ + + + + + + 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 000000000..6c1ae05d1 --- /dev/null +++ b/editor/libeditor/tests/test_bug795418-4.html @@ -0,0 +1,67 @@ + + + + + + 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 000000000..5ff90b15a --- /dev/null +++ b/editor/libeditor/tests/test_bug795418-5.html @@ -0,0 +1,67 @@ + + + + + + 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 000000000..798a6534b --- /dev/null +++ b/editor/libeditor/tests/test_bug795418-6.html @@ -0,0 +1,67 @@ + + + + + + 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 000000000..1db8cf026 --- /dev/null +++ b/editor/libeditor/tests/test_bug795418.html @@ -0,0 +1,67 @@ + + + + + + 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 000000000..5f93d5142 --- /dev/null +++ b/editor/libeditor/tests/test_bug795785.html @@ -0,0 +1,168 @@ + + + + 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 000000000..be4be316c --- /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 000000000..39ced297a --- /dev/null +++ b/editor/libeditor/tests/test_bug830600.html @@ -0,0 +1,100 @@ + + + + + + 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 000000000..40f4f4734 --- /dev/null +++ b/editor/libeditor/tests/test_bug832025.html @@ -0,0 +1,42 @@ + + + + + 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 000000000..b811c86a6 --- /dev/null +++ b/editor/libeditor/tests/test_bug850043.html @@ -0,0 +1,65 @@ + + + + + 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 000000000..a3746d44c --- /dev/null +++ b/editor/libeditor/tests/test_bug857487.html @@ -0,0 +1,72 @@ + + + + + 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 000000000..46f841bbc --- /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 000000000..32968b310 --- /dev/null +++ b/editor/libeditor/tests/test_bug915962.html @@ -0,0 +1,100 @@ + + + + + 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 000000000..524b15d69 --- /dev/null +++ b/editor/libeditor/tests/test_bug966155.html @@ -0,0 +1,57 @@ + + + + + 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 000000000..3d0ec5fe3 --- /dev/null +++ b/editor/libeditor/tests/test_bug966552.html @@ -0,0 +1,45 @@ + + + + + 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 000000000..e3caa87fb --- /dev/null +++ b/editor/libeditor/tests/test_bug974309.html @@ -0,0 +1,78 @@ + + + + + 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 000000000..2d167f0bd --- /dev/null +++ b/editor/libeditor/tests/test_bug998188.html @@ -0,0 +1,52 @@ + + + + + Test for Bug 998188 + + + + + +Mozilla Bug 998188 +

      + +
      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 000000000..18b72ccd4 --- /dev/null +++ b/editor/libeditor/tests/test_composition_event_created_in_chrome.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + diff --git a/editor/libeditor/tests/test_contenteditable_focus.html b/editor/libeditor/tests/test_contenteditable_focus.html new file mode 100644 index 000000000..051ac7b2f --- /dev/null +++ b/editor/libeditor/tests/test_contenteditable_focus.html @@ -0,0 +1,209 @@ + + + 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 000000000..06b95fbb8 --- /dev/null +++ b/editor/libeditor/tests/test_contenteditable_text_input_handling.html @@ -0,0 +1,329 @@ + + + Test for text input event handling on contenteditable editor + + + + + +
      +

      static content

      +

      content editable

      +
      + +
      +
      + + + + + diff --git a/editor/libeditor/tests/test_css_chrome_load_access.html b/editor/libeditor/tests/test_css_chrome_load_access.html new file mode 100644 index 000000000..b6bb3fb46 --- /dev/null +++ b/editor/libeditor/tests/test_css_chrome_load_access.html @@ -0,0 +1,67 @@ + + + + + Test for Bug 1245681 + + + + +Mozilla Bug 1245681 +

      +
      + +
      +
      +
      +
      + + 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 000000000..d1716a228 --- /dev/null +++ b/editor/libeditor/tests/test_dom_input_event_on_htmleditor.html @@ -0,0 +1,182 @@ + + + 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 000000000..b1395e99c --- /dev/null +++ b/editor/libeditor/tests/test_dom_input_event_on_texteditor.html @@ -0,0 +1,140 @@ + + + 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 000000000..c992b7142 --- /dev/null +++ b/editor/libeditor/tests/test_dragdrop.html @@ -0,0 +1,178 @@ + + + + + + + + + + + + Some Text + + + +

      This is some editable text.

      +

      First letter Middle Last part

      + + + + 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 000000000..bfec290a5 --- /dev/null +++ b/editor/libeditor/tests/test_htmleditor_keyevent_handling.html @@ -0,0 +1,664 @@ + + + Test for key event handler of HTML editor + + + + + +
      +

      +
      + +
      +
      + + + + + 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 000000000..6875c5a33 --- /dev/null +++ b/editor/libeditor/tests/test_keypress_untrusted_event.html @@ -0,0 +1,99 @@ + + + + + Test for untrusted keypress events + + + + + +Mozilla Bug 622245 +

      +
      +
      +
      +
      +
      +
      +
      +
      + + 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 000000000..f8b6f4336 --- /dev/null +++ b/editor/libeditor/tests/test_root_element_replacement.html @@ -0,0 +1,148 @@ + + + Test for root element replacement + + + + + +

      +

      + +
      +
      + + + + + 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 000000000..d947400c4 --- /dev/null +++ b/editor/libeditor/tests/test_select_all_without_body.html @@ -0,0 +1,27 @@ + + + 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 000000000..e217f8fdf --- /dev/null +++ b/editor/libeditor/tests/test_selection_move_commands.html @@ -0,0 +1,219 @@ + +Test for nsSelectionMoveCommands + + + +Mozilla Bug 454004 + + + + diff --git a/editor/libeditor/tests/test_set_document_title_transaction.html b/editor/libeditor/tests/test_set_document_title_transaction.html new file mode 100644 index 000000000..d745d4f13 --- /dev/null +++ b/editor/libeditor/tests/test_set_document_title_transaction.html @@ -0,0 +1,79 @@ + + + + Test for SetDocumentTitleTransaction + + + + +
      + +
      + +
      +
      + + + + + diff --git a/editor/libeditor/tests/test_spellcheck_pref.html b/editor/libeditor/tests/test_spellcheck_pref.html new file mode 100644 index 000000000..9faff45f3 --- /dev/null +++ b/editor/libeditor/tests/test_spellcheck_pref.html @@ -0,0 +1,23 @@ + + + Test if spellcheck is turned on + + + + + + +
      +
      + + + + + 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 000000000..5c4a8d1c2 --- /dev/null +++ b/editor/libeditor/tests/test_texteditor_keyevent_handling.html @@ -0,0 +1,386 @@ + + + Test for key event handler of text editor + + + + + +
      + + + +
      + +
      +
      + + + + + -- cgit v1.2.3